Files
music-tag-web/applications/task/tasks.py
2023-05-17 09:37:54 +08:00

237 lines
8.0 KiB
Python

import datetime
import os
import time
import uuid
from django.conf import settings
from django.db import transaction
from applications.music.models import Folder, Track, Album, Genre, Artist, Attachment
from applications.subsonic.constants import AUDIO_EXTENSIONS_AND_MIMETYPE, COVER_TYPE
from applications.task.services.scan_utils import ScanMusic
from applications.task.utils import folder_update_time, exists_dir
from django_vue_cli.celery_app import app
def get_uuid():
return str(uuid.uuid4())
@app.task
def full_scan_folder(sub_path=None):
a = time.time()
bulk_create = []
music_folder = os.path.join(settings.MEDIA_ROOT, "music")
ignore_path = [os.path.join(music_folder, "data")]
if sub_path:
stack = sub_path
else:
stack = [(None, music_folder)]
while len(stack) != 0:
# 从栈里取出数据
parent_uid, dir_data = stack.pop()
if os.path.isdir(dir_data):
if dir_data in ignore_path:
continue
try:
entries = os.scandir(dir_data)
my_uuid = get_uuid()
except Exception as e:
m = f"Error while reading {dir}: {e.__class__.__name__} {e}\n"
print(m)
continue
try:
sub_path = [(my_uuid, entry.path) for entry in entries]
except Exception as e:
m = f"Error2 while reading {dir}: {e.__class__.__name__} {e}\n"
print(m)
continue
finally:
if hasattr(entries, "close"):
entries.close()
# stack.extend(sub_path)
if sub_path:
full_scan_folder.delay(sub_path=sub_path)
bulk_create.append(
Folder(**{
"name": dir_data.split("/")[-1],
"path": dir_data,
"file_type": "folder",
"uid": my_uuid,
"parent_id": parent_uid
})
)
else:
suffix = dir_data.split(".")[-1]
if suffix in dict(AUDIO_EXTENSIONS_AND_MIMETYPE):
my_uuid = get_uuid()
bulk_create.append(
Folder(**{
"name": dir_data.split("/")[-1],
"path": dir_data,
"file_type": "music",
"uid": my_uuid,
"parent_id": parent_uid
})
)
elif suffix in COVER_TYPE:
my_uuid = get_uuid()
bulk_create.append(
Folder(**{
"name": dir_data.split("/")[-1],
"path": dir_data,
"file_type": "image",
"uid": my_uuid,
"parent_id": parent_uid
})
)
if len(bulk_create) % 500 == 0:
Folder.objects.bulk_create(bulk_create, batch_size=500)
bulk_create = []
if len(bulk_create) > 0:
Folder.objects.bulk_create(bulk_create, batch_size=500)
print("完成扫描!", time.time() - a)
@app.task
def update_scan_folder(sub_path=None):
music_folder = os.path.join(settings.MEDIA_ROOT, "music")
ignore_path = [os.path.join(music_folder, "data")]
print(music_folder)
if sub_path:
stack = sub_path
else:
stack = [(None, music_folder)]
last_folder = Folder.objects.order_by("-last_scan_time").first()
if last_folder:
last_scan_time = last_folder.last_scan_time
else:
last_scan_time = datetime.datetime(1970, 1, 1)
now_time = datetime.datetime.now()
while len(stack) != 0:
# 从栈里取出数据
parent_uid, dir_data = stack.pop(0)
if dir_data in ignore_path:
continue
if os.path.isdir(dir_data):
try:
sub_path = os.scandir(dir_data)
except Exception as e:
m = f"Error3 while reading {dir}: {e.__class__.__name__} {e}\n"
print(m)
continue
update_time = folder_update_time(dir_data)
if update_time < last_scan_time:
try:
sub_path_list = [i.path for i in sub_path]
except Exception as e:
m = f"Error4 while reading {dir}: {e.__class__.__name__} {e}\n"
print(m)
continue
finally:
if hasattr(sub_path, "close"):
sub_path.close()
if not exists_dir(sub_path_list):
continue
current_folder = Folder.objects.filter(path=dir_data).first()
if current_folder:
my_uuid = current_folder.uid
update_data = {
"name": dir_data.split("/")[-1],
"file_type": "folder",
"uid": my_uuid,
"parent_id": parent_uid,
"updated_at": now_time,
}
else:
my_uuid = get_uuid()
update_data = {
"name": dir_data.split("/")[-1],
"file_type": "folder",
"uid": my_uuid,
"parent_id": parent_uid,
"updated_at": now_time,
}
Folder.objects.update_or_create(path=dir_data, defaults=update_data)
try:
sub_path = [(my_uuid, f"{dir_data}/{i}") for i in sub_path]
except Exception as e:
m = f"Error5 while reading {dir}: {e.__class__.__name__} {e}\n"
print(m)
continue
finally:
if hasattr(sub_path, "close"):
sub_path.close()
# stack.extend(sub_path)
if sub_path:
update_scan_folder.delay(sub_path)
else:
suffix = dir_data.split(".")[-1]
if suffix in dict(AUDIO_EXTENSIONS_AND_MIMETYPE):
print(dir_data)
my_uuid = get_uuid()
update_data = {
"name": dir_data.split("/")[-1],
"file_type": "music",
"uid": my_uuid,
"parent_id": parent_uid,
"updated_at": now_time,
"state": "updated"
}
elif suffix in COVER_TYPE:
my_uuid = get_uuid()
update_data = {
"name": dir_data.split("/")[-1],
"file_type": "image",
"uid": my_uuid,
"parent_id": parent_uid,
"updated_at": now_time,
"state": "updated"
}
else:
continue
Folder.objects.update_or_create(path=dir_data, defaults=update_data)
folder_lst = Folder.objects.filter(updated_at=now_time, file_type="folder")
for folder in folder_lst:
path_list = list(
Folder.objects.filter(parent_id=folder.uid).exclude(updated_at=now_time).values_list("path", flat=True))
with transaction.atomic():
Track.objects.filter(path__in=path_list).delete()
Folder.objects.filter(parent_id=folder.uid).exclude(updated_at=now_time).delete()
print("完成更新扫描!")
@app.task
def scan_folder():
if Folder.objects.count() > 0:
update_scan_folder()
else:
full_scan_folder()
@app.task
def scan_music_id3():
a = time.time()
ScanMusic("/").scan()
print(time.time() - a)
@app.task
def scan():
if Folder.objects.count() > 0:
update_scan_folder()
else:
full_scan_folder()
ScanMusic("/").scan()
def clear_music():
Folder.objects.all().delete()
Track.objects.all().delete()
Album.objects.all().delete()
Genre.objects.all().delete()
Artist.objects.all().delete()
Attachment.objects.all().delete()