Skip to content

Commit

Permalink
Merge pull request #450 from InterN0te/main-delete-files-on-disk
Browse files Browse the repository at this point in the history
Following Delete files on disk #426
  • Loading branch information
meeb authored Jan 17, 2024
2 parents e4e0b48 + 9c18115 commit e7788eb
Show file tree
Hide file tree
Showing 6 changed files with 59 additions and 19 deletions.
17 changes: 17 additions & 0 deletions tubesync/sync/migrations/0021_add_delete_files_on_disk.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Generated by pac

from django.db import migrations, models

class Migration(migrations.Migration):

dependencies = [
('sync', '0020_auto_20231024_1825'),
]

operations = [
migrations.AddField(
model_name='source',
name='delete_files_on_disk',
field=models.BooleanField(default=False, help_text='Delete files on disk when they are removed from TubeSync', verbose_name='delete files on disk'),
),
]
5 changes: 5 additions & 0 deletions tubesync/sync/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,11 @@ class IndexSchedule(models.IntegerChoices):
default=False,
help_text=_('Delete media that is no longer on this playlist')
)
delete_files_on_disk = models.BooleanField(
_('delete files on disk'),
default=False,
help_text=_('Delete files on disk when they are removed from TubeSync')
)
source_resolution = models.CharField(
_('source resolution'),
max_length=8,
Expand Down
12 changes: 12 additions & 0 deletions tubesync/sync/signals.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import os
import glob
from django.conf import settings
from django.db.models.signals import pre_save, post_save, pre_delete, post_delete
from django.dispatch import receiver
Expand Down Expand Up @@ -74,6 +75,7 @@ def source_pre_delete(sender, instance, **kwargs):
media.delete()



@receiver(post_delete, sender=Source)
def source_post_delete(sender, instance, **kwargs):
# Triggered after a source is deleted
Expand Down Expand Up @@ -222,6 +224,16 @@ def media_pre_delete(sender, instance, **kwargs):
if thumbnail_url:
delete_task_by_media('sync.tasks.download_media_thumbnail',
(str(instance.pk), thumbnail_url))
if instance.source.delete_files_on_disk and (instance.media_file or instance.thumb):
# Delete all media files if it contains filename
filepath = instance.media_file.path if instance.media_file else instance.thumb.path
barefilepath, fileext = os.path.splitext(filepath)
# Get all files that start with the bare file path
all_related_files = glob.glob(f'{barefilepath}.*')
for file in all_related_files:
log.info(f'Deleting file for: {instance} path: {file}')
delete_file(file)



@receiver(post_delete, sender=Media)
Expand Down
4 changes: 2 additions & 2 deletions tubesync/sync/templates/sync/source-delete.html
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ <h1>Delete source <strong>{{ source.name }}</strong></h1>
<p>
Are you sure you want to delete this source? Deleting a source is permanent.
By default, deleting a source does not delete any saved media files. You can
tick the &quot;also delete downloaded media&quot; checkbox to also remove save
media when you delete the source. Deleting a source cannot be undone.
<strong>tick the &quot;also delete downloaded media&quot; checkbox to also remove directory {{ source.directory_path }}
</strong>when you delete the source. Deleting a source cannot be undone.
</p>
</div>
</div>
Expand Down
4 changes: 4 additions & 0 deletions tubesync/sync/templates/sync/source.html
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,10 @@ <h1 class="truncate">Source <strong>{{ source.name }}</strong></h1>
<tr title="Delete media that is no longer on this playlist?">
<td class="hide-on-small-only">Delete removed media</td>
<td><span class="hide-on-med-and-up">Delete removed media<br></span><strong>{% if source.delete_removed_media %}<i class="fas fa-check"></i>{% else %}<i class="fas fa-times"></i>{% endif %}</strong></td>
</tr>
<tr title="Delete files on disk when they are removed from TubeSync?">
<td class="hide-on-small-only">Delete files on disk</td>
<td><span class="hide-on-med-and-up">Delete files on disk<br></span><strong>{% if source.delete_files_on_disk %}<i class="fas fa-check"></i>{% else %}<i class="fas fa-times"></i>{% endif %}</strong></td>
</tr>
{% if source.delete_old_media and source.days_to_keep > 0 %}
<tr title="Days after which your media from this source will be locally deleted">
Expand Down
36 changes: 19 additions & 17 deletions tubesync/sync/views.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import glob
import os
import json
from base64 import b64decode
import pathlib
import shutil
import sys
from django.conf import settings
from django.http import FileResponse, Http404, HttpResponseNotFound, HttpResponseRedirect
Expand Down Expand Up @@ -296,9 +298,9 @@ class EditSourceMixin:
model = Source
fields = ('source_type', 'key', 'name', 'directory', 'filter_text', 'media_format',
'index_schedule', 'download_media', 'download_cap', 'delete_old_media',
'delete_removed_media', 'days_to_keep', 'source_resolution', 'source_vcodec',
'source_acodec', 'prefer_60fps', 'prefer_hdr', 'fallback', 'copy_thumbnails',
'write_nfo', 'write_json', 'embed_metadata', 'embed_thumbnail',
'delete_removed_media', 'delete_files_on_disk', 'days_to_keep', 'source_resolution',
'source_vcodec', 'source_acodec', 'prefer_60fps', 'prefer_hdr', 'fallback',
'copy_thumbnails', 'write_nfo', 'write_json', 'embed_metadata', 'embed_thumbnail',
'enable_sponsorblock', 'sponsorblock_categories', 'write_subtitles',
'auto_subtitles', 'sub_langs')
errors = {
Expand Down Expand Up @@ -435,14 +437,13 @@ def post(self, request, *args, **kwargs):
source = self.get_object()
for media in Media.objects.filter(source=source):
if media.media_file:
# Delete the media file
delete_file(media.media_file.path)
# Delete thumbnail copy if it exists
delete_file(media.thumbpath)
# Delete NFO file if it exists
delete_file(media.nfopath)
# Delete JSON file if it exists
delete_file(media.jsonpath)
file_path = media.media_file.path
matching_files = glob.glob(os.path.splitext(file_path)[0] + '.*')
for file in matching_files:
delete_file(file)
directory_path = source.directory_path
if os.path.exists(directory_path):
shutil.rmtree(directory_path, True)
return super().post(request, *args, **kwargs)

def get_success_url(self):
Expand Down Expand Up @@ -653,12 +654,13 @@ def form_valid(self, form):
delete_task_by_media('sync.tasks.download_media', (str(self.object.pk),))
# If the media file exists on disk, delete it
if self.object.media_file_exists:
delete_file(self.object.media_file.path)
self.object.media_file = None
# If the media has an associated thumbnail copied, also delete it
delete_file(self.object.thumbpath)
# If the media has an associated NFO file with it, also delete it
delete_file(self.object.nfopath)
# Delete all files which contains filename
filepath = self.object.media_file.path
barefilepath, fileext = os.path.splitext(filepath)
# Get all files that start with the bare file path
all_related_files = glob.glob(f'{barefilepath}.*')
for file in all_related_files:
delete_file(file)
# Reset all download data
self.object.metadata = None
self.object.downloaded = False
Expand Down

0 comments on commit e7788eb

Please sign in to comment.