packages feed

spotify-0.1.0.0: types/Spotify/Types/Misc.hs

{- HLINT ignore "Use newtype instead of data" -}
{-# LANGUAGE UndecidableInstances #-}

module Spotify.Types.Misc where

import Spotify.Types.Internal.CustomJSON
import Spotify.Types.Internal.EnumJSON

import Data.Aeson (FromJSON, ToJSON)
import Data.List.Extra (enumerate)
import Data.Map (Map)
import Data.Proxy (Proxy (Proxy))
import Data.Set qualified as Set
import Data.String (IsString)
import Data.Text (Text)
import Data.Text qualified as T
import GHC.Generics (Generic)
import GHC.Records (HasField)
import GHC.TypeLits (KnownSymbol, Symbol, symbolVal)
import Servant.API (ToHttpApiData)

data Copyright = Copyright
    { text :: Text
    , type_ :: CopyrightType
    }
    deriving (Eq, Ord, Show, Generic)
    deriving (FromJSON) via CustomJSON Copyright

data CopyrightType
    = C
    | P
    deriving (Eq, Ord, Show, Generic)
    deriving (FromJSON)

data Error = Error
    { status :: HTTPError
    , message :: Text
    }
    deriving (Eq, Ord, Show, Generic)
    deriving (FromJSON) via CustomJSON Error

data Followers = Followers
    { href :: Maybe Text
    , total :: Int
    }
    deriving (Eq, Ord, Show, Generic)
    deriving (FromJSON) via CustomJSON Followers

data Image = Image
    { height :: Maybe Int
    , url :: Text
    , width :: Maybe Int
    }
    deriving (Eq, Ord, Show, Generic)
    deriving (FromJSON) via CustomJSON Image

data Paging a = Paging
    { href :: Href
    , items :: [a]
    , limit :: Int
    , next :: Maybe Text
    , offset :: Int
    , previous :: Maybe Text
    , total :: Int
    }
    deriving (Eq, Ord, Show, Generic)
    deriving (FromJSON) via CustomJSON (Paging a)

data Tracks = Tracks
    { href :: Maybe Text
    , total :: Int
    }
    deriving (Eq, Ord, Show, Generic)
    deriving (FromJSON) via CustomJSON Tracks

data DatePrecision
    = DatePrecisionYear
    | DatePrecisionMonth
    | DatePrecisionDay
    deriving (Eq, Ord, Show, Generic)
    deriving (FromJSON) via CustomJSON DatePrecision

data Key
    = KeyC
    | KeyCSharp
    | KeyD
    | KeyDSharp
    | KeyE
    | KeyF
    | KeyFSharp
    | KeyG
    | KeyGSharp
    | KeyA
    | KeyASharp
    | KeyB
    deriving (Eq, Ord, Show, Generic, Enum)
    deriving (FromJSON) via EnumJSON Key

data TrackLink = TrackLink
    { externalUrls :: ExternalURLs
    , href :: Href
    , id :: TrackID
    , url :: Maybe Text
    }
    deriving (Eq, Ord, Show, Generic)
    deriving (FromJSON) via CustomJSON TrackLink

data AlbumGroup
    = GroupAlbum
    | GroupSingle
    | GroupCompilation
    | AppearsOn
    deriving (Eq, Ord, Show, Generic)
    deriving (FromJSON) via CustomJSON AlbumGroup

data AlbumType
    = AlbumTypeAlbum
    | AlbumTypeSingle
    | AlbumTypeCompilation
    deriving (Eq, Ord, Show, Generic)
    deriving (FromJSON) via CustomJSON AlbumType

data ExplicitContent = ExplicitContent
    { filterEnabled :: Bool
    , filterLocked :: Bool
    }
    deriving (Eq, Ord, Show, Generic)
    deriving (FromJSON) via CustomJSON ExplicitContent

data Product
    = Premium
    | Free
    deriving (Eq, Ord, Show, Generic)
    deriving (FromJSON) via CustomJSON Product

data Offset = Offset
    { position :: Int
    , uri :: Maybe URI
    }
    deriving (Eq, Ord, Show, Generic)
    deriving (ToJSON)

newtype Market = Market {unwrap :: Text}
    deriving newtype (Eq, Ord, Show, ToHttpApiData, IsString)

newtype Genre = Genre {unwrap :: Text}
    deriving newtype (Eq, Ord, Show, FromJSON, IsString)

newtype Href = Href {unwrap :: Text}
    deriving newtype (Eq, Ord, Show, FromJSON, IsString)

class ToURI a where
    toURI :: a -> URI
newtype URIPrefix (s :: Symbol) a = URIPrefix a
instance (KnownSymbol s, HasField "unwrap" a Text) => ToURI (URIPrefix s a) where
    toURI (URIPrefix x) = URI $ "spotify:" <> T.pack (symbolVal (Proxy @s)) <> ":" <> x.unwrap
newtype DeviceID = DeviceID {unwrap :: Text}
    deriving newtype (Eq, Ord, Show, FromJSON, ToJSON, ToHttpApiData, IsString)
newtype AlbumID = AlbumID {unwrap :: Text}
    deriving newtype (Eq, Ord, Show, FromJSON, ToJSON, ToHttpApiData, IsString)
    deriving (ToURI) via URIPrefix "album" AlbumID
newtype ArtistID = ArtistID {unwrap :: Text}
    deriving newtype (Eq, Ord, Show, FromJSON, ToJSON, ToHttpApiData, IsString)
    deriving (ToURI) via URIPrefix "artist" ArtistID
newtype EpisodeID = EpisodeID {unwrap :: Text}
    deriving newtype (Eq, Ord, Show, FromJSON, ToJSON, ToHttpApiData, IsString)
    deriving (ToURI) via URIPrefix "episode" EpisodeID
newtype TrackID = TrackID {unwrap :: Text}
    deriving newtype (Eq, Ord, Show, FromJSON, ToJSON, ToHttpApiData, IsString)
    deriving (ToURI) via URIPrefix "track" TrackID
newtype UserID = UserID {unwrap :: Text}
    deriving newtype (Eq, Ord, Show, FromJSON, ToJSON, ToHttpApiData, IsString)
    deriving (ToURI) via URIPrefix "user" UserID
newtype PlaylistID = PlaylistID {unwrap :: Text}
    deriving newtype (Eq, Ord, Show, FromJSON, ToJSON, ToHttpApiData, IsString)
    deriving (ToURI) via URIPrefix "playlist" PlaylistID
newtype CategoryID = CategoryID {unwrap :: Text}
    deriving newtype (Eq, Ord, Show, FromJSON, ToJSON, ToHttpApiData, IsString)
newtype SnapshotID = SnapshotID {unwrap :: Text}
    deriving newtype (Eq, Ord, Show, FromJSON, ToJSON, ToHttpApiData, IsString)

newtype URL = URL {unwrap :: Text}
    deriving newtype (Eq, Ord, Show, FromJSON, IsString, ToHttpApiData)

newtype URI = URI {unwrap :: Text}
    deriving newtype (Eq, Ord, Show, FromJSON, ToJSON, IsString)

newtype Country = Country {unwrap :: Text}
    deriving newtype (Eq, Ord, Show, FromJSON, ToJSON, ToHttpApiData, IsString)

newtype Locale = Locale {unwrap :: Text}
    deriving newtype (Eq, Ord, Show, FromJSON, ToJSON, ToHttpApiData, IsString)

newtype HTTPError = HTTPError {unwrap :: Int}
    deriving (Show)
    deriving newtype (Eq, Ord, FromJSON)

newtype Restrictions = Restrictions {unwrap :: Map Text Text}
    deriving (Show)
    deriving newtype (Eq, Ord, FromJSON)

newtype ExternalIDs = ExternalIDs {unwrap :: Map Text Text}
    deriving (Show)
    deriving newtype (Eq, Ord, FromJSON)

newtype ExternalURLs = ExternalURLs {unwrap :: Map Text Text}
    deriving (Show)
    deriving newtype (Eq, Ord, FromJSON)

data Scope
    = UgcImageUpload
    | UserModifyPlaybackState
    | UserReadPlaybackState
    | UserReadCurrentlyPlaying
    | UserFollowModify
    | UserFollowRead
    | UserReadRecentlyPlayed
    | UserReadPlaybackPosition
    | UserTopRead
    | PlaylistReadCollaborative
    | PlaylistModifyPublic
    | PlaylistReadPrivate
    | PlaylistModifyPrivate
    | AppRemoteControl
    | Streaming
    | UserReadEmail
    | UserReadPrivate
    | UserLibraryModify
    | UserLibraryRead
    deriving (Eq, Ord, Show, Enum, Bounded)
allScopes :: Set.Set Scope
allScopes = Set.fromList enumerate
showScope :: Scope -> Text
showScope = \case
    UgcImageUpload -> "ugc-image-upload"
    UserModifyPlaybackState -> "user-modify-playback-state"
    UserReadPlaybackState -> "user-read-playback-state"
    UserReadCurrentlyPlaying -> "user-read-currently-playing"
    UserFollowModify -> "user-follow-modify"
    UserFollowRead -> "user-follow-read"
    UserReadRecentlyPlayed -> "user-read-recently-played"
    UserReadPlaybackPosition -> "user-read-playback-position"
    UserTopRead -> "user-top-read"
    PlaylistReadCollaborative -> "playlist-read-collaborative"
    PlaylistModifyPublic -> "playlist-modify-public"
    PlaylistReadPrivate -> "playlist-read-private"
    PlaylistModifyPrivate -> "playlist-modify-private"
    AppRemoteControl -> "app-remote-control"
    Streaming -> "streaming"
    UserReadEmail -> "user-read-email"
    UserReadPrivate -> "user-read-private"
    UserLibraryModify -> "user-library-modify"
    UserLibraryRead -> "user-library-read"