11{-# LANGUAGE DeriveGeneric #-}
22{-# LANGUAGE OverloadedStrings #-}
3- {-# OPTIONS_GHC -Wno-incomplete-patterns #-}
4- {-# OPTIONS_GHC -Wno-name-shadowing #-}
53{-# LANGUAGE FlexibleInstances #-}
64{-# LANGUAGE MultiParamTypeClasses #-}
5+ {-# OPTIONS_GHC -Wno-incomplete-patterns #-}
6+ {-# OPTIONS_GHC -Wno-name-shadowing #-}
77
88module Main where
99
1010-- Standard library imports
11+ import Control.Exception (SomeException , try )
1112import System.Environment (getArgs , getProgName , lookupEnv )
13+ import System.FilePath (takeDirectory )
1214
1315-- Third-party library imports
1416import Control.Lens (Identity (runIdentity ), (^?) )
1517import Data.Aeson (FromJSON (parseJSON ), ToJSON ,
1618 Value (Object ), decodeStrict , (.:) )
19+ import Data.Aeson.Key (fromString )
1720import Data.Aeson.Lens (AsNumber (_Integer ), key , nth )
1821import Data.ByteString (ByteString )
1922import qualified Data.ByteString.Char8 as BS
@@ -23,14 +26,12 @@ import GHC.Generics (Generic)
2326import Network.HTTP.Simple (Query , getResponseBody , httpBS ,
2427 parseRequest_ , setRequestHeader ,
2528 setRequestQueryString )
26- import System.FilePath (takeDirectory )
2729import Text.Ginger (IncludeResolver , SourcePos , Template ,
2830 ToGVal (.. ), dict , easyRender ,
2931 parseGinger )
30- import Control.Exception (try , SomeException )
3132
3233-- Data type definitions
33- data MainRelease = MainRelease {
34+ data Release = Release {
3435 artists :: [String ],
3536 title :: String ,
3637 year :: Int ,
@@ -40,9 +41,9 @@ data MainRelease = MainRelease {
4041 uri :: String
4142} deriving (Show , Eq , Generic )
4243
43- instance ToJSON MainRelease
44+ instance ToJSON Release
4445
45- instance ToGVal m MainRelease where
46+ instance ToGVal m Release where
4647 toGVal release = dict [
4748 (" artists" , toGVal . L. intercalate " , " . artists $ release),
4849 (" title" , toGVal $ title release),
@@ -53,8 +54,7 @@ instance ToGVal m MainRelease where
5354 (" uri" , toGVal $ uri release)
5455 ]
5556
56-
57- instance FromJSON MainRelease where
57+ instance FromJSON Release where
5858 parseJSON (Object v) = do
5959 artists <- v .: " artists" >>= traverse (.: " name" )
6060 title <- v .: " title"
@@ -66,7 +66,7 @@ instance FromJSON MainRelease where
6666 [] -> fail " No images found"
6767 labels <- v .: " labels" >>= traverse (.: " name" )
6868 uri <- v .: " uri"
69- return MainRelease {
69+ return Release {
7070 artists = artists,
7171 title = title,
7272 year = year,
@@ -91,35 +91,54 @@ runDiscogsQuery query url = do
9191 parseRequest_ url
9292 getResponseBody <$> httpBS request
9393
94- getMasterReleaseId :: String -> String -> IO String
95- getMasterReleaseId artistName albumName = do
94+ data ReleaseType = Master | Regular deriving (Show )
95+
96+ toQueryParams :: ReleaseType -> (String , String )
97+ toQueryParams Master = (" master" , " master_id" )
98+ toQueryParams Regular = (" release" , " id" )
99+
100+ fetchReleaseIdByType :: String -> String -> ReleaseType -> IO String
101+ fetchReleaseIdByType artistName albumName releaseType = do
96102 let url = " https://api.discogs.com/database/search"
103+ (queryType, queryKey) = toQueryParams releaseType
97104 query =
98105 [ (" artist" , Just $ BS. pack artistName),
99106 (" release_title" , Just $ BS. pack albumName),
100- (" type" , Just " master " )
107+ (" type" , Just $ BS. pack queryType )
101108 ]
102109 body <- BS. unpack <$> runDiscogsQuery query url
103- case body ^? key " results" . nth 0 . key " master_id " . _Integer of
104- Just masterId -> return $ show masterId
105- Nothing -> fail " Failed to extract master_id from the response"
110+ case body ^? key " results" . nth 0 . key (fromString queryKey) . _Integer of
111+ Just idValue -> return $ show idValue
112+ Nothing -> fail $ " Failed to extract " ++ queryKey ++ " from the response"
106113
107- getMainReleaseId :: String -> IO String
108- getMainReleaseId masterId = do
114+ fetchMainReleaseId :: String -> IO String
115+ fetchMainReleaseId masterId = do
109116 let url = " https://api.discogs.com/masters/" ++ masterId
110117 body <- BS. unpack <$> runDiscogsQuery [] url
111118 case body ^? key " main_release" . _Integer of
112119 Just mainId -> return $ show mainId
113120 Nothing -> fail " Failed to extract main_release from the response"
114121
115- getMainRelease :: String -> IO MainRelease
116- getMainRelease releaseId = do
122+ -- | Fetches the master release ID. If fetching the master release ID fails,
123+ -- it falls back to fetching the first item's ID where the type is 'release'.
124+ -- This ensures that a valid release ID is returned even if the master release
125+ -- ID is unavailable.
126+ getReleaseId :: String -> String -> IO String
127+ getReleaseId artistName albumName = do
128+ result <- try (fetchReleaseIdByType artistName albumName Master ) :: IO (Either SomeException String )
129+ case result of
130+ Right masterId -> fetchMainReleaseId masterId
131+ Left _ -> fetchReleaseIdByType artistName albumName Regular
132+
133+ getRelease :: String -> IO Release
134+ getRelease releaseId = do
117135 let url = " https://api.discogs.com/releases/" ++ releaseId
118136 body <- runDiscogsQuery [] url
119- case (decodeStrict body :: Maybe MainRelease ) of
137+ case (decodeStrict body :: Maybe Release ) of
120138 Just release -> return release
121139 Nothing -> fail " Cannot decode main release"
122140
141+ -- Template rendering
123142nullResolver :: IncludeResolver Identity
124143nullResolver = const $ return Nothing
125144
@@ -134,12 +153,9 @@ templatePath = do
134153
135154runGenAlbumPost :: String -> String -> IO String
136155runGenAlbumPost artistName albumName = do
137- -- Get the MainRelease of the album
138- release <- getMasterReleaseId artistName albumName
139- >>= getMainReleaseId
140- >>= getMainRelease
141- content <- templatePath >>= readFile
142- return $ T. unpack . easyRender release $ getTemplate content
156+ release <- getReleaseId artistName albumName >>= getRelease
157+ content <- templatePath >>= readFile
158+ return $ T. unpack . easyRender release $ getTemplate content
143159
144160-- Main function
145161main :: IO ()
0 commit comments