packages feed

liblastfm 0.2.0.0 → 0.3.0.0

raw patch · 22 files changed

+125/−1148 lines, 22 filesdep +semigroupsdep −HUnitdep −attoparsecdep −liblastfmdep ~aesondep ~bytestringPVP ok

version bump matches the API change (PVP)

Dependencies added: semigroups

Dependencies removed: HUnit, attoparsec, liblastfm, test-framework, test-framework-hunit

Dependency ranges changed: aeson, bytestring

API changes (from Hackage documentation)

+ Network.Lastfm.Internal: absorbQuery :: Foldable t => t (Request f b) -> Request f a
+ Network.Lastfm.Internal: indexedWith :: Int -> Request f a -> Request f a
+ Network.Lastfm.Library: albumItem :: Request f (Artist -> Album -> LibraryAlbum)
+ Network.Lastfm.Library: artistItem :: Request f (Artist -> LibraryArtist)
+ Network.Lastfm.Request: data LibraryAlbum
+ Network.Lastfm.Request: data LibraryArtist
+ Network.Lastfm.Request: data Scrobble
+ Network.Lastfm.Track: item :: Request f (Artist -> Track -> Timestamp -> Scrobble)
- Network.Lastfm.Library: addAlbum :: Request f (Artist -> Album -> APIKey -> SessionKey -> Sign)
+ Network.Lastfm.Library: addAlbum :: NonEmpty (Request f LibraryAlbum) -> Request f (APIKey -> SessionKey -> Sign)
- Network.Lastfm.Library: addArtist :: Request f (Artist -> APIKey -> SessionKey -> Sign)
+ Network.Lastfm.Library: addArtist :: NonEmpty (Request f LibraryArtist) -> Request f (APIKey -> SessionKey -> Sign)
- Network.Lastfm.Track: scrobble :: Request f (Artist -> Track -> Timestamp -> APIKey -> SessionKey -> Sign)
+ Network.Lastfm.Track: scrobble :: NonEmpty (Request f Scrobble) -> Request f (APIKey -> SessionKey -> Sign)

Files

liblastfm.cabal view
@@ -1,5 +1,5 @@ name: liblastfm-version: 0.2.0.0+version: 0.3.0.0 synopsis: Lastfm API interface license: MIT license-file: LICENSE@@ -13,74 +13,46 @@  library   default-language: Haskell2010-  build-depends: base >= 3 && < 5,-                 bytestring,-                 containers >= 0.5,-                 text,-                 cereal,-                 http-conduit >= 1.9,-                 http-types,-                 pureMD5,-                 crypto-api,-                 network,-                 contravariant,-                 void,-                 aeson+  build-depends:+    aeson,+    base >= 3 && < 5,+    bytestring,+    cereal,+    containers >= 0.5,+    contravariant,+    crypto-api,+    http-conduit >= 1.9,+    http-types,+    network,+    pureMD5,+    semigroups,+    text,+    void   hs-source-dirs: src-  exposed-modules: Network.Lastfm-                   Network.Lastfm.Authentication-                   Network.Lastfm.Album-                   Network.Lastfm.Artist-                   Network.Lastfm.Chart-                   Network.Lastfm.Event-                   Network.Lastfm.Geo-                   Network.Lastfm.Group-                   Network.Lastfm.Library-                   Network.Lastfm.Playlist-                   Network.Lastfm.Radio-                   Network.Lastfm.Tag-                   Network.Lastfm.Tasteometer-                   Network.Lastfm.Track-                   Network.Lastfm.User-                   Network.Lastfm.Venue-                   Network.Lastfm.Request-                   Network.Lastfm.Response-                   Network.Lastfm.Internal-  ghc-options: -Wall-               -fno-warn-unused-do-bind-               -funbox-strict-fields---test-suite json-  build-depends: base >= 3 && < 5,-                 bytestring >= 0.9 && < 0.11,-                 attoparsec >= 0.10,-                 aeson == 0.6.*,-                 HUnit,-                 test-framework,-                 test-framework-hunit,-                 text,-                 liblastfm-  type: exitcode-stdio-1.0-  hs-source-dirs: tests-  main-is: json.hs-  other-modules: Common-                 Venue-                 User-                 Track-                 Tasteometer-                 Tag-                 Playlist-                 Library-                 Group-                 Geo-                 Event-                 Chart-                 Artist-                 Album-  ghc-options: -Wall-               -fno-warn-unused-do-bind-               -fno-warn-orphans+  exposed-modules:+    Network.Lastfm+    Network.Lastfm.Album+    Network.Lastfm.Artist+    Network.Lastfm.Authentication+    Network.Lastfm.Chart+    Network.Lastfm.Event+    Network.Lastfm.Geo+    Network.Lastfm.Group+    Network.Lastfm.Internal+    Network.Lastfm.Library+    Network.Lastfm.Playlist+    Network.Lastfm.Radio+    Network.Lastfm.Request+    Network.Lastfm.Response+    Network.Lastfm.Tag+    Network.Lastfm.Tasteometer+    Network.Lastfm.Track+    Network.Lastfm.User+    Network.Lastfm.Venue+  ghc-options:+    -Wall+    -fno-warn-unused-do-bind+    -funbox-strict-fields   source-repository head
src/Network/Lastfm.hs view
@@ -1,3 +1,4 @@+-- | Lastfm API interface module Network.Lastfm   ( -- * Utilities for constructing requests     module Network.Lastfm.Request
src/Network/Lastfm/Authentication.hs view
@@ -12,6 +12,19 @@ -- -- Note that you can use any of them in your -- application despite their names+--+-- How to get session key for yourself for debug with GHCi:+--+-- >>> import Network.Lastfm+-- >>> import Network.Lastfm.Authentication+-- >>> :set -XOverloadedStrings+-- >>> lastfm $ getToken <*> apiKey "__API_KEY__" <* json+-- Just (Object fromList [("token",String "__TOKEN__")])+-- >>> putStrLn . link $ apiKey "__API_KEY__" <* token "__TOKEN__"+-- http://www.last.fm/api/auth/?api_key=__API_KEY__&token=__TOKEN__+-- >>> -- Click that link ^^^+-- >>> lastfm . sign "__SECRET__" $ getSession <*> token "__TOKEN__" <*> apiKey "__API_KEY__"  <* json+-- Just (Object fromList [("session",Object fromList [("name",String "__USER__"),("subscriber",String "0"),("key",String "__SESSION_KEY__")])]) module Network.Lastfm.Authentication   ( -- * Helpers     getToken, getSession, getMobileSession
src/Network/Lastfm/Internal.hs view
@@ -7,6 +7,7 @@ module Network.Lastfm.Internal   ( Request(..), Format(..), Ready, Sign   , R(..), wrap, unwrap, render, coerce+  , absorbQuery, indexedWith     -- * Lenses   , host, method, query   ) where@@ -99,11 +100,28 @@ wrap = Request . Const . Dual . Endo {-# INLINE wrap #-} - -- | Unwrapping from interesting 'Monoid' ('R' -> 'R') instance unwrap :: Request f a -> R f -> R f unwrap = appEndo . getDual . getConst . unRequest {-# INLINE unwrap #-}+++-- | Absorbing a bunch of queries, useful in batch operations+absorbQuery :: Foldable t => t (Request f b) -> Request f a+absorbQuery rs = wrap $ \r ->+  r { _query = _query r <> foldMap (_query . ($ rempty) . unwrap) rs }+{-# INLINE absorbQuery #-}++-- | Transforming Request to the "array notation"+indexedWith :: Int -> Request f a -> Request f a+indexedWith n r = r <* wrap (\s ->+  s { _query = M.mapKeys (\k -> k <> "[" <> T.pack (show n) <> "]") (_query s) })+{-# INLINE indexedWith #-}++-- | Empty request+rempty :: R f+rempty = R mempty mempty mempty+{-# INLINE rempty #-}   -- Miscellaneous instances
src/Network/Lastfm/Library.hs view
@@ -8,30 +8,51 @@ -- import qualified Network.Lastfm.Library as Library -- @ module Network.Lastfm.Library-  ( addAlbum, addArtist, addTrack+  ( addAlbum, albumItem, addArtist, artistItem, addTrack   , getAlbums, getArtists, getTracks   , removeAlbum, removeArtist, removeScrobble, removeTrack   ) where  import Control.Applicative+import           Data.List.NonEmpty (NonEmpty)+import qualified Data.List.NonEmpty as N +import Network.Lastfm.Internal (absorbQuery, indexedWith, wrap) import Network.Lastfm.Request  ++ -- | Add an album or collection of albums to a user's Last.fm library -- -- <http://www.last.fm/api/show/library.addAlbum>-addAlbum :: Request f (Artist -> Album -> APIKey -> SessionKey -> Sign)-addAlbum = api "library.addAlbum" <* post+addAlbum :: NonEmpty (Request f LibraryAlbum) -> Request f (APIKey -> SessionKey -> Sign)+addAlbum batch = api "library.addAlbum" <* items <* post+ where+  items = absorbQuery (N.zipWith indexedWith (N.fromList [0..]) batch)+  {-# INLINE items #-} {-# INLINE addAlbum #-} +-- | What artist to add to library?+albumItem :: Request f (Artist -> Album -> LibraryAlbum)+albumItem = wrap id+{-# INLINE albumItem #-} + -- | Add an artist to a user's Last.fm library -- -- <http://www.last.fm/api/show/library.addArtist>-addArtist :: Request f (Artist -> APIKey -> SessionKey -> Sign)-addArtist = api "library.addArtist" <* post+addArtist :: NonEmpty (Request f LibraryArtist) -> Request f (APIKey -> SessionKey -> Sign)+addArtist batch = api "library.addArtist" <* items <* post+ where+  items = absorbQuery (N.zipWith indexedWith (N.fromList [0..]) batch)+  {-# INLINE items #-} {-# INLINE addArtist #-}++-- | What album to add to library?+artistItem :: Request f (Artist -> LibraryArtist)+artistItem = wrap id+{-# INLINE artistItem #-}   -- | Add a track to a user's Last.fm library
src/Network/Lastfm/Request.hs view
@@ -27,7 +27,7 @@   , TaggingType, taggingType, UseRecs, useRecs, Venue, venue, VenueName, venueName   , Discovery, discovery, RTP, rtp, BuyLinks, buyLinks, Multiplier(..), multiplier   , Bitrate(..), bitrate, Name, name, Station, station-  , Targeted, comparison+  , Targeted, comparison, Scrobble, LibraryAlbum, LibraryArtist   ) where  import Control.Applicative@@ -173,6 +173,7 @@ data TaggingType data RecentTracks data UseRecs+data Scrobble data Group data Venue data VenueName@@ -183,6 +184,8 @@ data Discovery data RTP data BuyLinks+data LibraryAlbum+data LibraryArtist   -- | Add artist parameter@@ -190,12 +193,12 @@ artist = add "artist" {-# INLINE artist #-} --- | Add artist parameter+-- | Add artists parameter artists :: [Text] -> Request f [Artist] artists = add "artists" {-# INLINE artists #-} --- | Add artist parameter+-- | Add album parameter album :: Text -> Request f Album album = add "album" {-# INLINE album #-}
src/Network/Lastfm/Track.hs view
@@ -12,12 +12,15 @@   ( ArtistTrackOrMBID   , addTags, ban, getBuyLinks, getCorrection, getFingerprintMetadata   , getInfo, getShouts, getSimilar, getTags, getTopFans-  , getTopTags, love, removeTag, scrobble+  , getTopTags, love, removeTag, scrobble, item   , search, share, unban, unlove, updateNowPlaying   ) where -import Control.Applicative+import           Control.Applicative+import           Data.List.NonEmpty (NonEmpty)+import qualified Data.List.NonEmpty as N +import Network.Lastfm.Internal (absorbQuery, indexedWith, wrap) import Network.Lastfm.Request  @@ -149,15 +152,25 @@ {-# INLINE removeTag #-}  --- | Used to add a track-play to a user's profile.+-- | Add played tracks to the user profile. ----- Optional: 'album', 'albumArtist', 'chosenByUser', 'context',--- 'duration', 'mbid', 'streamId', 'trackNumber'+-- Scrobbles 50 first list elements -- -- <http://www.last.fm/api/show/track.scrobble>-scrobble :: Request f (Artist -> Track -> Timestamp -> APIKey -> SessionKey -> Sign)-scrobble = api "track.scrobble" <* post+scrobble :: NonEmpty (Request f Scrobble) -> Request f (APIKey -> SessionKey -> Sign)+scrobble batch = api "track.scrobble" <* items <* post+ where+  items = absorbQuery (N.zipWith indexedWith (N.fromList [0..49]) batch)+  {-# INLINE items #-} {-# INLINE scrobble #-}++-- | What track to scrobble?+--+-- Optional: 'album', 'albumArtist', 'chosenByUser', 'context',+-- 'duration', 'mbid', 'streamId', 'trackNumber'+item :: Request f (Artist -> Track -> Timestamp -> Scrobble)+item = wrap id+{-# INLINE item #-}   -- | Search for a track by track name. Returns track matches sorted by relevance.
− tests/Album.hs
@@ -1,90 +0,0 @@-{-# LANGUAGE DataKinds #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE UnicodeSyntax #-}-module Album (auth, noauth) where--import Data.Aeson.Types-import Network.Lastfm-import Network.Lastfm.Album-import Test.Framework-import Test.Framework.Providers.HUnit--import Common---auth ∷ Request JSON APIKey → Request JSON SessionKey → Secret → [Test]-auth ak sk s =-  [ testCase "Album.addTags" testAddTags-  , testCase "Album.getTags-authenticated" testGetTagsAuth-  , testCase "Album.removeTag" testRemoveTag-  , testCase "Album.share" testShare-  ]- where-  testAddTags = check ok . sign s $-    addTags <*> artist "Pink Floyd" <*> album "The Wall" <*> tags ["70s", "awesome", "classic"]-      <*> ak <*> sk--  testGetTagsAuth = check gt . sign s $-    getTags <*> artist "Pink Floyd" <*> album "The Wall"-      <*> ak <* sk--  testRemoveTag = check ok . sign s $-    removeTag <*> artist "Pink Floyd" <*> album "The Wall" <*> tag "awesome"-      <*> ak <*> sk--  testShare = check ok . sign s $-    share <*> album "Jerusalem" <*> artist "Sleep" <*> recipient "liblastfm" <* message "Just listen!"-      <*> ak <*> sk---noauth ∷ Request JSON APIKey → [Test]-noauth ak =-  [ testCase "Album.getBuyLinks" testGetBuylinks-  , testCase "Album.getBuyLinks_mbid" testGetBuylinks_mbid-  , testCase "Album.getInfo" testGetInfo-  , testCase "Album.getInfo_mbid" testGetInfo_mbid-  , testCase "Album.getShouts" testGetShouts-  , testCase "Album.getShouts_mbid" testGetShouts_mbid-  , testCase "Album.getTags" testGetTags-  , testCase "Album.getTags_mbid" testGetTags_mbid-  , testCase "Album.getTopTags" testGetTopTags-  , testCase "Album.getTopTags_mbid" testGetTopTags_mbid-  , testCase "Album.search" testSearch-  ]- where-  testGetBuylinks = check gbl $-    getBuyLinks <*> country "United Kingdom" <*> artist "Pink Floyd" <*> album "The Wall" <*> ak-  testGetBuylinks_mbid = check gbl $-    getBuyLinks <*> country "United Kingdom" <*> mbid "816abcd3-924a-3565-92b9-7ab750688f34" <*> ak--  testGetInfo = check gi $-    getInfo <*> artist "Pink Floyd" <*> album "The Wall" <*> ak-  testGetInfo_mbid = check gi $-    getInfo <*> mbid "816abcd3-924a-3565-92b9-7ab750688f34" <*> ak--  testGetShouts = check gs $-    getShouts <*> artist "Pink Floyd" <*> album "The Wall" <* limit 7 <*> ak-  testGetShouts_mbid = check gs $-    getShouts <*> mbid "816abcd3-924a-3565-92b9-7ab750688f34" <* limit 7 <*> ak--  testGetTags = check gt $-    getTags <*> artist "Pink Floyd" <*> album "The Wall" <* user "liblastfm" <*> ak-  testGetTags_mbid = check gt $-    getTags <*> mbid "816abcd3-924a-3565-92b9-7ab750688f34" <* user "liblastfm" <*> ak--  testGetTopTags = check gtt $-    getTopTags <*> artist "Pink Floyd" <*> album "The Wall" <*> ak-  testGetTopTags_mbid = check gtt $-    getTopTags <*> mbid "816abcd3-924a-3565-92b9-7ab750688f34" <*> ak--  testSearch = check se $-    search <*> album "wall" <* limit 5 <*> ak---gbl, gi, gs, gt, gtt, se ∷ Value → Parser [String]-gbl o = parseJSON o >>= (.: "affiliations") >>= (.: "physicals") >>= (.: "affiliation") >>= mapM (.: "supplierName")-gi o = parseJSON o >>= (.: "album") >>= (.: "toptags") >>= (.: "tag") >>= mapM (.: "name")-gs o = parseJSON o >>= (.: "shouts") >>= (.: "shout") >>= mapM (.: "body")-gt o = parseJSON o >>= (.: "tags") >>= (.: "tag") >>= mapM (.: "name")-gtt o = parseJSON o >>= (.: "toptags") >>= (.: "tag") >>= mapM (.: "count")-se o = parseJSON o >>= (.: "results") >>= (.: "albummatches") >>= (.: "album") >>= mapM (.: "name")
− tests/Artist.hs
@@ -1,140 +0,0 @@-{-# LANGUAGE DataKinds #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE UnicodeSyntax #-}-module Artist (auth, noauth) where--import Data.Aeson.Types-import Network.Lastfm-import Network.Lastfm.Artist-import Test.Framework-import Test.Framework.Providers.HUnit--import Common---auth ∷ Request JSON APIKey → Request JSON SessionKey → Secret → [Test]-auth ak sk s =-  [ testCase "Artist.addTags" testAddTags-  , testCase "Artist.getTags-authenticated" testGetTagsAuth-  , testCase "Artist.removeTag" testRemoveTag-  , testCase "Artist.share" testShare-  ]- where-  testAddTags = check ok . sign s $-    addTags <*> artist "Егор Летов" <*> tags ["russian", "black metal"] <*> ak <*> sk--  testGetTagsAuth = check gt . sign s $-    getTags <*> artist "Егор Летов" <*> ak <* sk--  testRemoveTag = check ok . sign s $-    removeTag <*> artist "Егор Летов" <*> tag "russian" <*> ak <*> sk--  testShare = check ok . sign s $-    share <*> artist "Sleep" <*> recipient "liblastfm" <* message "Just listen!" <*> ak <*> sk---noauth ∷ Request JSON APIKey → [Test]-noauth ak =-  [ testCase "Artist.getCorrection" testGetCorrection-  , testCase "Artist.getEvents" testGetEvents-  , testCase "Artist.getEvents_mbid" testGetEvents_mbid-  , testCase "Artist.getInfo" testGetInfo-  , testCase "Artist.getInfo_mbid" testGetInfo_mbid-  , testCase "Artist.getPastEvents" testGetPastEvents-  , testCase "Artist.getPastEvents_mbid" testGetPastEvents_mbid-  , testCase "Artist.getPodcast" testGetPodcast-  , testCase "Artist.getPodcast_mbid" testGetPodcast_mbid-  , testCase "Artist.getShouts" testGetShouts-  , testCase "Artist.getShouts_mbid" testGetShouts_mbid-  , testCase "Artist.getSimilar" testGetSimilar-  , testCase "Artist.getSimilar_mbid" testGetSimilar_mbid-  , testCase "Artist.getTags" testGetTags-  , testCase "Artist.getTags_mbid" testGetTags_mbid-  , testCase "Artist.getTopAlbums" testGetTopAlbums-  , testCase "Artist.getTopAlbums_mbid" testGetTopAlbums_mbid-  , testCase "Artist.getTopFans" testGetTopFans-  , testCase "Artist.getTopFans_mbid" testGetTopFans_mbid-  , testCase "Artist.getTopTags" testGetTopTags-  , testCase "Artist.getTopTags_mbid" testGetTopTags_mbid-  , testCase "Artist.getTopTracks" testGetTopTracks-  , testCase "Artist.getTopTracks_mbid" testGetTopTracks_mbid-  , testCase "Artist.search" testSearch-  ]- where-  testGetCorrection = check gc $-    getCorrection <*> artist "Meshugah" <*> ak--  testGetEvents = check ge $-    getEvents <*> artist "Meshuggah" <* limit 2 <*> ak-  testGetEvents_mbid = check ge $-    getEvents <*> mbid "cf8b3b8c-118e-4136-8d1d-c37091173413" <* limit 2 <*> ak--  testGetInfo = check gin $-    getInfo <*> artist "Meshuggah" <*> ak-  testGetInfo_mbid = check gin $-    getInfo <*> mbid "cf8b3b8c-118e-4136-8d1d-c37091173413" <*> ak--  testGetPastEvents = check gpe $-    getPastEvents <*> artist "Meshuggah" <* autocorrect True <*> ak-  testGetPastEvents_mbid = check gpe $-    getPastEvents <*> mbid "cf8b3b8c-118e-4136-8d1d-c37091173413" <* autocorrect True <*> ak--  testGetPodcast = check gp $-    getPodcast <*> artist "Meshuggah" <*> ak-  testGetPodcast_mbid = check gp $-    getPodcast <*> mbid "cf8b3b8c-118e-4136-8d1d-c37091173413" <*> ak--  testGetShouts = check gs $-    getShouts <*> artist "Meshuggah" <* limit 5 <*> ak-  testGetShouts_mbid = check gs $-    getShouts <*> mbid "cf8b3b8c-118e-4136-8d1d-c37091173413" <* limit 5 <*> ak--  testGetSimilar = check gsi $-    getSimilar <*> artist "Meshuggah" <* limit 3 <*> ak-  testGetSimilar_mbid = check gsi $-    getSimilar <*> mbid "cf8b3b8c-118e-4136-8d1d-c37091173413" <* limit 3 <*> ak--  testGetTags = check gt $-    getTags <*> artist "Егор Летов" <* user "liblastfm" <*> ak-  testGetTags_mbid = check gt $-    getTags <*> mbid "cfb3d32e-d095-4d63-946d-9daf06932180" <* user "liblastfm" <*> ak--  testGetTopAlbums = check gta $-    getTopAlbums <*> artist "Meshuggah" <* limit 3 <*> ak-  testGetTopAlbums_mbid = check gta $-    getTopAlbums <*> mbid "cf8b3b8c-118e-4136-8d1d-c37091173413" <* limit 3 <*> ak--  testGetTopFans = check gtf $-    getTopFans <*> artist "Meshuggah" <*> ak-  testGetTopFans_mbid = check gtf $-    getTopFans <*> mbid "cf8b3b8c-118e-4136-8d1d-c37091173413" <*> ak--  testGetTopTags = check gtt $-    getTopTags <*> artist "Meshuggah" <*> ak-  testGetTopTags_mbid = check gtt $-    getTopTags <*> mbid "cf8b3b8c-118e-4136-8d1d-c37091173413" <*> ak--  testGetTopTracks = check gttr $-    getTopTracks <*> artist "Meshuggah" <* limit 3 <*> ak-  testGetTopTracks_mbid = check gttr $-    getTopTracks <*> mbid "cf8b3b8c-118e-4136-8d1d-c37091173413" <* limit 3 <*> ak--  testSearch = check se $-    search <*> artist "Mesh" <* limit 3 <*> ak---gc, gin, gp ∷ Value → Parser String-ge, gpe, gs, gsi, gt, gta, gtf, gtt, gttr, se ∷ Value → Parser [String]-gc o = parseJSON o >>= (.: "corrections") >>= (.: "correction") >>= (.: "artist") >>= (.: "name")-ge o = parseJSON o >>= (.: "events") >>= (.: "event") >>= mapM (\o' → (o' .: "venue") >>= (.: "name"))-gin o = parseJSON o >>= (.: "artist") >>= (.: "stats") >>= (.: "listeners")-gp o = parseJSON o >>= (.: "rss") >>= (.: "channel") >>= (.: "description")-gpe o = parseJSON o >>= (.: "events") >>= (.: "event") >>= mapM (.: "title")-gs o = parseJSON o >>= (.: "shouts") >>= (.: "shout") >>= mapM (.: "author")-gsi o = parseJSON o >>= (.: "similarartists") >>= (.: "artist") >>= mapM (.: "name")-gt o = parseJSON o >>= (.: "tags") >>= (.: "tag") >>= mapM (.: "name")-gta o = parseJSON o >>= (.: "topalbums") >>= (.: "album") >>= mapM (.: "name")-gtf o = parseJSON o >>= (.: "topfans") >>= (.: "user") >>= mapM (.: "name")-gtt o = parseJSON o >>= (.: "toptags") >>= (.: "tag") >>= mapM (.: "name")-gttr o = parseJSON o >>= (.: "toptracks") >>= (.: "track") >>= mapM (.: "name")-se o = parseJSON o >>= (.: "results") >>= (.: "artistmatches") >>= (.: "artist") >>= mapM (.: "name")
− tests/Chart.hs
@@ -1,47 +0,0 @@-{-# LANGUAGE DataKinds #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE UnicodeSyntax #-}-module Chart (noauth) where--import Data.Aeson.Types-import Network.Lastfm-import Network.Lastfm.Chart-import Test.Framework-import Test.Framework.Providers.HUnit--import Common---noauth ∷ Request JSON APIKey → [Test]-noauth ak =-  [ testCase "Chart.getHypedArtists" testGetHypedArtists-  , testCase "Chart.getHypedTracks" testGetHypedTracks-  , testCase "Chart.getLovedTracks" testGetLovedTracks-  , testCase "Chart.getTopArtists" testGetTopArtists-  , testCase "Chart.getTopTags" testGetTopTags-  , testCase "Chart.getTopTracks" testGetTopTracks-  ]- where-  testGetHypedArtists = check ga $-    getHypedArtists <* limit 3 <*> ak--  testGetHypedTracks = check gt $-    getHypedTracks <* limit 2 <*> ak--  testGetLovedTracks = check gt $-    getLovedTracks <* limit 3 <*> ak--  testGetTopArtists = check ga $-    getTopArtists <* limit 4 <*> ak--  testGetTopTags = check gta $-    getTopTags <* limit 5 <*> ak--  testGetTopTracks = check gt $-    getTopTracks <* limit 2 <*> ak---ga, gt, gta ∷ Value → Parser [String]-ga o = parseJSON o >>= (.: "artists") >>= (.: "artist") >>= mapM (.: "name")-gt o = parseJSON o >>= (.: "tracks") >>= (.: "track") >>= mapM (.: "name")-gta o = parseJSON o >>= (.: "tags") >>= (.: "tag") >>= mapM (.: "name")
− tests/Common.hs
@@ -1,20 +0,0 @@-{-# LANGUAGE DataKinds #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE UnicodeSyntax #-}-module Common where--import Data.Aeson.Types-import Network.Lastfm-import Test.HUnit---check ∷ (Value → Parser a) → Request JSON Ready → Assertion-check p q = do-  r ← lastfm q-  case parse p `fmap` r of-    Just (Success _) → assertBool "success" True-    _                → assertFailure $ "Got: " ++ show r---ok ∷ Value → Parser String-ok o = parseJSON o >>= (.: "status")
− tests/Event.hs
@@ -1,49 +0,0 @@-{-# LANGUAGE DataKinds #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE UnicodeSyntax #-}-module Event (auth, noauth) where--import Data.Aeson.Types-import Network.Lastfm-import Network.Lastfm.Event-import Test.Framework-import Test.Framework.Providers.HUnit--import Common---auth ∷ Request JSON APIKey → Request JSON SessionKey → Secret → [Test]-auth ak sk s =-  [ testCase "Event.attend" testAttend-  , testCase "Event.share" testShare-  ]- where-  testAttend = check ok . sign s $-    attend <*> event 3142549 <*> status Attending <*> ak <*> sk--  testShare = check ok . sign s $-    share <*> event 3142549 <*> recipient "liblastfm" <* message "Just listen!" <*> ak <*> sk---noauth ∷ Request JSON APIKey → [Test]-noauth ak =-  [ testCase "Event.getAttendees" testGetAttendees-  , testCase "Event.getInfo" testGetInfo-  , testCase "Event.getShouts" testGetShouts-  ]- where-  testGetAttendees = check ga $-    getAttendees <*> event 3142549 <* limit 2 <*> ak--  testGetInfo = check gi $-    getInfo <*> event 3142549 <*> ak--  testGetShouts = check gs $-    getShouts <*> event 3142549 <* limit 1 <*> ak---gi, gs ∷ Value → Parser String-ga ∷ Value → Parser [String]-ga o = parseJSON o >>= (.: "attendees") >>= (.: "user") >>= mapM (.: "name")-gi o = parseJSON o >>= (.: "event") >>= (.: "venue") >>= (.: "location") >>= (.: "city")-gs o = parseJSON o >>= (.: "shouts") >>= (.: "shout") >>= (.: "body")
− tests/Geo.hs
@@ -1,70 +0,0 @@-{-# LANGUAGE DataKinds #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE UnicodeSyntax #-}-module Geo (noauth) where--import Data.Aeson.Types-import Network.Lastfm-import Network.Lastfm.Geo-import Test.Framework-import Test.Framework.Providers.HUnit--import Common---noauth ∷ Request JSON APIKey → [Test]-noauth ak =-  [ testCase "Geo.getEvents" testGetEvents-  , testCase "Geo.getMetroArtistChart" testGetMetroArtistChart-  , testCase "Geo.getMetroHypeArtistChart" testGetMetroHypeArtistChart-  , testCase "Geo.getMetroHypeTrackChart" testGetMetroHypeTrackChart-  , testCase "Geo.getMetroTrackChart" testGetMetroTrackChart-  , testCase "Geo.getMetroUniqueArtistChart" testGetMetroUniqueArtistChart-  , testCase "Geo.getMetroUniqueTrackChart" testGetMetroUniqueTrackChart-  , testCase "Geo.getMetroWeeklyChartlist" testGetMetroWeeklyChartlist-  , testCase "Geo.getMetros" testGetMetros-  , testCase "Geo.getTopArtists" testGetTopArtists-  , testCase "Geo.getTopTracks" testGetTopTracks-  ]- where-  testGetEvents = check ge $-    getEvents <* location "Moscow" <* limit 5 <*> ak--  testGetMetroArtistChart = check ga $-    getMetroArtistChart <*> metro "Saint Petersburg" <*> country "Russia" <*> ak--  testGetMetroHypeArtistChart = check ga $-    getMetroHypeArtistChart <*> metro "New York" <*> country "United States" <*> ak--  testGetMetroHypeTrackChart = check gt $-    getMetroHypeTrackChart <*> metro "Moscow" <*> country "Russia" <*> ak--  testGetMetroTrackChart = check gt $-    getMetroTrackChart <*> metro "Boston" <*> country "United States" <*> ak--  testGetMetroUniqueArtistChart = check ga $-    getMetroUniqueArtistChart <*> metro "Minsk" <*> country "Belarus" <*> ak--  testGetMetroUniqueTrackChart = check gt $-    getMetroUniqueTrackChart <*> metro "Moscow" <*> country "Russia" <*> ak--  testGetMetroWeeklyChartlist = check gc $-    getMetroWeeklyChartlist <*> metro "Moscow" <*> ak--  testGetMetros = check gm $-    getMetros <* country "Russia" <*> ak--  testGetTopArtists = check ga $-    getTopArtists <*> country "Belarus" <* limit 3 <*> ak--  testGetTopTracks = check gt $-    getTopTracks <*> country "Ukraine" <* limit 2 <*> ak---ga, ge, gm, gt ∷ Value → Parser [String]-gc ∷ Value → Parser [(String, String)]-ga o = parseJSON o >>= (.: "topartists") >>= (.: "artist") >>= mapM (.: "name")-gc o = parseJSON o >>= (.: "weeklychartlist") >>= (.: "chart") >>= mapM (\t → (,) <$> (t .: "from") <*> (t .: "to"))-ge o = parseJSON o >>= (.: "events") >>= (.: "event") >>= mapM (.: "id")-gm o = parseJSON o >>= (.: "metros") >>= (.: "metro") >>= mapM (.: "name")-gt o = parseJSON o >>= (.: "toptracks") >>= (.: "track") >>= mapM (.: "name")
− tests/Group.hs
@@ -1,53 +0,0 @@-{-# LANGUAGE DataKinds #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE UnicodeSyntax #-}-module Group (noauth) where--import Data.Aeson.Types-import Network.Lastfm-import Network.Lastfm.Group-import Test.Framework-import Test.Framework.Providers.HUnit--import Common---noauth ∷ Request JSON APIKey → [Test]-noauth ak =-  [ testCase "Group.getHype" testGetHype-  , testCase "Group.getMembers" testGetMembers-  , testCase "Group.getWeeklyAlbumChart" testGetWeeklyAlbumChart-  , testCase "Group.getWeeklyArtistChart" testGetWeeklyArtistChart-  , testCase "Group.getWeeklyChartList" testGetWeeklyChartList-  , testCase "Group.getWeeklyTrackChart" testGetWeeklyTrackChart-  ]- where-  g = "People with no social lives that listen to more music than is healthy who are slightly scared of spiders and can never seem to find a pen"--  testGetHype = check gh $-    getHype <*> group g <*> ak--  testGetMembers = check gm $-    getMembers <*> group g <* limit 10 <*> ak--  testGetWeeklyAlbumChart = check ga $-    getWeeklyAlbumChart <*> group g <*> ak--  testGetWeeklyArtistChart = check gar $-    getWeeklyArtistChart <*> group g <*> ak--  testGetWeeklyChartList = check gc $-    getWeeklyChartList <*> group g <*> ak--  testGetWeeklyTrackChart = check gt $-    getWeeklyTrackChart <*> group g <*> ak---ga, gar, gh, gm, gt ∷ Value → Parser [String]-gc ∷ Value → Parser [(String, String)]-ga o = parseJSON o >>= (.: "weeklyalbumchart") >>= (.: "album") >>= mapM (.: "playcount")-gar o = parseJSON o >>= (.: "weeklyartistchart") >>= (.: "artist") >>= mapM (.: "name")-gc o = parseJSON o >>= (.: "weeklychartlist") >>= (.: "chart") >>= mapM (\t → (,) <$> (t .: "from") <*> (t .: "to"))-gh o = parseJSON o >>= (.: "weeklyartistchart") >>= (.: "artist") >>= mapM (.: "mbid")-gm o = parseJSON o >>= (.: "members") >>= (.: "user") >>= mapM (.: "name")-gt o = parseJSON o >>= (.: "weeklytrackchart") >>= (.: "track") >>= mapM (.: "url")
− tests/Library.hs
@@ -1,68 +0,0 @@-{-# LANGUAGE DataKinds #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE UnicodeSyntax #-}-module Library (auth, noauth) where--import Data.Aeson.Types-import Network.Lastfm-import Network.Lastfm.Library-import Test.Framework-import Test.Framework.Providers.HUnit--import Common---auth ∷ Request JSON APIKey → Request JSON SessionKey → Secret → [Test]-auth ak sk s =-  [ testCase "Library.addAlbum" testAddAlbum-  , testCase "Library.addArtist" testAddArtist-  , testCase "Library.addTrack" testAddTrack-  , testCase "Library.removeAlbum" testRemoveAlbum-  , testCase "Library.removeArtist" testRemoveArtist-  , testCase "Library.removeTrack" testRemoveTrack-  , testCase "Library.removeScrobble" testRemoveScrobble-  ]- where-  testAddAlbum = check ok . sign s $-    addAlbum <*> artist "Franz Ferdinand" <*> album "Franz Ferdinand" <*> ak <*> sk--  testAddArtist = check ok . sign s $-    addArtist <*> artist "Mobthrow" <*> ak <*> sk--  testAddTrack = check ok . sign s $-    addTrack <*> artist "Eminem" <*> track "Kim" <*> ak <*> sk--  testRemoveAlbum = check ok . sign s $-    removeAlbum <*> artist "Franz Ferdinand" <*> album "Franz Ferdinand" <*> ak <*> sk--  testRemoveArtist = check ok . sign s $-    removeArtist <*> artist "Burzum" <*> ak <*> sk--  testRemoveTrack = check ok . sign s $-    removeTrack <*> artist "Eminem" <*> track "Kim" <*> ak <*> sk--  testRemoveScrobble = check ok . sign s $-    removeScrobble <*> artist "Gojira" <*> track "Ocean" <*> timestamp 1328905590 <*> ak <*> sk---noauth ∷ Request JSON APIKey → [Test]-noauth ak =-  [ testCase "Library.getAlbums" testGetAlbums-  , testCase "Library.getArtists" testGetArtists-  , testCase "Library.getTracks" testGetTracks-  ]- where-  testGetAlbums = check ga $-    getAlbums <*> user "smpcln" <* artist "Burzum" <* limit 5 <*> ak--  testGetArtists = check gar $-    getArtists <*> user "smpcln" <* limit 7 <*> ak--  testGetTracks = check gt $-    getTracks <*> user "smpcln" <* artist "Burzum" <* limit 4 <*> ak---ga, gar, gt ∷ Value → Parser [String]-ga o = parseJSON o >>= (.: "albums") >>= (.: "album") >>= mapM (.: "name")-gar o = parseJSON o >>= (.: "artists") >>= (.: "artist") >>= mapM (.: "name")-gt o = parseJSON o >>= (.: "tracks") >>= (.: "track") >>= mapM (.: "name")
− tests/Playlist.hs
@@ -1,39 +0,0 @@-{-# LANGUAGE DataKinds #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE UnicodeSyntax #-}-module Playlist (auth) where--import Data.Aeson.Types-import Network.Lastfm-import Network.Lastfm.Playlist-import Network.Lastfm.User-import Test.Framework-import Test.Framework.Providers.HUnit--import Common---auth ∷ Request JSON APIKey → Request JSON SessionKey → Secret → [Test]-auth ak sk s =-  [ testCase "Playlist.create"   testCreate -- Order matters.-  , testCase "Playlist.addTrack" testAddTrack-  ]- where-  ak' = "29effec263316a1f8a97f753caaa83e0"--  testAddTrack =-    do r ← lastfm $ getPlaylists <*> user "liblastfm" <*> apiKey ak' <* json-       case parseMaybe pl =<< r of-         Nothing → error "M"-         Just r' → let pid = read $ head r' in check ok . sign s $-           addTrack <*> playlist pid <*> artist "Ruby my dear" <*> track "Chazz" <*> ak <*> sk--  testCreate = check pn . sign s $-    create <* title "Awesome playlist" <*> ak <*> sk---pl ∷ Value → Parser [String]-pl o = parseJSON o >>= (.: "playlists") >>= (.: "playlist") >>= mapM (.: "id")--pn ∷ Value → Parser String-pn o = parseJSON o >>= (.: "playlists") >>= (.: "playlist") >>= (.: "title")
− tests/Tag.hs
@@ -1,67 +0,0 @@-{-# LANGUAGE DataKinds #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE UnicodeSyntax #-}-module Tag (noauth) where--import Data.Aeson.Types-import Network.Lastfm-import Network.Lastfm.Tag-import Test.Framework-import Test.Framework.Providers.HUnit--import Common---noauth ∷ Request JSON APIKey → [Test]-noauth ak =-  [ testCase "Tag.getInfo" testGetInfo-  , testCase "Tag.getSimilar" testGetSimilar-  , testCase "Tag.getTopAlbums" testGetTopAlbums-  , testCase "Tag.getTopArtists" testGetTopArtists-  , testCase "Tag.getTopTags" testGetTopTags-  , testCase "Tag.getTopTracks" testGetTopTracks-  , testCase "Tag.getWeeklyArtistChart" testGetWeeklyArtistChart-  , testCase "Tag.getWeeklyChartList" testGetWeeklyChartList-  , testCase "Tag.search" testSearch-  ]- where-  testGetInfo = check gi $-    getInfo <*> tag "depressive" <*> ak--  testGetSimilar = check gs $-    getSimilar <*> tag "depressive" <*> ak--  testGetTopAlbums = check gta $-    getTopAlbums <*> tag "depressive" <* limit 2 <*> ak--  testGetTopArtists = check gtar $-    getTopArtists <*> tag "depressive" <* limit 3 <*> ak--  testGetTopTags = check gtt $-    getTopTags <*> ak--  testGetTopTracks = check gttr $-    getTopTracks <*> tag "depressive" <* limit 2 <*> ak--  testGetWeeklyArtistChart = check gwac $-    getWeeklyArtistChart <*> tag "depressive" <* limit 3 <*> ak--  testGetWeeklyChartList = check gc $-    getWeeklyChartList <*> tag "depressive" <*> ak--  testSearch = check se $-    search <*> tag "depressive" <* limit 3 <*> ak---gi ∷ Value → Parser String-gs, gta, gtar, gtt, gttr, gwac, se ∷ Value → Parser [String]-gc ∷ Value → Parser [(String, String)]-gi o = parseJSON o >>= (.: "tag") >>= (.: "taggings")-gc o = parseJSON o >>= (.: "weeklychartlist") >>= (.: "chart") >>= mapM (\t → (,) <$> (t .: "from") <*> (t .: "to"))-gs o = parseJSON o >>= (.: "similartags") >>= (.: "tag") >>= mapM (.: "name")-gta o = parseJSON o >>= (.: "topalbums") >>= (.: "album") >>= mapM (.: "url")-gtar o = parseJSON o >>= (.: "topartists") >>= (.: "artist") >>= mapM (.: "url")-gtt o = parseJSON o >>= (.: "toptags") >>= (.: "tag") >>= mapM (.: "name")-gttr o = parseJSON o >>= (.: "toptracks") >>= (.: "track") >>= mapM (.: "url")-gwac o = parseJSON o >>= (.: "weeklyartistchart") >>= (.: "artist") >>= mapM (.: "name")-se o = parseJSON o >>= (.: "results") >>= (.: "tagmatches") >>= (.: "tag") >>= mapM (.: "name")
− tests/Tasteometer.hs
@@ -1,34 +0,0 @@-{-# LANGUAGE DataKinds #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE UnicodeSyntax #-}-module Tasteometer (noauth) where--import           Data.Aeson.Types-import           Network.Lastfm-import qualified Network.Lastfm.Tasteometer as T-import           Test.Framework-import           Test.Framework.Providers.HUnit--import Common---noauth ∷ Request JSON APIKey → [Test]-noauth ak =-  [ testCase "Tasteometer.compare"    testCompare-  , testCase "Tasteometer.compare'"   testCompare'-  , testCase "Tasteometer.compare''"  testCompare''-  , testCase "Tasteometer.compare'''" testCompare'''-  ]- where-  testCompare = check cs $-    T.compare (user "smpcln") (user "MCDOOMDESTROYER") <*> ak-  testCompare' = check cs $-    T.compare (user "smpcln") (artists ["enduser", "venetian snares"]) <*> ak-  testCompare'' = check cs $-    T.compare (artists ["enduser", "venetian snares"]) (user "smpcln") <*> ak-  testCompare''' = check cs $-    T.compare (artists ["enduser", "venetian snares"]) (artists ["enduser", "venetian snares"]) <*> ak---cs ∷ Value → Parser String-cs o = parseJSON o >>= (.: "comparison") >>= (.: "result") >>= (.: "score")
− tests/Track.hs
@@ -1,132 +0,0 @@-{-# LANGUAGE DataKinds #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE UnicodeSyntax #-}-module Track (auth, noauth) where--import Data.Aeson.Types-import Network.Lastfm-import Network.Lastfm.Track-import Test.Framework-import Test.Framework.Providers.HUnit--import Common---auth ∷ Request JSON APIKey → Request JSON SessionKey → Secret → [Test]-auth ak sk s =-  [ testCase "Track.addTags" testAddTags-  , testCase "Track.ban" testBan-  , testCase "Track.love" testLove-  , testCase "Track.removeTag" testRemoveTag-  , testCase "Track.share" testShare-  , testCase "Track.unban" testUnban-  , testCase "Track.unlove" testUnlove-  , testCase "Track.scrobble" testScrobble-  , testCase "Track.updateNowPlaying" testUpdateNowPlaying-  ]- where-  testAddTags = check ok . sign s $-    addTags <*> artist "Jefferson Airplane" <*> track "White rabbit" <*> tags ["60s", "awesome"] <*> ak <*> sk--  testBan = check ok . sign s $-    ban <*> artist "Eminem" <*> track "Kim" <*> ak <*> sk--  testLove = check ok . sign s $-    love <*> artist "Gojira" <*> track "Ocean" <*> ak <*> sk--  testRemoveTag = check ok . sign s $-    removeTag <*> artist "Jefferson Airplane" <*> track "White rabbit" <*> tag "awesome" <*> ak <*> sk--  testShare = check ok . sign s $-    share <*> artist "Led Zeppelin" <*> track "When the Levee Breaks" <*> recipient "liblastfm" <* message "Just listen!" <*> ak <*> sk--  testUnban = check ok . sign s $-    unban <*> artist "Eminem" <*> track "Kim" <*> ak <*> sk--  testUnlove = check ok . sign s $-    unlove <*> artist "Gojira" <*> track "Ocean" <*> ak <*> sk--  testScrobble = check ss . sign s $-    scrobble <*> artist "Gojira" <*> track "Ocean" <*> timestamp 1300000000 <*> ak <*> sk--  testUpdateNowPlaying = check np . sign s $-    updateNowPlaying <*> artist "Gojira" <*> track "Ocean" <*> ak <*> sk---noauth ∷ Request JSON APIKey → [Test]-noauth ak =-  [ testCase "Track.getBuylinks" testGetBuylinks-  , testCase "Track.getCorrection" testGetCorrection-  , testCase "Track.getFingerprintMetadata" testGetFingerprintMetadata-  , testCase "Track.getInfo" testGetInfo-  , testCase "Track.getInfo_mbid" testGetInfo_mbid-  , testCase "Track.getShouts" testGetShouts-  , testCase "Track.getShouts_mbid" testGetShouts_mbid-  , testCase "Track.getSimilar" testGetSimilar-  , testCase "Track.getSimilar_mbid" testGetSimilar_mbid-  , testCase "Track.getTags" testGetTags-  , testCase "Track.getTags_mbid" testGetTags_mbid-  , testCase "Track.getTopFans" testGetTopFans-  , testCase "Track.getTopFans_mbid" testGetTopFans_mbid-  , testCase "Track.getTopTags" testGetTopTags-  , testCase "Track.getTopTags_mbid" testGetTopTags_mbid-  , testCase "Track.search" testSearch-  ]- where-  testGetBuylinks = check gbl $-    getBuyLinks <*> country "United Kingdom" <*> artist "Pink Floyd" <*> track "Brain Damage" <*> ak--  testGetCorrection = check gc $-    getCorrection <*> artist "Pink Ployd" <*> track "Brain Damage" <*> ak--  testGetFingerprintMetadata = check gfm $-    getFingerprintMetadata <*> fingerprint 1234 <*> ak--  testGetInfo = check gi $-    getInfo <*> artist "Pink Floyd" <*> track "Comfortably Numb" <* username "aswalrus" <*> ak-  testGetInfo_mbid = check gi $-    getInfo <*> mbid "52d7c9ff-6ae4-48a6-acec-4c1a486f8c92" <* username "aswalrus" <*> ak--  testGetShouts = check gsh $-    getShouts <*> artist "Pink Floyd" <*> track "Comfortably Numb" <* limit 7 <*> ak-  testGetShouts_mbid = check gsh $-    getShouts <*> mbid "52d7c9ff-6ae4-48a6-acec-4c1a486f8c92" <* limit 7 <*> ak--  testGetSimilar = check gsi $-    getSimilar <*> artist "Pink Floyd" <*> track "Comfortably Numb" <* limit 4 <*> ak-  testGetSimilar_mbid = check gsi $-    getSimilar <*> mbid "52d7c9ff-6ae4-48a6-acec-4c1a486f8c92" <* limit 4 <*> ak--  testGetTags = check gt $-    getTags <*> artist "Jefferson Airplane" <*> track "White Rabbit" <* user "liblastfm" <*> ak-  testGetTags_mbid = check gt $-    getTags <*> mbid "001b3337-faf4-421a-a11f-45e0b60a7703"  <* user "liblastfm" <*> ak--  testGetTopFans = check gtf $-    getTopFans <*> artist "Pink Floyd" <*> track "Comfortably Numb" <*> ak-  testGetTopFans_mbid = check gtf $-    getTopFans <*> mbid "52d7c9ff-6ae4-48a6-acec-4c1a486f8c92" <*> ak--  testGetTopTags = check gtt $-    getTopTags <*> artist "Pink Floyd" <*> track "Comfortably Numb" <*> ak-  testGetTopTags_mbid = check gtt $-    getTopTags <*> mbid "52d7c9ff-6ae4-48a6-acec-4c1a486f8c92" <*> ak--  testSearch = check s' $-    search <*> track "Believe" <* limit 12 <*> ak---gc, gi, gt, ss, np ∷ Value → Parser String-gbl, gfm, gsh, gsi{-, gta-}, gtf, gtt, s' ∷ Value → Parser [String]-gbl o = parseJSON o >>= (.: "affiliations") >>= (.: "downloads") >>= (.: "affiliation") >>= mapM (.: "supplierName")-gc o = parseJSON o >>= (.: "corrections") >>= (.: "correction") >>= (.: "track") >>= (.: "artist") >>= (.: "name")-gfm o = parseJSON o >>= (.: "tracks") >>= (.: "track") >>= mapM (.: "name")-gi o = parseJSON o >>= (.: "track") >>= (.: "userplaycount")-gsh o = parseJSON o >>= (.: "shouts") >>= (.: "shout") >>= mapM (.: "author")-gsi o = parseJSON o >>= (.: "similartracks") >>= (.: "track") >>= mapM (.: "name")-gt o = parseJSON o >>= (.: "tags") >>= (.: "@attr") >>= (.: "track")-gtf o = parseJSON o >>= (.: "topfans") >>= (.: "user") >>= mapM (.: "name")-gtt o = parseJSON o >>= (.: "toptags") >>= (.: "tag") >>= mapM (.: "name")-s' o = parseJSON o >>= (.: "results") >>= (.: "trackmatches") >>= (.: "track") >>= mapM (.: "name")-ss o = parseJSON o >>= (.: "scrobbles") >>= (.: "scrobble") >>= (.: "track") >>= (.: "#text")-np o = parseJSON o >>= (.: "nowplaying") >>= (.: "track") >>= (.: "#text")
− tests/User.hs
@@ -1,152 +0,0 @@-{-# LANGUAGE DataKinds #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE UnicodeSyntax #-}-module User (auth, noauth) where--import Data.Aeson.Types-import Network.Lastfm-import Network.Lastfm.User-import Test.Framework-import Test.Framework.Providers.HUnit--import Common---auth ∷ Request JSON APIKey → Request JSON SessionKey → Secret → [Test]-auth ak sk s =-  [ testCase "User.getRecentStations" testGetRecentStations-  , testCase "User.getRecommendedArtists" testGetRecommendedArtists-  , testCase "User.getRecommendedEvents" testGetRecommendedEvents-  , testCase "User.shout" testShout-  ]- where-  testGetRecentStations = check grs . sign s $-    getRecentStations <*> user "liblastfm" <* limit 10 <*> ak <*> sk--  testGetRecommendedArtists = check gra . sign s $-    getRecommendedArtists <* limit 10 <*> ak <*> sk--  testGetRecommendedEvents = check gre . sign s $-    getRecommendedEvents <* limit 10 <*> ak <*> sk--  testShout = check ok . sign s $-    shout <*> user "liblastfm" <*> message "test message" <*> ak <*> sk---noauth ∷ Request JSON APIKey → [Test]-noauth ak =-  [ testCase "User.getArtistTracks" testGetArtistTracks-  , testCase "User.getBannedTracks" testGetBannedTracks-  , testCase "User.getEvents" testGetEvents-  , testCase "User.getFriends" testGetFriends-  , testCase "User.getPlayCount" testGetPlayCount-  , testCase "User.getGetLovedTracks" testGetLovedTracks-  , testCase "User.getNeighbours" testGetNeighbours-  , testCase "User.getNewReleases" testGetNewReleases-  , testCase "User.getPastEvents" testGetPastEvents-  , testCase "User.getPersonalTags" testGetPersonalTags-  , testCase "User.getPlaylists" testGetPlaylists-  , testCase "User.getRecentTracks" testGetRecentTracks-  , testCase "User.getShouts" testGetShouts-  , testCase "User.getTopAlbums" testGetTopAlbums-  , testCase "User.getTopArtists" testGetTopArtists-  , testCase "User.getTopTags" testGetTopTags-  , testCase "User.getTopTracks" testGetTopTracks-  , testCase "User.getWeeklyAlbumChart" testGetWeeklyAlbumChart-  , testCase "User.getWeeklyArtistChart" testGetWeeklyArtistChart-  , testCase "User.getWeeklyChartList" testGetWeeklyChartList-  , testCase "User.getWeeklyTrackChart" testGetWeeklyTrackChart-  ]- where-  testGetArtistTracks = check gat $-    getArtistTracks <*> user "smpcln" <*> artist "Dvar" <*> ak--  testGetBannedTracks = check gbt $-    getBannedTracks <*> user "smpcln" <* limit 10 <*> ak--  testGetEvents = check ge $-    getEvents <*> user "chansonnier" <* limit 5 <*> ak--  testGetFriends = check gf $-    getFriends <*> user "smpcln" <* limit 10 <*> ak--  testGetPlayCount = check gpc $-    getInfo <*> user "smpcln" <*> ak--  testGetLovedTracks = check glt $-    getLovedTracks <*> user "smpcln" <* limit 10 <*> ak--  testGetNeighbours = check gn $-    getNeighbours <*> user "smpcln" <* limit 10 <*> ak--  testGetNewReleases = check gnr $-    getNewReleases <*> user "rj" <*> ak--  testGetPastEvents = check gpe $-    getPastEvents <*> user "mokele" <* limit 5 <*> ak--  testGetPersonalTags = check gpt $-    getPersonalTags <*> user "crackedcore" <*> tag "rhythmic noise" <*> taggingType "artist" <* limit 10 <*> ak--  testGetPlaylists = check gp $-    getPlaylists <*> user "mokele" <*> ak--  testGetRecentTracks = check grt $-    getRecentTracks <*> user "smpcln" <* limit 10 <*> ak--  testGetShouts = check gs $-    getShouts <*> user "smpcln" <* limit 2 <*> ak--  testGetTopAlbums = check gtal $-    getTopAlbums <*> user "smpcln" <* limit 5 <*> ak--  testGetTopArtists = check gtar $-    getTopArtists <*> user "smpcln" <* limit 5 <*> ak--  testGetTopTags = check gtta $-    getTopTags <*> user "smpcln" <* limit 10 <*> ak--  testGetTopTracks = check gttr $-    getTopTracks <*> user "smpcln" <* limit 10 <*> ak--  testGetWeeklyAlbumChart = check gwalc $-    getWeeklyAlbumChart <*> user "smpcln" <*> ak--  testGetWeeklyArtistChart = check gwarc $-    getWeeklyArtistChart <*> user "smpcln" <*> ak--  testGetWeeklyChartList = check gwcl $-    getWeeklyChartList <*> user "smpcln" <*> ak--  testGetWeeklyTrackChart = check gwtc $-    getWeeklyTrackChart <*> user "smpcln" <*> ak---gpc ∷ Value → Parser String-gat, gbt, ge, gf, glt, gn, gnr, gp, gpe, gpt, gra, gre, grs, grt, gs, gtal, gtar, gtta, gttr, gwalc, gwarc, gwcl, gwtc ∷ Value → Parser [String]-gat o = parseJSON o >>= (.: "artisttracks") >>= (.: "track") >>= mapM (.: "name")-gbt o = parseJSON o >>= (.: "bannedtracks") >>= (.: "track") >>= mapM (.: "name")-ge o = parseJSON o >>= (.: "events") >>= (.: "event") >>= mapM (.: "venue") >>= mapM (.: "url")-gf o = parseJSON o >>= (.: "friends") >>= (.: "user") >>= mapM (.: "name")-glt o = parseJSON o >>= (.: "lovedtracks") >>= (.: "track") >>= mapM (.: "name")-gn o = parseJSON o >>= (.: "neighbours") >>= (.: "user") >>= mapM (.: "name")-gnr o = parseJSON o >>= (.: "albums") >>= (.: "album") >>= mapM (.: "url")-gp o = parseJSON o >>= (.: "playlists") >>= (.: "playlist") >>= mapM (.: "title")-gpc o = parseJSON o >>= (.: "user") >>= (.: "playcount")-gpe o = parseJSON o >>= (.: "events") >>= (.: "event") >>= mapM (.: "url")-gpt o = parseJSON o >>= (.: "taggings") >>= (.: "artists") >>= (.: "artist") >>= mapM (.: "name")-gra o = parseJSON o >>= (.: "recommendations") >>= (.: "artist") >>= mapM (.: "name")-gre o = do-  m <- parseJSON o >>= (.: "events")-  (m .: "event" >>= mapM (.: "url")) <|> (m .: "event" >>= fmap return . (.: "url"))-grs o = parseJSON o >>= (.: "recentstations") >>= (.: "station") >>= mapM (.: "name")-grt o = parseJSON o >>= (.: "recenttracks") >>= (.: "track") >>= mapM (.: "name")-gs o = parseJSON o >>= (.: "shouts") >>= (.: "shout") >>= mapM (.: "body")-gtal o = parseJSON o >>= (.: "topalbums") >>= (.: "album") >>= mapM (.: "artist") >>= mapM (.: "name")-gtar o = parseJSON o >>= (.: "topartists") >>= (.: "artist") >>= mapM (.: "name")-gtta o = parseJSON o >>= (.: "toptags") >>= (.: "tag") >>= mapM (.: "name")-gttr o = parseJSON o >>= (.: "toptracks") >>= (.: "track") >>= mapM (.: "url")-gwalc o = parseJSON o >>= (.: "weeklyalbumchart") >>= (.: "album") >>= mapM (.: "url")-gwarc o = parseJSON o >>= (.: "weeklyartistchart") >>= (.: "artist") >>= mapM (.: "url")-gwcl o = take 5 `fmap` (parseJSON o >>= (.: "weeklychartlist") >>= (.: "chart") >>= mapM (.: "from"))-gwtc o = parseJSON o >>= (.: "weeklytrackchart") >>= (.: "track") >>= mapM (.: "url")
− tests/Venue.hs
@@ -1,35 +0,0 @@-{-# LANGUAGE DataKinds #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE UnicodeSyntax #-}-module Venue (noauth) where--import Data.Aeson.Types-import Network.Lastfm-import Network.Lastfm.Venue-import Test.Framework-import Test.Framework.Providers.HUnit--import Common---noauth ∷ Request JSON APIKey → [Test]-noauth ak =-  [ testCase "Venue.getEvents" testGetEvents-  , testCase "Venue.getPastEvents" testGetPastEvents-  , testCase "Venue.search" testSearch-  ]- where-  testGetEvents = check ge $-    getEvents <*> venue 9163107 <*> ak--  testGetPastEvents = check gpe $-    getPastEvents <*> venue 9163107 <* limit 2 <*> ak--  testSearch = check se $-    search <*> venueName "Arena" <*> ak---ge, gpe, se ∷ Value → Parser [String]-ge o = parseJSON o >>= (.: "events") >>= (.: "event") >>= mapM (\t → (t .: "venue") >>= (.: "name"))-gpe o = parseJSON o >>= (.: "events") >>= (.: "event") >>= mapM (.: "title")-se o = parseJSON o >>= (.: "results") >>= (.: "venuematches") >>= (.: "venue") >>= mapM (.: "id")
− tests/json.hs
@@ -1,68 +0,0 @@-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE UnicodeSyntax #-}-module Main where--import Control.Applicative-import Data.Monoid-import System.Exit (ExitCode(ExitFailure), exitWith)--import qualified Data.ByteString.Lazy as B-import           Data.Aeson-import           Data.Text (Text)-import           Network.Lastfm-import           Test.Framework--import qualified Album as Album-import qualified Artist as Artist-import qualified Chart as Chart-import qualified Event as Event-import qualified Geo as Geo-import qualified Group as Group-import qualified Library as Library-import qualified Playlist as Playlist-import qualified Tag as Tag-import qualified Tasteometer as Tasteometer-import qualified Track as Track-import qualified User as User-import qualified Venue as Venue---main ∷ IO ()-main =-  do keys ← B.readFile "tests/lastfm-keys.json"-     case decode keys of-       Just (Keys ak sk s) →-         defaultMainWithOpts (auth <> noauth) (mempty { ropt_threads = Just 20 })-          where-           auth = mconcat . map (\f → f (apiKey ak) (sessionKey sk) (Secret s)) $-             [ Album.auth-             , Artist.auth-             , Event.auth-             , Library.auth-             , Playlist.auth-             , Track.auth-             , User.auth-             ]-           noauth = mconcat . map (\f → f (apiKey ak)) $-             [ Album.noauth-             , Artist.noauth-             , Chart.noauth-             , Event.noauth-             , Geo.noauth-             , Group.noauth-             , Library.noauth-             , Tag.noauth-             , Tasteometer.noauth-             , Track.noauth-             , User.noauth-             , Venue.noauth-             ]-       Nothing → exitWith (ExitFailure 1)---data Keys = Keys Text Text Text---instance FromJSON Keys where-  parseJSON (Object o) = Keys <$> (o .: "APIKey") <*> (o .: "SessionKey") <*> (o .: "Secret")-  parseJSON _ = empty