fix db insert duplicate unique fields error

+ save album date as timestamp in db
+ Rewrite artist image downloader with multiprocessing.Pool
This commit is contained in:
mungai-njoroge 2023-06-21 13:20:09 +03:00
parent 4d310c39c3
commit 88be80b25d
5 changed files with 37 additions and 33 deletions

View File

@ -115,7 +115,9 @@ def get_artist_albums():
albums = [ albums = [
{ {
"artisthash": a, "artisthash": a,
"albums": AlbumStore.get_albums_by_albumartist(a, limit, exclude=base_title), "albums": AlbumStore.get_albums_by_albumartist(
a, limit, exclude=base_title
),
} }
for a in albumartists for a in albumartists
] ]
@ -136,18 +138,17 @@ def get_album_versions():
if data is None: if data is None:
return {"msg": "No albumartist provided"} return {"msg": "No albumartist provided"}
og_album_title: str = data['og_album_title'] og_album_title: str = data["og_album_title"]
base_title: str = data['base_title'] base_title: str = data["base_title"]
artisthash: str = data['artisthash'] artisthash: str = data["artisthash"]
albums = AlbumStore.get_albums_by_artisthash(artisthash) albums = AlbumStore.get_albums_by_artisthash(artisthash)
albums = [ albums = [
a for a in albums a
if for a in albums
create_hash(a.base_title) == create_hash(base_title) and create_hash(og_album_title) != create_hash(a.og_title) if create_hash(a.base_title) == create_hash(base_title)
and create_hash(og_album_title) != create_hash(a.og_title)
] ]
return { return {"data": albums}
"data": albums
}

View File

@ -21,7 +21,7 @@ class SQLiteTrackMethods:
""" """
Inserts a single track into the database. Inserts a single track into the database.
""" """
sql = """INSERT INTO tracks( sql = """INSERT OR REPLACE INTO tracks(
album, album,
albumartist, albumartist,
albumhash, albumhash,

View File

@ -1,19 +1,19 @@
from concurrent.futures import ThreadPoolExecutor
from pathlib import Path
from io import BytesIO
from PIL import Image, UnidentifiedImageError
import requests
import urllib import urllib
from concurrent.futures import ProcessPoolExecutor as Pool
from io import BytesIO
from multiprocessing import Pool, cpu_count
from pathlib import Path
import requests
from PIL import Image, UnidentifiedImageError
from requests.exceptions import ConnectionError as ReqConnError
from requests.exceptions import ReadTimeout
from tqdm import tqdm from tqdm import tqdm
from requests.exceptions import ConnectionError as ReqConnError, ReadTimeout
from app import settings from app import settings
from app.models import Artist, Track, Album from app.models import Album, Artist, Track
from app.utils.hashing import create_hash
from app.store import artists as artist_store from app.store import artists as artist_store
from app.utils.hashing import create_hash
def get_artist_image_link(artist: str): def get_artist_image_link(artist: str):
@ -74,15 +74,17 @@ class DownloadImage:
class CheckArtistImages: class CheckArtistImages:
def __init__(self): def __init__(self):
with ThreadPoolExecutor() as pool: with Pool(cpu_count()) as pool:
list( res = list(
tqdm( tqdm(
pool.map(self.download_image, artist_store.ArtistStore.artists), pool.imap_unordered(self.download_image, artist_store.ArtistStore.artists),
total=len(artist_store.ArtistStore.artists), total=len(artist_store.ArtistStore.artists),
desc="Downloading missing artist images", desc="Downloading missing artist images",
) )
) )
list(res)
@staticmethod @staticmethod
def download_image(artist: Artist): def download_image(artist: Artist):
""" """
@ -90,7 +92,9 @@ class CheckArtistImages:
:param artist: The artist name :param artist: The artist name
""" """
img_path = Path(settings.Paths.get_artist_img_sm_path()) / f"{artist.artisthash}.webp" img_path = (
Path(settings.Paths.get_artist_img_sm_path()) / f"{artist.artisthash}.webp"
)
if img_path.exists(): if img_path.exists():
return return
@ -155,9 +159,7 @@ def get_albumartists(albums: list[Album]) -> set[str]:
return artists return artists
def get_all_artists( def get_all_artists(tracks: list[Track], albums: list[Album]) -> list[Artist]:
tracks: list[Track], albums: list[Album]
) -> list[Artist]:
artists_from_tracks = get_artists_from_tracks(tracks=tracks) artists_from_tracks = get_artists_from_tracks(tracks=tracks)
artist_from_albums = get_albumartists(albums=albums) artist_from_albums = get_albumartists(albums=albums)

View File

@ -1,6 +1,7 @@
import datetime import datetime
import os import os
from io import BytesIO from io import BytesIO
import pendulum
from PIL import Image, UnidentifiedImageError from PIL import Image, UnidentifiedImageError
from tinytag import TinyTag from tinytag import TinyTag
@ -64,11 +65,12 @@ def extract_thumb(filepath: str, webp_path: str) -> bool:
return False return False
def extract_date(date_str: str | None, timestamp: float) -> int: def extract_date(date_str: str | None) -> int | None:
try: try:
return int(date_str.split("-")[0]) date = pendulum.parse(date_str, strict=False)
return int(date.timestamp())
except Exception as e: except Exception as e:
return datetime.datetime.fromtimestamp(timestamp).year return None
def get_tags(filepath: str): def get_tags(filepath: str):
@ -141,7 +143,7 @@ def get_tags(filepath: str):
tags.image = f"{tags.albumhash}.webp" tags.image = f"{tags.albumhash}.webp"
tags.folder = win_replace_slash(os.path.dirname(filepath)) tags.folder = win_replace_slash(os.path.dirname(filepath))
tags.date = extract_date(tags.year, last_mod) tags.date = extract_date(tags.year) or int(last_mod)
tags.filepath = win_replace_slash(filepath) tags.filepath = win_replace_slash(filepath)
tags.filetype = filetype tags.filetype = filetype
tags.last_mod = last_mod tags.last_mod = last_mod

View File

@ -131,7 +131,6 @@ def add_track(filepath: str) -> None:
""" """
# remove the track if it already exists # remove the track if it already exists
TrackStore.remove_track_by_filepath(filepath) TrackStore.remove_track_by_filepath(filepath)
db.remove_tracks_by_filepaths(filepath)
# add the track to the database and store. # add the track to the database and store.
tags = get_tags(filepath) tags = get_tags(filepath)