soundwave/backend/audio/models_artwork.py

160 lines
5.1 KiB
Python
Raw Normal View History

"""Models for artwork and metadata"""
from django.db import models
from audio.models import Audio
from channel.models import Channel
class Artwork(models.Model):
"""Store artwork/cover art for audio and channels"""
ARTWORK_TYPE_CHOICES = [
('audio_thumbnail', 'Audio Thumbnail'),
('audio_cover', 'Audio Cover Art'),
('album_cover', 'Album Cover'),
('artist_image', 'Artist Image'),
('artist_banner', 'Artist Banner'),
('artist_logo', 'Artist Logo'),
]
SOURCE_CHOICES = [
('youtube', 'YouTube'),
('lastfm', 'Last.fm'),
('fanart', 'Fanart.tv'),
('manual', 'Manual Upload'),
]
# Related objects
audio = models.ForeignKey(
Audio,
on_delete=models.CASCADE,
related_name='artworks',
null=True,
blank=True
)
channel = models.ForeignKey(
Channel,
on_delete=models.CASCADE,
related_name='artworks',
null=True,
blank=True
)
# Artwork details
artwork_type = models.CharField(max_length=50, choices=ARTWORK_TYPE_CHOICES)
source = models.CharField(max_length=50, choices=SOURCE_CHOICES)
url = models.URLField(max_length=1000)
local_path = models.CharField(max_length=500, blank=True, default='')
# Image metadata
width = models.IntegerField(null=True, blank=True)
height = models.IntegerField(null=True, blank=True)
file_size = models.IntegerField(null=True, blank=True, help_text="Size in bytes")
# Priority for display (higher = preferred)
priority = models.IntegerField(default=0)
# Metadata
fetched_date = models.DateTimeField(auto_now_add=True)
is_primary = models.BooleanField(default=False)
class Meta:
ordering = ['-priority', '-fetched_date']
indexes = [
models.Index(fields=['audio', 'artwork_type']),
models.Index(fields=['channel', 'artwork_type']),
models.Index(fields=['is_primary']),
]
def __str__(self):
if self.audio:
return f"{self.artwork_type} for {self.audio.title} ({self.source})"
elif self.channel:
return f"{self.artwork_type} for {self.channel.channel_name} ({self.source})"
return f"{self.artwork_type} ({self.source})"
class MusicMetadata(models.Model):
"""Extended music metadata from Last.fm and other sources"""
audio = models.OneToOneField(
Audio,
on_delete=models.CASCADE,
related_name='music_metadata',
primary_key=True
)
# Album information
album_name = models.CharField(max_length=500, blank=True, default='')
album_artist = models.CharField(max_length=500, blank=True, default='')
release_year = models.IntegerField(null=True, blank=True)
# Track information
track_number = models.IntegerField(null=True, blank=True)
disc_number = models.IntegerField(null=True, blank=True)
# Additional metadata
genre = models.CharField(max_length=200, blank=True, default='')
tags = models.JSONField(default=list, blank=True) # List of tags
# Last.fm specific
lastfm_url = models.URLField(max_length=500, blank=True, default='')
lastfm_mbid = models.CharField(max_length=100, blank=True, default='', help_text="MusicBrainz ID")
play_count = models.IntegerField(default=0, help_text="Global play count from Last.fm")
listeners = models.IntegerField(default=0, help_text="Unique listeners from Last.fm")
# Fanart.tv IDs
fanart_artist_id = models.CharField(max_length=100, blank=True, default='')
fanart_album_id = models.CharField(max_length=100, blank=True, default='')
# Metadata status
metadata_fetched = models.BooleanField(default=False)
last_updated = models.DateTimeField(auto_now=True)
class Meta:
verbose_name_plural = "Music Metadata"
def __str__(self):
return f"Metadata for {self.audio.title}"
class ArtistInfo(models.Model):
"""Store artist/channel information from Last.fm and Fanart.tv"""
channel = models.OneToOneField(
Channel,
on_delete=models.CASCADE,
related_name='artist_info',
primary_key=True
)
# Basic info
bio = models.TextField(blank=True, default='')
bio_summary = models.TextField(blank=True, default='')
# Links
lastfm_url = models.URLField(max_length=500, blank=True, default='')
lastfm_mbid = models.CharField(max_length=100, blank=True, default='')
# Stats
lastfm_listeners = models.IntegerField(default=0)
lastfm_playcount = models.IntegerField(default=0)
# Tags/Genres
tags = models.JSONField(default=list, blank=True)
# Fanart.tv ID
fanart_id = models.CharField(max_length=100, blank=True, default='')
# Social links from Last.fm
similar_artists = models.JSONField(default=list, blank=True)
# Status
metadata_fetched = models.BooleanField(default=False)
last_updated = models.DateTimeField(auto_now=True)
class Meta:
verbose_name_plural = "Artist Info"
def __str__(self):
return f"Info for {self.channel.channel_name}"