Skip to content

nineonine/haskogs

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

37 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Haskogs Build Status

A Haskell Library for interacting with Discogs API.

Features

  • Covers all Endpoints
  • Supports pagination, optional parameters
  • Can be easily embedded in your monad transformer stack
  • Includes test suites

Examples

Database
{-# LANGUAGE OverloadedStrings #-}
import Discogs.Types.Discogs
import Discogs.Types.Release
import Discogs.Types.Artist

token :: ByteString
token = "yourGeneratedToken"

program :: DiscogsT IO (Release, Artist)
program = do
    r <- release 1
    a <- artist 1
    return (r, a)

main :: IO ()
main = do
    (r , a) <- fmap fromRightMaybe $ runDiscogs token program
    print r
    print a
Marketplace
{-# LANGUAGE OverloadedStrings #-}
import Discogs.Types.Discogs
import Discogs.Types.MarketPlace.Listing

token :: ByteString
token = "yourGeneratedToken"

program :: DiscogsT IO ()
program = newListing 4941528 "Mint (M)" 100 "Draft" Nothing >> return ()

main :: IO ()
main = runDiscogs token program >> return ()
User Actions
{-# LANGUAGE OverloadedStrings #-}
import Discogs.Types.Discogs
import Discogs.Types.User

token :: ByteString
token = "yourGeneratedToken"

program :: DiscogsT IO ()
program = profile "username"

main :: IO ()
main = do
    Right ( Just prfl ) <- runDiscogs token program
    print prfl

Useful accessors

A lot of Discogs entities have same field names. Because it was not allowed (GHC version < 8) to have multiple data types with same field names, every Type that describes Discogs response JSON object has unique name field names ( refactoring this using OverloadedRecordFields is on the TODO list ).

However, we have a useful typeclass for accesing common Discogs fields which are id and resource_url .

class DiscogsResource resource where
    type ID resource
    resourceId :: resource -> ID resource
    resourceUrl :: resource -> T.Text

All necessary Types implement this TC. We are using TypeFamilies extension here because there some instances with id field may also include non numeric characters ( e.g. Order ).

Now we have handy generic accessor functions.

{-# LANGUAGE OverloadedStrings #-}
import Discogs
import Discogs.Types ( Release, Artist )

token :: ByteString
token = "yourGeneratedToken"

program :: DiscogsT IO ()
program = do
    r <- release 1
    liftIO . print $ resourceId r -- prints 1
    a <- artist 1
    liftIO . print $ resourceUrl a -- prints "https://api.discogs.com/artists/1"
    return ()

Pagination

You can pass pagination related URL parameters using special function from Discogs.Types.Discogs

withParams :: (MonadIO m) => DiscogsT m a -> Params -> DiscogsT m a

Some responses consist of pagination object, as well as rest of the content. For convenient access we have Paginated class, which gives us generic functions for accessing either Pagination object or rest of the JSON object found in response.

class Paginated resource where
    type Content resource
    pagination :: resource -> Maybe Pagination
    contents :: resource -> Content resource

Example

{-# LANGUAGE OverloadedStrings #-}
import Discogs
import Discogs.Types ( SearchResult, Pagination, Result )

program :: DiscogsT IO ()
program = do
    let searchExample = search [("artist", "nirvana")]
    sr <- searchExample `withParams` [("page" , "50")] -- ( sr :: SearchResult )
    liftIO . print $ pagination sr -- prints pagination object
    liftIO . print $ contents sr -- prints contents ( 50th page of search result )
    return ()

Optional Parameters

Some endpoints accept optional parameters. You can pass them using special type Params. It is wrapped in existential type, so you just have to pass Text and Params will take care of conversion.

Example

-- without optional params
runDiscogs token $ newListing 4941528 "Mint (M)" 100 "Draft" Nothing

-- with optional params
runDiscogs token $ newListing 4941528 "Mint (M)" 100 "Draft" ( Just [("location", "unknown")] )

Testing

2 test suites available

cabal test test

for testing JSON instances

cabal test test-io

for testing IO.

TODO

  • OAuth Authentication
  • Richer Error Types
  • Automatic pausing when request limit reached
  • More Examples
  • Documentation
  • Types Refactoring : Reduce the amount of types, make types more generic
  • Types Refactoring : explicit FromJSON / ToJSON instances to avoid clashes with reserved words and same name fields
  • Types Refactoring : Search -> Release
  • Type class for accessing typical Discogs entity fields (id, resource_url)
  • Type class for paginated responses and types
  • IO tests rely on maintainer's private account -> need to make and setup 2 fake accounts for testing
  • Switch entirely to using withParams function for handling optional URL parameters

Contributions

  • Fork this repo
  • Create a new branch on your fork
  • Push commits to your branch
  • Submit new Pull Request

License

MIT License 2016 © Alex Dudarenko

About

Discogs API wrapper written in Haskell

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published