Skip to content

Commit 9375bba

Browse files
authored
Merge pull request #598 from tcely/patch-3
Remove files in post_delete when Media is deleted
2 parents 157f5aa + 5dc3cc2 commit 9375bba

File tree

1 file changed

+55
-9
lines changed

1 file changed

+55
-9
lines changed

tubesync/sync/signals.py

Lines changed: 55 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import os
22
import glob
3+
from pathlib import Path
34
from django.conf import settings
45
from django.db.models.signals import pre_save, post_save, pre_delete, post_delete
56
from django.dispatch import receiver
@@ -14,7 +15,7 @@
1415
download_media, rescan_media_server, download_source_images,
1516
save_all_media_for_source, rename_all_media_for_source,
1617
get_media_metadata_task)
17-
from .utils import delete_file
18+
from .utils import delete_file, glob_quote
1819
from .filtering import filter_media
1920

2021

@@ -208,19 +209,63 @@ def media_pre_delete(sender, instance, **kwargs):
208209
if thumbnail_url:
209210
delete_task_by_media('sync.tasks.download_media_thumbnail',
210211
(str(instance.pk), thumbnail_url))
211-
if instance.source.delete_files_on_disk and (instance.media_file or instance.thumb):
212-
# Delete all media files if it contains filename
213-
filepath = instance.media_file.path if instance.media_file else instance.thumb.path
214-
barefilepath, fileext = os.path.splitext(filepath)
212+
213+
214+
@receiver(post_delete, sender=Media)
215+
def media_post_delete(sender, instance, **kwargs):
216+
# Remove thumbnail file for deleted media
217+
if instance.thumb:
218+
instance.thumb.delete(save=False)
219+
# Remove the video file, when configured to do so
220+
if instance.source.delete_files_on_disk and instance.media_file:
221+
video_path = Path(str(instance.media_file.path)).resolve()
222+
instance.media_file.delete(save=False)
223+
# the other files we created have these known suffixes
224+
for suffix in frozenset(('nfo', 'jpg', 'webp', 'info.json',)):
225+
other_path = video_path.with_suffix(f'.{suffix}').resolve()
226+
log.info(f'Deleting file for: {instance} path: {other_path!s}')
227+
delete_file(other_path)
228+
# Jellyfin creates .trickplay directories and posters
229+
for suffix in frozenset(('.trickplay', '-poster.jpg', '-poster.webp',)):
230+
# with_suffix insists on suffix beginning with '.' for no good reason
231+
other_path = Path(str(video_path.with_suffix('')) + suffix).resolve()
232+
if other_path.is_file():
233+
log.info(f'Deleting file for: {instance} path: {other_path!s}')
234+
delete_file(other_path)
235+
elif other_path.is_dir():
236+
# Delete the contents of the directory
237+
paths = list(other_path.rglob('*'))
238+
attempts = len(paths)
239+
while paths and attempts > 0:
240+
attempts -= 1
241+
# delete files first
242+
for p in list(filter(lambda x: x.is_file(), paths)):
243+
log.info(f'Deleting file for: {instance} path: {p!s}')
244+
delete_file(p)
245+
# refresh the list
246+
paths = list(other_path.rglob('*'))
247+
# delete directories
248+
# a directory with a subdirectory will fail
249+
# we loop to try removing each of them
250+
# a/b/c: c then b then a, 3 times around the loop
251+
for p in list(filter(lambda x: x.is_dir(), paths)):
252+
try:
253+
p.rmdir()
254+
log.info(f'Deleted directory for: {instance} path: {p!s}')
255+
except OSError as e:
256+
pass
257+
# Delete the directory itself
258+
try:
259+
other_path.rmdir()
260+
log.info(f'Deleted directory for: {instance} path: {other_path!s}')
261+
except OSError as e:
262+
pass
215263
# Get all files that start with the bare file path
216-
all_related_files = glob.glob(f'{barefilepath}.*')
264+
all_related_files = video_path.parent.glob(f'{glob_quote(video_path.with_suffix("").name)}*')
217265
for file in all_related_files:
218266
log.info(f'Deleting file for: {instance} path: {file}')
219267
delete_file(file)
220268

221-
222-
@receiver(post_delete, sender=Media)
223-
def media_post_delete(sender, instance, **kwargs):
224269
# Schedule a task to update media servers
225270
for mediaserver in MediaServer.objects.all():
226271
log.info(f'Scheduling media server updates')
@@ -231,3 +276,4 @@ def media_post_delete(sender, instance, **kwargs):
231276
verbose_name=verbose_name.format(mediaserver),
232277
remove_existing_tasks=True
233278
)
279+

0 commit comments

Comments
 (0)