packages feed

twitchapi 0.0.2 → 0.0.3

raw patch · 6 files changed

+215/−127 lines, 6 files

Files

CHANGELOG.md view
@@ -1,5 +1,13 @@ # Revision history for twitchapi +## 0.0.3 -- 2022-11-09++* Restructured Helix API to remove DuplicateRecordFields dependency++## 0.0.2 -- 2022-10-10++* Implemented support for Helix (User - partial)+ ## 0.0.1 -- 2022-09-27  * Implemented support for Helix (Bits, Channel Points)
src/Web/TwitchAPI/Helix/Bits.hs view
@@ -1,7 +1,6 @@-{-# LANGUAGE DuplicateRecordFields #-}-{-# LANGUAGE OverloadedStrings     #-}-{-# LANGUAGE RecordWildCards       #-}-{-# LANGUAGE ScopedTypeVariables   #-}+{-# LANGUAGE OverloadedStrings   #-}+{-# LANGUAGE RecordWildCards     #-}+{-# LANGUAGE ScopedTypeVariables #-}  module Web.TwitchAPI.Helix.Bits where @@ -14,17 +13,16 @@ import qualified Data.Text.Encoding    as Text ( encodeUtf8 ) import qualified Network.HTTP.Client   as HTTP -import Data.Maybe ( fromMaybe ) import Data.Aeson ( FromJSON(..), (.:), withObject                   , Object                   )  import qualified Web.TwitchAPI.Helix.Request as Req -data Leaderboard = Leaderboard { count     :: Maybe Integer-                               , period    :: Maybe Period-                               , startedAt :: Maybe Time.UTCTime-                               , userId    :: Maybe Integer+data Leaderboard = Leaderboard { count    :: Maybe Integer+                               , period   :: Maybe Period+                               , start    :: Maybe Time.UTCTime+                               , searchId :: Maybe Integer                                } deriving ( Show, Eq )  data Period = Day | Week | Month | Year | All deriving ( Eq )@@ -37,11 +35,11 @@  instance Req.HelixRequest Leaderboard where     toRequest leaderboard =-        let count'     :: [(BS.ByteString, Maybe BS.ByteString)] = fromMaybe [] $ (\c -> ("count", Just . BS.pack . show $ c):[]) <$> (count leaderboard)-            period'    :: [(BS.ByteString, Maybe BS.ByteString)] = fromMaybe [] $ (\p -> ("period", Just . BS.pack . show $ p):[]) <$> (period leaderboard)-            startedAt' :: [(BS.ByteString, Maybe BS.ByteString)] = fromMaybe [] $ (\s -> ("started_at", Just . Text.encodeUtf8 $ (Time.formatTimeRFC3339 $ Time.utcToZonedTime Time.utc s :: Text.Text)):[]) <$> ((startedAt :: Leaderboard -> Maybe Time.UTCTime) leaderboard)-            userId'    :: [(BS.ByteString, Maybe BS.ByteString)] = fromMaybe [] $ (\u -> ("user_id", Just . Text.encodeUtf8 . Text.pack . show $ u):[]) <$> ((userId :: Leaderboard -> Maybe Integer) leaderboard)-            setQuery = HTTP.setQueryString $ foldl (++) [] [count', period', startedAt', userId']+        let count'    :: [(BS.ByteString, Maybe BS.ByteString)] = maybe [] (\c -> [("count", Just . BS.pack . show $ c)]) (count leaderboard)+            period'   :: [(BS.ByteString, Maybe BS.ByteString)] = maybe [] (\p -> [("period", Just . BS.pack . show $ p)]) (period leaderboard)+            start'    :: [(BS.ByteString, Maybe BS.ByteString)] = maybe [] (\s -> [("started_at", Just . Text.encodeUtf8 $ (Time.formatTimeRFC3339 $ Time.utcToZonedTime Time.utc s :: Text.Text))]) (start leaderboard)+            searchId' :: [(BS.ByteString, Maybe BS.ByteString)] = maybe [] (\u -> [("user_id", Just . Text.encodeUtf8 . Text.pack . show $ u)]) (searchId leaderboard)+            setQuery = HTTP.setQueryString $ concat [count', period', start', searchId']         in setQuery $ HTTP.parseRequest_ "GET https://api.twitch.tv/helix/bits/leaderboard"     scope Leaderboard{} = Just "bits:read" @@ -79,7 +77,7 @@             startedAt = Time.zonedTimeToUTC <$> Time.parseTimeRFC3339 started         return LeaderboardResponse{..} -data Cheermotes = Cheermotes { broadcasterId :: Integer } deriving ( Show, Eq )+newtype Cheermotes = Cheermotes { broadcasterId :: Integer } deriving ( Show, Eq )  instance Req.HelixRequest Cheermotes where     toRequest c =
src/Web/TwitchAPI/Helix/ChannelPoints.hs view
@@ -1,7 +1,6 @@-{-# LANGUAGE DuplicateRecordFields #-}-{-# LANGUAGE RecordWildCards       #-}-{-# LANGUAGE OverloadedStrings     #-}-{-# LANGUAGE ScopedTypeVariables   #-}+{-# LANGUAGE RecordWildCards     #-}+{-# LANGUAGE OverloadedStrings   #-}+{-# LANGUAGE ScopedTypeVariables #-}  module Web.TwitchAPI.Helix.ChannelPoints where @@ -21,33 +20,41 @@  import qualified Web.TwitchAPI.Helix.Request as Req -data Create = Create { broadcasterId :: Integer+class RewardDetails a where+    broadcasterId :: a -> Integer+    prompt :: a -> Maybe String+    backgroundColor :: a -> String+    maxPerStream :: a -> Maybe Integer+    maxPerUser :: a -> Maybe Integer+    autoFulfilled :: a -> Bool++data Create = Create { forBroadcasterId :: Integer                      , title :: String-                     , prompt :: Maybe String+                     , setPrompt :: Maybe String                      , cost :: Integer                      , enabled :: Maybe Bool-                     , backgroundColor :: Maybe String-                     , maxPerStream :: Maybe Integer-                     , maxPerUser :: Maybe Integer+                     , setBackgroundColor :: Maybe String+                     , setMaxPerStream :: Maybe Integer+                     , setMaxPerUser :: Maybe Integer                      , cooldownSeconds :: Maybe Integer-                     , autoFulfilled :: Maybe Bool+                     , setAutoFulfilled :: Maybe Bool                      } deriving ( Show, Eq )  instance ToJSON Create where     toJSON Create{..} =-        object [ "title"      .= (Text.pack title)-               , "prompt"     .= (Text.pack <$> prompt)+        object [ "title"      .= Text.pack title+               , "prompt"     .= (Text.pack <$> setPrompt)                , "cost"       .= cost-               , "is_enabled" .= (fromMaybe True enabled)-               , "background_color" .= (Text.pack <$> backgroundColor)-               , "is_user_input_required" .= (fmap (const True) prompt)-               , "is_max_per_stream_enabled" .= (fmap (const True) maxPerStream)-               , "max_per_stream" .= maxPerStream-               , "is_max_per_user_per_stream_enabled" .= (fmap (const True) maxPerUser)-               , "max_per_user_per_stream" .= maxPerUser-               , "is_global_cooldown_enabled" .= (fmap (const True) cooldownSeconds)+               , "is_enabled" .= fromMaybe True enabled+               , "background_color" .= (Text.pack <$> setBackgroundColor)+               , "is_user_input_required" .= fmap (const True) setPrompt+               , "is_max_per_stream_enabled" .= fmap (const True) setMaxPerStream+               , "max_per_stream" .= setMaxPerStream+               , "is_max_per_user_per_stream_enabled" .= fmap (const True) setMaxPerUser+               , "max_per_user_per_stream" .= setMaxPerUser+               , "is_global_cooldown_enabled" .= fmap (const True) cooldownSeconds                , "global_cooldown_seconds" .= cooldownSeconds-               , "should_redemptions_skip_request_queue" .= autoFulfilled+               , "should_redemptions_skip_request_queue" .= setAutoFulfilled                ]  instance Req.HelixRequest Create where@@ -57,6 +64,14 @@         in setBody . setQuery $ HTTP.parseRequest_ "POST https://api.twitch.tv/helix/channel_points/custom_rewards"     scope Create{} = Just "channel:manage:redemptions" +instance RewardDetails Create where+    broadcasterId = forBroadcasterId+    prompt = setPrompt+    backgroundColor = fromMaybe "" . setBackgroundColor+    maxPerStream = setMaxPerStream+    maxPerUser = setMaxPerUser+    autoFulfilled = fromMaybe False . setAutoFulfilled+ data RewardImages = RewardImages { tiny :: Maybe String                                  , large :: Maybe String                                  , huge :: Maybe String@@ -69,22 +84,22 @@         huge <- o .: "url_4x"         return RewardImages{..} -data CreateResponse = CreateResponse { broadcasterId :: Integer+data CreateResponse = CreateResponse { broadcaster :: Integer                                      , broadcasterLogin :: String                                      , broadcasterName :: String                                      , rewardId :: String                                      , rewardTitle :: String-                                     , prompt :: Maybe String+                                     , rewardPrompt :: Maybe String                                      , rewardCost :: Integer                                      , rewardImage :: Maybe RewardImages                                      , defaultImage :: RewardImages-                                     , backgroundColor :: String-                                     , maxPerStream :: Maybe Integer-                                     , maxPerUser :: Maybe Integer-                                     , cooldownSeconds :: Maybe Integer+                                     , rewardBackgroundColor :: String+                                     , rewardMaxPerStream :: Maybe Integer+                                     , rewardMaxPerUser :: Maybe Integer+                                     , cooldown :: Maybe Integer                                      , paused :: Bool                                      , inStock :: Bool-                                     , autoFulfilled :: Bool+                                     , rewardAutoFulfilled :: Bool                                      , redemptionCount :: Integer                                      , cooldownExpires :: Maybe Time.UTCTime                                      } deriving ( Show, Eq )@@ -92,7 +107,7 @@ instance FromJSON CreateResponse where     parseJSON = withObject "CreateResponse" $ \o -> do         bid <- o .: "broadcaster_id"-        let broadcasterId = read bid :: Integer+        let broadcaster = read bid :: Integer         broadcasterLogin <- o .: "broadcaster_login"         broadcasterName <- o .: "broadcaster_name"         rewardId <- o .: "id"@@ -100,32 +115,40 @@          promptText <- o .: "prompt"         promptEnabled :: Bool <- o .: "is_user_input_required"-        let prompt = if promptEnabled then Just promptText else Nothing+        let rewardPrompt = if promptEnabled then Just promptText else Nothing          rewardCost <- o .: "cost"         rewardImage <- o .: "image"         defaultImage <- o .: "default_image"-        backgroundColor <- o .: "background_color"+        rewardBackgroundColor <- o .: "background_color"          maxObject :: Object <- o .: "max_per_stream_setting"         maxEnabled <- maxObject .: "is_enabled"         streamMax <- maxObject .: "max_per_stream"-        let maxPerStream = if maxEnabled then Just streamMax else Nothing+        let rewardMaxPerStream = if maxEnabled then Just streamMax else Nothing          userMaxObject :: Object <- o .: "max_per_user_per_stream_setting"         userMaxEnabled <- userMaxObject .: "is_enabled"         userMax <- userMaxObject .: "max_per_user_per_stream"-        let maxPerUser = if userMaxEnabled then Just userMax else Nothing+        let rewardMaxPerUser = if userMaxEnabled then Just userMax else Nothing          cooldownObject :: Object <- o .: "global_cooldown_setting"         cooldownEnabled <- cooldownObject .: "is_enabled"-        cooldown <- cooldownObject .: "global_cooldown_seconds"-        let cooldownSeconds = if cooldownEnabled then Just cooldown else Nothing+        cooldownSeconds <- cooldownObject .: "global_cooldown_seconds"+        let cooldown = if cooldownEnabled then Just cooldownSeconds else Nothing          paused <- o .: "is_paused"         inStock <- o .: "is_in_stock"-        autoFulfilled <- o .: "should_redemptions_skip_request_queue"+        rewardAutoFulfilled <- o .: "should_redemptions_skip_request_queue"         redemptionCount <- o .: "redemptions_redeemed_current_stream"         cooldownExpiry :: Maybe String <- o .: "cooldown_expires_at"         let cooldownExpires = Time.zonedTimeToUTC <$> (Time.parseTimeRFC3339 =<< cooldownExpiry)         return CreateResponse{..}++instance RewardDetails CreateResponse where+    broadcasterId = broadcaster+    prompt = rewardPrompt+    backgroundColor = rewardBackgroundColor+    maxPerStream = rewardMaxPerStream+    maxPerUser = rewardMaxPerUser+    autoFulfilled = rewardAutoFulfilled
src/Web/TwitchAPI/Helix/Request.hs view
@@ -1,5 +1,3 @@-{-# LANGUAGE DuplicateRecordFields #-}- module Web.TwitchAPI.Helix.Request where  import Prelude
src/Web/TwitchAPI/Helix/Users.hs view
@@ -1,7 +1,6 @@-{-# LANGUAGE DuplicateRecordFields #-}-{-# LANGUAGE OverloadedStrings     #-}-{-# LANGUAGE RecordWildCards       #-}-{-# LANGUAGE ScopedTypeVariables   #-}+{-# LANGUAGE OverloadedStrings   #-}+{-# LANGUAGE RecordWildCards     #-}+{-# LANGUAGE ScopedTypeVariables #-}  module Web.TwitchAPI.Helix.Users where @@ -24,15 +23,33 @@ --   - Block/Unblock User --   - Update User Extensions -data User = User { lookupID :: Maybe String+class DisplayName a where+    displayName :: a -> String++class ExtensionId a where+    extensionId :: a -> String++class IsActive a where+    active :: a -> Bool++class Named a where+    name :: a -> String++class UserId a where+    userId :: a -> Integer++class Versioned a where+    version :: a -> String++data User = User { lookupId :: Maybe String                  , username :: Maybe String                  } deriving ( Show )  instance Req.HelixRequest User where     toRequest user =-        let lookupID' :: [(BS.ByteString, Maybe BS.ByteString)] = maybe [] (\i -> [("id", Just . BS.pack . show $ i)]) (lookupID user)+        let lookupId' :: [(BS.ByteString, Maybe BS.ByteString)] = maybe [] (\i -> [("id", Just . BS.pack . show $ i)]) (lookupId user)             username' :: [(BS.ByteString, Maybe BS.ByteString)] = maybe [] (\u -> [("login", Just . BS.pack $ u)]) (username user)-            setQuery = HTTP.setQueryString $ lookupID' ++ username'+            setQuery = HTTP.setQueryString $ lookupId' ++ username'         in setQuery $ HTTP.parseRequest_ "GET https://api.twitch.tv/helix/users"     scope User{} = Just "user:read:email" @@ -53,8 +70,8 @@  data UserEntry = UserEntry { broadcasterType :: BroadcasterType                            , description     :: String-                           , displayName     :: String-                           , userId          :: Integer+                           , userDisplayName :: String+                           , userEntryId     :: Integer                            , login           :: String                            , offlineImageURL :: String                            , profileImageURL :: String@@ -69,28 +86,34 @@         created :: String <- o .: "created_at"         userType' :: String <- o .: "type"         broadcasterType' :: String <- o .: "broadcaster_type"-        let userId = read userId' :: Integer+        let userEntryId = read userId' :: Integer             createdAt = Time.zonedTimeToUTC <$> Time.parseTimeRFC3339 created             userType = read userType' :: UserType             broadcasterType = read broadcasterType' :: BroadcasterType          description <- o .: "description"-        displayName <- o .: "display_name"+        userDisplayName <- o .: "display_name"         login <- o .: "login"         offlineImageURL <- o .: "offline_image_url"         profileImageURL <- o .: "profile_image_url"         email <- o .: "email"         return UserEntry{..} -data Users = Users { lookupIDs :: [Integer]+instance DisplayName UserEntry where+    displayName = userDisplayName++instance UserId UserEntry where+    userId = userEntryId++data Users = Users { lookupIds :: [Integer]                    , usernames :: [String]                    } deriving ( Show, Eq )  instance Req.HelixRequest Users where     toRequest users =-        let lookupID' :: [(BS.ByteString, Maybe BS.ByteString)] = (\i -> ("id", Just . BS.pack . show $ i)) <$> lookupIDs users+        let lookupId' :: [(BS.ByteString, Maybe BS.ByteString)] = (\i -> ("id", Just . BS.pack . show $ i)) <$> lookupIds users             username' :: [(BS.ByteString, Maybe BS.ByteString)] = (\u -> ("login", Just . BS.pack $ u)) <$> usernames users-            setQuery = HTTP.setQueryString $ lookupID' ++ username'+            setQuery = HTTP.setQueryString $ lookupId' ++ username'         in setQuery $ HTTP.parseRequest_ "GET https://api.twitch.tv/helix/users"     scope Users{} = Nothing @@ -111,27 +134,27 @@     toRequest user =         let after' :: [(BS.ByteString, Maybe BS.ByteString)] = maybe [] (\a -> [("after", Just . BS.pack $ a)]) (after user)             max' :: [(BS.ByteString, Maybe BS.ByteString)] = maybe [] (\u -> [("first", Just . BS.pack . show $ u)]) (from user)-            fromID' :: [(BS.ByteString, Maybe BS.ByteString)] = maybe [] (\u -> [("after", Just . BS.pack . show $ u)]) (from user)-            toID' :: [(BS.ByteString, Maybe BS.ByteString)] = maybe [] (\u -> [("after", Just . BS.pack . show $ u)]) (to user)-            setQuery = HTTP.setQueryString $ concat [after', max', fromID', toID']+            fromId' :: [(BS.ByteString, Maybe BS.ByteString)] = maybe [] (\u -> [("after", Just . BS.pack . show $ u)]) (from user)+            toId' :: [(BS.ByteString, Maybe BS.ByteString)] = maybe [] (\u -> [("after", Just . BS.pack . show $ u)]) (to user)+            setQuery = HTTP.setQueryString $ concat [after', max', fromId', toId']         in setQuery $ HTTP.parseRequest_ "GET https://api.twitch.tv/helix/users/follows"     scope Follows{} = Nothing -data FollowEntry = FollowEntry { fromID :: Integer+data FollowEntry = FollowEntry { fromId :: Integer                                , fromLogin :: String                                , fromName :: String-                               , toID :: Integer+                               , toId :: Integer                                , toName :: String                                , followedAt :: Maybe Time.UTCTime                                } deriving ( Show, Eq )  instance FromJSON FollowEntry where     parseJSON = withObject "FollowEntry" $ \o -> do-        fromID' :: String <- o .: "from_id"-        toID' :: String <- o .: "to_id"+        fromId' :: String <- o .: "from_id"+        toId' :: String <- o .: "to_id"         followedAt' :: String <- o .: "followed_at"-        let fromID = read fromID' :: Integer-            toID = read toID' :: Integer+        let fromId = read fromId' :: Integer+            toId = read toId' :: Integer             followedAt = Time.zonedTimeToUTC <$> Time.parseTimeRFC3339 followedAt'         fromLogin <- o .: "from_login"         fromName <- o .: "from_name"@@ -139,7 +162,7 @@         return FollowEntry{..}  data FollowsResponse = FollowsResponse { total :: Integer-                                       , users :: [FollowEntry]+                                       , follows :: [FollowEntry]                                        , paginationCursor :: String                                        } deriving ( Show, Eq ) @@ -147,30 +170,36 @@     parseJSON = withObject "FollowsResponse" $ \o -> do         total <- o .: "total"         paginationCursor <- (o .: "pagination") >>= (.: "cursor")-        users <- o .: "data"+        follows <- o .: "data"         return FollowsResponse{..} -newtype BlockList = BlockList { broadcasterID :: Integer } deriving ( Show, Eq )+newtype BlockList = BlockList { broadcasterId :: Integer } deriving ( Show, Eq )  instance Req.HelixRequest BlockList where     toRequest user =-        HTTP.setQueryString [("login", Just . BS.pack . show . broadcasterID $ user)] $+        HTTP.setQueryString [("login", Just . BS.pack . show . broadcasterId $ user)] $             HTTP.parseRequest_ "https://api.twitch.tv/helix/users/blocks"     scope BlockList{} = Just "user:read:blocked_users" -data BlockListEntry = BlockListEntry { userId :: Integer+data BlockListEntry = BlockListEntry { blockedUserId :: Integer                                      , userLogin :: String-                                     , displayName :: String+                                     , blockedDisplayName :: String                                      } deriving ( Show, Eq )  instance FromJSON BlockListEntry where     parseJSON = withObject "BlockListEntry" $ \o -> do         userId' :: String <- o .: "user_id"-        let userId = read userId' :: Integer+        let blockedUserId = read userId' :: Integer         userLogin <- o .: "user_login"-        displayName <- o .: "display_name"+        blockedDisplayName <- o .: "display_name"         return BlockListEntry{..} +instance DisplayName BlockListEntry where+    displayName = blockedDisplayName++instance UserId BlockListEntry where+    userId = blockedUserId+ newtype BlockListResponse = BlockListResponse { blocks :: [BlockListEntry] } deriving ( Show, Eq )  instance FromJSON BlockListResponse where@@ -194,20 +223,26 @@     readsPrec _ _           = mempty  data ExtensionsEntry = ExtensionsEntry { canActivate :: Bool-                                       , extensionId :: String-                                       , name :: String+                                       , extensionEntryId :: String+                                       , extensionName :: String                                        , extensionTypes :: [ExtensionType]-                                       , version :: String+                                       , extensionVersion :: String                                        } deriving ( Show, Eq ) +instance ExtensionId ExtensionsEntry where+    extensionId = extensionEntryId++instance Versioned ExtensionsEntry where+    version = extensionVersion+ instance FromJSON ExtensionsEntry where     parseJSON = withObject "ExtensionsEntry" $ \o -> do         extensionTypes' :: [String] <- o .: "type"         let extensionTypes :: [ExtensionType] = read <$> extensionTypes'         canActivate <- o .: "can_activate"-        extensionId <- o .: "id"-        name <- o .: "name"-        version <- o .: "version"+        extensionEntryId <- o .: "id"+        extensionName <- o .: "name"+        extensionVersion <- o .: "version"         return ExtensionsEntry{..}  newtype ExtensionsResponse = ExtensionsResponse { extensions :: [ExtensionsEntry] } deriving ( Show, Eq )@@ -217,44 +252,58 @@         extensions <- o .: "data"         return ExtensionsResponse{..} -newtype ActiveExtensions = ActiveExtensions { userID :: Maybe Integer } deriving ( Show, Eq )+data ActiveExtensions = ActiveExtensions+                      | ActiveExtensionsFor Integer deriving ( Show, Eq )  instance Req.HelixRequest ActiveExtensions where-    toRequest user =-        let userID' :: [(BS.ByteString, Maybe BS.ByteString)] = maybe [] (\i -> [("user_id", Just . BS.pack . show $ i)]) (userID user)-            setQuery = HTTP.setQueryString userID'+    toRequest (ActiveExtensionsFor i) =+        let setQuery = HTTP.setQueryString [("user_id", Just . BS.pack . show $ i)]         in setQuery $ HTTP.parseRequest_ "GET https://api.twitch.tv/helix/users/extensions"-    scope ActiveExtensions{} = Nothing+    toRequest ActiveExtensions = HTTP.parseRequest_ "GET https://api.twitch.tv/helix/users/extensions"+    scope ActiveExtensions = Nothing+    scope (ActiveExtensionsFor _) = Nothing -data ActiveComponentExtensionEntry' = ActiveComponentExtensionEntry' { active :: Bool-                                                                     , extensionId :: String-                                                                     , version :: String-                                                                     , name :: String-                                                                     , x :: Integer-                                                                     , y :: Integer+data ActiveComponentExtensionEntry' = ActiveComponentExtensionEntry' { activeComponentActive' :: Bool+                                                                     , activeComponentExtensionId' :: String+                                                                     , activeComponentVersion' :: String+                                                                     , activeComponentName' :: String+                                                                     , activeComponentX :: Integer+                                                                     , activeComponentY :: Integer                                                                      }                                     | InactiveComponentExtension deriving ( Show, Eq )  instance FromJSON ActiveComponentExtensionEntry' where     parseJSON = withObject "ActiveExtensionEntry" $ \o -> do-        active <- o .: "active"-        if active then do-            extensionId <- o .: "id"-            version <- o .: "version"-            name <- o .: "name"-            x <- o .: "x"-            y <- o .: "y"+        activeComponentActive' <- o .: "active"+        if activeComponentActive' then do+            activeComponentExtensionId' <- o .: "id"+            activeComponentVersion' <- o .: "version"+            activeComponentName' <- o .: "name"+            activeComponentX <- o .: "x"+            activeComponentY <- o .: "y"             return ActiveComponentExtensionEntry'{..}         else return InactiveComponentExtension -data ActiveComponentExtensionEntry = ActiveComponentExtensionEntry { active :: Bool-                                                                   , extensionId :: String-                                                                   , version :: String-                                                                   , name :: String+data ActiveComponentExtensionEntry = ActiveComponentExtensionEntry { activeComponentExtensionActive :: Bool+                                                                   , activeComponentExtensionId :: String+                                                                   , activeComponentExtensionVersion :: String+                                                                   , activeComponentExtensionName :: String                                                                    , x :: Integer                                                                    , y :: Integer                                                                    } deriving ( Show, Eq ) +instance ExtensionId ActiveComponentExtensionEntry where+    extensionId = activeComponentExtensionId++instance IsActive ActiveComponentExtensionEntry where+    active = activeComponentExtensionActive++instance Named ActiveComponentExtensionEntry where+    name = activeComponentExtensionName++instance Versioned ActiveComponentExtensionEntry where+    version = activeComponentExtensionVersion+ filterActiveComponentExtensions :: [ActiveComponentExtensionEntry'] -> [ActiveComponentExtensionEntry] filterActiveComponentExtensions = reverse . foldl filterActiveComponentExtensions' [] @@ -262,28 +311,40 @@ filterActiveComponentExtensions' as InactiveComponentExtension = as filterActiveComponentExtensions' as (ActiveComponentExtensionEntry' _ i v n x y) = ActiveComponentExtensionEntry True i v n x y : as -data ActiveExtensionEntry' = ActiveExtensionEntry' { active :: Bool-                                                   , extensionId :: String-                                                   , version :: String-                                                   , name :: String-                                                   } +data ActiveExtensionEntry' = ActiveExtensionEntry' { activeExtensionActive' :: Bool+                                                   , activeExtensionExtensionId' :: String+                                                   , activeExtensionVersion' :: String+                                                   , activeExtensionName' :: String+                                                   }                           | InactiveExtension deriving ( Show, Eq )  instance FromJSON ActiveExtensionEntry' where     parseJSON = withObject "ActiveExtensionEntry" $ \o -> do-        active <- o .: "active"-        if active then do-            extensionId <- o .: "id"-            version <- o .: "version"-            name <- o .: "name"+        activeExtensionActive' <- o .: "active"+        if activeExtensionActive' then do+            activeExtensionExtensionId' <- o .: "id"+            activeExtensionVersion' <- o .: "version"+            activeExtensionName' <- o .: "name"             return ActiveExtensionEntry'{..}         else return InactiveExtension -data ActiveExtensionEntry = ActiveExtensionEntry { active :: Bool-                                                 , extensionId :: String-                                                 , version :: String-                                                 , name :: String+data ActiveExtensionEntry = ActiveExtensionEntry { activeExtensionActive :: Bool+                                                 , activeExtensionId :: String+                                                 , activeExtensionVersion :: String+                                                 , activeExtensionName :: String                                                  } deriving ( Show, Eq )++instance IsActive ActiveExtensionEntry where+    active = activeExtensionActive++instance ExtensionId ActiveExtensionEntry where+    extensionId = activeExtensionId++instance Versioned ActiveExtensionEntry where+    version = activeExtensionVersion++instance Named ActiveExtensionEntry where+    name = activeExtensionName  filterActiveExtensions :: [ActiveExtensionEntry'] -> [ActiveExtensionEntry] filterActiveExtensions = reverse . foldl filterActiveExtensions' []
twitchapi.cabal view
@@ -1,5 +1,5 @@ name:                twitchapi-version:             0.0.2+version:             0.0.3 synopsis:            Client access to Twitch.tv API endpoints description:         Twitch.tv API client supporting Helix and PubSub homepage:            https://github.com/wuest/haskell-twitchapi