feat: add playlist models

This commit is contained in:
NiceAesth 2024-02-23 17:54:09 +02:00
parent 33a728f8ec
commit b719fa461c
5 changed files with 200 additions and 2 deletions

View File

@ -2,6 +2,8 @@ import pydantic
from pydantic import ConfigDict
from .events import *
from .music import *
from .payloads import *
from .version import *

136
pomice/models/music.py Normal file
View File

@ -0,0 +1,136 @@
from __future__ import annotations
from typing import List
from typing import Optional
from discord.ext.commands import Context
from discord.user import _UserTag
from pydantic import Field
from pydantic import model_validator
from pomice.enums import PlaylistType
from pomice.enums import SearchType
from pomice.enums import TrackType
from pomice.filters import Filter
from pomice.models import BaseModel
__all__ = (
"Track",
"TrackInfo",
)
class TrackInfo(BaseModel):
identifier: str
title: str
author: str
length: int
position: int = 0
is_stream: bool = Field(default=False, alias="isStream")
is_seekable: bool = Field(default=False, alias="isSeekable")
uri: Optional[str] = None
isrc: Optional[str] = None
source_name: Optional[str] = Field(default=None, alias="sourceName")
artwork_url: Optional[str] = Field(default=None, alias="artworkUrl")
class Track(BaseModel):
"""The base track object. Returns critical track information needed for parsing by Lavalink.
You can also pass in commands.Context to get a discord.py Context object in your track.
"""
track_id: str = Field(alias="encoded")
track_type: TrackType
info: TrackInfo
search_type: SearchType = SearchType.YTSEARCH
filters: List[Filter] = Field(default_factory=list)
timestamp: Optional[float] = None
original: Optional[Track] = None
ctx: Optional[Context] = None
requester: Optional[_UserTag] = None
@property
def title(self) -> str:
return self.info.title
@property
def author(self) -> str:
return self.info.author
@property
def uri(self) -> Optional[str]:
return self.info.uri
@property
def identifier(self) -> str:
return self.info.identifier
@property
def isrc(self) -> Optional[str]:
return self.info.isrc
@property
def thumbnail(self) -> Optional[str]:
return self.info.artwork_url
def __eq__(self, other: object) -> bool:
if not isinstance(other, Track):
return False
return self.track_id == other.track_id
def __str__(self) -> str:
return self.info.title
def __repr__(self) -> str:
return f"<Pomice.Track title={self.info.title!r} uri=<{self.info.uri!r}> length={self.info.length}>"
@model_validator(mode="after")
def _set_thumbnail_url(self) -> Track:
if self.track_type is TrackType.YOUTUBE and not self.info.artwork_url:
self.info.artwork_url = (
f"https://img.youtube.com/vi/{self.info.identifier}/mqdefault.jpg"
)
return self
class PlaylistInfo(BaseModel):
name: str
selected_track: int = Field(default=0, alias="selectedTrack")
class Playlist(BaseModel):
"""The base playlist object.
Returns critical playlist information needed for parsing by Lavalink.
"""
info: PlaylistInfo
tracks: List[Track]
playlist_type: PlaylistType
uri: str
artwork_url: Optional[str] = None
@property
def name(self) -> str:
return self.info.name
@property
def thumbnail(self) -> Optional[str]:
return self.artwork_url
@property
def selected_track(self) -> Optional[Track]:
if self.track_count <= 0:
return None
return self.tracks[self.info.selected_track]
@property
def track_count(self) -> int:
return len(self.tracks)
def __str__(self) -> str:
return self.info.name
def __repr__(self) -> str:
return f"<Pomice.Playlist name={self.info.name!r} total_tracks={self.track_count}>"

View File

@ -8,7 +8,13 @@ from pomice.models import LavalinkVersion
from pomice.models import LavalinkVersion3Type
from pomice.models import LavalinkVersion4Type
__all__ = ("ResumePayload", "ResumePayloadV3", "ResumePayloadV4")
__all__ = (
"ResumePayload",
"ResumePayloadV3",
"ResumePayloadV4",
"ResumePayloadType",
"ResumePayloadTypeAdapter",
)
class ResumePayload(BaseModel):

View File

@ -1,4 +1,5 @@
"""Spotify module for Pomice, made possible by cloudwithax 2023"""
from .client import Client
from .client import *
from .exceptions import *
from .models import *
from .objects import *

53
pomice/spotify/models.py Normal file
View File

@ -0,0 +1,53 @@
from typing import Dict
from typing import List
from typing import Optional
from discord.ext.commands import Context
from discord.user import _UserTag
from pydantic import Field
from pomice.enums import SearchType
from pomice.enums import TrackType
from pomice.filters import Filter
from pomice.models import BaseModel
from pomice.models.music import Track
from pomice.models.music import TrackInfo
class SpotifyTrackRaw(BaseModel):
id: str
name: str
artists: List[Dict[str, str]]
duration_ms: float
external_ids: Dict[str, str] = Field(default_factory=dict)
external_urls: Dict[str, str] = Field(default_factory=dict)
album: Dict[str, List[Dict[str, str]]] = Field(default_factory=dict)
def build_track(
self,
image: Optional[str] = None,
filters: Optional[List[Filter]] = None,
ctx: Optional[Context] = None,
requester: Optional[_UserTag] = None,
) -> Track:
if self.album:
image = self.album["images"][0]["url"]
return Track(
track_id=self.id,
track_type=TrackType.SPOTIFY,
search_type=SearchType.YTMSEARCH,
filters=filters,
ctx=ctx,
requester=requester,
info=TrackInfo(
identifier=self.id,
title=self.name,
author=", ".join(artist["name"] for artist in self.artists),
length=self.duration_ms,
is_seekable=True,
uri=self.external_urls.get("spotify", ""),
artwork_url=image,
isrc=self.external_ids.get("isrc"),
),
)