ig 0.5 → 0.5.1
raw patch · 3 files changed
+122/−121 lines, 3 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
+ Instagram: IGAppException :: IGError -> IGException
+ Instagram: IGError :: Int -> Maybe Text -> Maybe Text -> IGError
+ Instagram: JSONException :: String -> IGException
+ Instagram: data IGError
+ Instagram: igeCode :: IGError -> Int
+ Instagram: igeMessage :: IGError -> Maybe Text
+ Instagram: igeType :: IGError -> Maybe Text
Files
- ig.cabal +1/−1
- src/Instagram.hs +2/−1
- src/Instagram/Types.hs +119/−119
ig.cabal view
@@ -1,5 +1,5 @@ name: ig-version: 0.5+version: 0.5.1 synopsis: Bindings to Instagram's API. homepage: https://github.com/prowdsponsor/ig license: BSD3
src/Instagram.hs view
@@ -5,7 +5,8 @@ InstagramT ,runInstagramT ,runResourceInIs- ,IGException+ ,IGException(..)+ ,IGError(..) -- authentication ,RedirectUri
src/Instagram/Types.hs view
@@ -13,7 +13,7 @@ ,IGException(..) ,Envelope(..) ,ErrEnvelope(..)- ,IGError+ ,IGError(..) ,Pagination(..) ,MediaID ,Media(..)@@ -61,7 +61,7 @@ ,cClientSecret :: Text -- ^ client secret } deriving (Show,Read,Eq,Ord,Typeable)- + -- | get client id in ByteString form clientIDBS :: Credentials -> ByteString clientIDBS=TE.encodeUtf8 . cClientID@@ -69,7 +69,7 @@ -- | get client secret in ByteString form clientSecretBS :: Credentials -> ByteString clientSecretBS=TE.encodeUtf8 . cClientSecret- + -- | the oauth token returned after authentication data OAuthToken = OAuthToken { oaAccessToken :: AccessToken -- ^ the access token@@ -79,22 +79,22 @@ -- | to json as per Instagram format instance ToJSON OAuthToken where- toJSON oa=object ["access_token" .= oaAccessToken oa, "user" .= oaUser oa] + toJSON oa=object ["access_token" .= oaAccessToken oa, "user" .= oaUser oa] --- | from json as per Instagram format +-- | from json as per Instagram format instance FromJSON OAuthToken where parseJSON (Object v) =OAuthToken <$> v .: "access_token" <*>- v .: "user" + v .: "user" parseJSON _= fail "OAuthToken" -- | the access token is simply a Text newtype AccessToken=AccessToken Text deriving (Eq, Ord, Read, Show, Typeable)- --- | simple string ++-- | simple string instance ToJSON AccessToken where- toJSON (AccessToken at)=String at + toJSON (AccessToken at)=String at -- | simple string instance FromJSON AccessToken where@@ -104,7 +104,7 @@ -- | User ID type UserID = Text --- | the User partial profile returned by the authentication +-- | the User partial profile returned by the authentication data User = User { uID :: UserID, uUsername :: Text,@@ -115,8 +115,8 @@ uCounts :: Maybe UserCounts } deriving (Show,Read,Eq,Ord,Typeable)- --- | to json as per Instagram format ++-- | to json as per Instagram format instance ToJSON User where toJSON u = object [ "id" .= uID u@@ -174,10 +174,10 @@ ,igeMessage :: Maybe Text } deriving (Show,Read,Eq,Ord,Typeable)- --- | to json as per Instagram format ++-- | to json as per Instagram format instance ToJSON IGError where- toJSON e=object ["code" .= igeCode e, "error_type" .= igeType e , "error_message" .= igeMessage e] + toJSON e=object ["code" .= igeCode e, "error_type" .= igeType e , "error_message" .= igeMessage e] -- | from json as per Instagram format instance FromJSON IGError where@@ -192,21 +192,21 @@ | IGAppException IGError -- ^ application exception deriving (Show,Typeable) --- | make our exception type a normal exception -instance Exception IGException +-- | make our exception type a normal exception+instance Exception IGException -- | envelope for Instagram OK response data Envelope d=Envelope{ eMeta :: IGError -- ^ this should only say 200, no error, but put here for completeness- ,eData :: d -- ^ data, garanteed to be present (otherwise we get an ErrEnvelope) + ,eData :: d -- ^ data, garanteed to be present (otherwise we get an ErrEnvelope) ,ePagination :: Maybe Pagination } deriving (Show,Read,Eq,Ord,Typeable)- --- | to json as per Instagram format ++-- | to json as per Instagram format instance (ToJSON d)=>ToJSON (Envelope d) where- toJSON e=object ["meta" .= eMeta e, "data" .= eData e, "pagination" .= ePagination e] - + toJSON e=object ["meta" .= eMeta e, "data" .= eData e, "pagination" .= ePagination e]+ -- | from json as per Instagram format instance (FromJSON d)=>FromJSON (Envelope d) where parseJSON (Object v) =Envelope <$>@@ -220,18 +220,18 @@ eeMeta :: IGError } deriving (Show,Read,Eq,Ord,Typeable)- --- | to json as per Instagram format ++-- | to json as per Instagram format instance ToJSON ErrEnvelope where- toJSON e=object ["meta" .= eeMeta e] - + toJSON e=object ["meta" .= eeMeta e]+ -- | from json as per Instagram format instance FromJSON ErrEnvelope where parseJSON (Object v) =ErrEnvelope <$> v .: "meta" parseJSON _= fail "ErrEnvelope" --- | pagination info for responses that can return a lot of data +-- | pagination info for responses that can return a lot of data data Pagination = Pagination { pNextUrl :: Maybe Text ,pNextMaxID :: Maybe Text@@ -240,10 +240,10 @@ ,pMinTagID :: Maybe Text } deriving (Show,Read,Eq,Ord,Typeable)- --- | to json as per Instagram format ++-- | to json as per Instagram format instance ToJSON Pagination where- toJSON p=object ["next_url" .= pNextUrl p, "next_max_id" .= pNextMaxID p, "next_min_id" .= pNextMinID p, "next_max_tag_id" .= pNextMaxTagID p,"min_tag_id" .= pMinTagID p] + toJSON p=object ["next_url" .= pNextUrl p, "next_max_id" .= pNextMaxID p, "next_min_id" .= pNextMinID p, "next_max_tag_id" .= pNextMaxTagID p,"min_tag_id" .= pMinTagID p] -- | from json as per Instagram format instance FromJSON Pagination where@@ -253,17 +253,17 @@ v .:? "next_min_id" <*> v .:? "next_max_tag_id" <*> v .:? "min_tag_id"- parseJSON _= fail "Pagination" - + parseJSON _= fail "Pagination"+ -- | Media ID type MediaID=Text- + -- | instagram media object data Media = Media { mID :: MediaID ,mCaption :: Maybe Comment ,mLink :: Text- ,mUser :: User + ,mUser :: User ,mCreated :: POSIXTime ,mImages :: Images ,mType :: Text@@ -275,14 +275,14 @@ ,mLikes :: Collection User ,mUserHasLiked :: Bool ,mAttribution :: Maybe Object -- ^ seems to be open format https://groups.google.com/forum/?fromgroups#!topic/instagram-api-developers/KvGH1cnjljQ- } + } deriving (Show,Eq,Typeable)- --- | to json as per Instagram format ++-- | to json as per Instagram format instance ToJSON Media where toJSON m=object ["id" .= mID m,"caption" .= mCaption m,"user".= mUser m,"link" .= mLink m, "created_time" .= toJSON (show ((round $ mCreated m) :: Integer)) ,"images" .= mImages m,"type" .= mType m,"users_in_photo" .= mUsersInPhoto m, "filter" .= mFilter m,"tags" .= mTags m- ,"location" .= mLocation m,"comments" .= mComments m,"likes" .= mLikes m,"user_has_liked" .= mUserHasLiked m,"attribution" .= mAttribution m] + ,"location" .= mLocation m,"comments" .= mComments m,"likes" .= mLikes m,"user_has_liked" .= mUserHasLiked m,"attribution" .= mAttribution m] -- | from json as per Instagram format instance FromJSON Media where@@ -304,7 +304,7 @@ v .:? "likes" .!= Collection 0 [] <*> v .:? "user_has_liked" .!= False <*> v .:? "attribution"- parseJSON _= fail "Media" + parseJSON _= fail "Media" -- | position in picture data Position = Position {@@ -312,34 +312,34 @@ ,pY :: Double } deriving (Show,Eq,Typeable) - --- | to json as per Instagram format ++-- | to json as per Instagram format instance ToJSON Position where toJSON p=object ["x" .= pX p,"y" .= pY p]- + -- | from json as per Instagram format instance FromJSON Position where parseJSON (Object v) = Position <$> v .: "x" <*>- v .: "y" + v .: "y" parseJSON _=fail "Position"- + -- | position of a user data UserPosition = UserPosition { upPosition :: Position ,upUser :: User } deriving (Show,Eq,Typeable) - --- | to json as per Instagram format ++-- | to json as per Instagram format instance ToJSON UserPosition where toJSON p=object ["position" .= upPosition p,"user" .= upUser p]- + -- | from json as per Instagram format instance FromJSON UserPosition where parseJSON (Object v) = UserPosition <$> v .: "position" <*>- v .: "user" + v .: "user" parseJSON _=fail "UserPosition" -- | location ID@@ -352,23 +352,23 @@ ,lLongitude :: Maybe Double ,lStreetAddress :: Maybe Text ,lName :: Maybe Text- } + } deriving (Show,Eq,Ord,Typeable)- --- | to json as per Instagram format ++-- | to json as per Instagram format instance ToJSON Location where toJSON l=object ["id" .= lID l,"latitude" .= lLatitude l,"longitude" .= lLongitude l, "street_address" .= lStreetAddress l,"name" .= lName l]- + -- | from json as per Instagram format instance FromJSON Location where- parseJSON (Object v) = + parseJSON (Object v) = Location <$> parseID v <*> v .:? "latitude" <*> v .:? "longitude" <*> v .:? "street_address" <*> v .:? "name"- where + where -- | the Instagram API hasn't made its mind up, sometimes location id is an int, sometimes a string parseID :: Object -> Parser (Maybe LocationID) parseID obj=case HM.lookup "id" obj of@@ -377,50 +377,50 @@ Nothing->pure Nothing _->fail "LocationID" parseJSON _= fail "Location"- + -- | data for a single image data ImageData = ImageData { idURL :: Text, idWidth :: Integer, idHeight :: Integer- } + } deriving (Show,Eq,Ord,Typeable)- --- | to json as per Instagram format ++-- | to json as per Instagram format instance ToJSON ImageData where toJSON i=object ["url" .= idURL i,"width" .= idWidth i,"height" .= idHeight i]- + -- | from json as per Instagram format instance FromJSON ImageData where parseJSON (Object v) = ImageData <$> v .: "url" <*> v .: "width" <*> v .: "height"- parseJSON _= fail "ImageData" - + parseJSON _= fail "ImageData"+ -- | different images for the same media data Images = Images { iLowRes :: ImageData ,iThumbnail :: ImageData ,iStandardRes :: ImageData }- deriving (Show,Eq,Ord,Typeable) - --- | to json as per Instagram format + deriving (Show,Eq,Ord,Typeable)++-- | to json as per Instagram format instance ToJSON Images where toJSON i=object ["low_resolution" .= iLowRes i,"thumbnail" .= iThumbnail i,"standard_resolution" .= iStandardRes i]- + -- | from json as per Instagram format instance FromJSON Images where parseJSON (Object v) = Images <$> v .: "low_resolution" <*> v .: "thumbnail" <*> v .: "standard_resolution"- parseJSON _= fail "Images" - + parseJSON _= fail "Images"+ -- | comment id type CommentID = Text- + -- | Commenton on a medium data Comment = Comment { cID :: CommentID@@ -428,12 +428,12 @@ ,cText :: Text ,cFrom :: User }- deriving (Show,Eq,Ord,Typeable) + deriving (Show,Eq,Ord,Typeable) --- | to json asCommentstagram format +-- | to json asCommentstagram format instance ToJSON Comment where toJSON c=object ["id" .= cID c,"created_time" .= toJSON (show ((round $ cCreated c) :: Integer))- ,"text" .= cText c,"from" .= cFrom c] + ,"text" .= cText c,"from" .= cFrom c] -- | from json asCommentstagram format instance FromJSON Comment where@@ -443,8 +443,8 @@ v .: "id" <*> pure (fromIntegral (read ct::Integer)) <*> v .: "text" <*>- v .: "from" - parseJSON _= fail "Caption" + v .: "from"+ parseJSON _= fail "Caption" -- | a collection of items (count + data) -- data can only be a subset@@ -452,10 +452,10 @@ cCount :: Integer ,cData :: [a] }- deriving (Show,Eq,Ord,Typeable) + deriving (Show,Eq,Ord,Typeable) - --- | to json as per Instagram format ++-- | to json as per Instagram format instance (ToJSON a)=>ToJSON (Collection a) where toJSON igc=object ["count" .= cCount igc,"data" .= cData igc] @@ -463,27 +463,27 @@ instance (FromJSON a)=>FromJSON (Collection a) where parseJSON (Object v) = Collection <$> v .: "count" <*>- v .: "data" - parseJSON _= fail "Collection" - + v .: "data"+ parseJSON _= fail "Collection" + -- | the URL to receive notifications to-type CallbackUrl = Text - +type CallbackUrl = Text+ -- | notification aspect data Aspect = Aspect Text deriving (Show, Read, Eq, Ord, Typeable)- --- | to json as per Instagram format ++-- | to json as per Instagram format instance ToJSON Aspect where toJSON (Aspect t)=String t -- | from json as per Instagram format instance FromJSON Aspect where parseJSON (String t) = pure $ Aspect t- parseJSON _= fail "Aspect" + parseJSON _= fail "Aspect" --- | the media Aspect, the only one supported for now +-- | the media Aspect, the only one supported for now media :: Aspect media = Aspect "media" @@ -498,10 +498,10 @@ ,sLatitude :: Maybe Double ,sLongitude :: Maybe Double ,sRadius :: Maybe Integer- } + } deriving (Show,Eq,Typeable)- --- | to json as per Instagram format ++-- | to json as per Instagram format instance ToJSON Subscription where toJSON s=object ["id" .= sID s,"type" .= sType s,"object" .= sObject s,"object_id" .= sObjectID s,"aspect" .= sAspect s ,"callback_url".=sCallbackUrl s,"lat".= sLatitude s,"lng".=sLongitude s,"radius".=sRadius s]@@ -518,9 +518,9 @@ v .:? "lat" <*> v .:? "lng" <*> v .:? "radius"- parseJSON _= fail "Subscription" - --- | an update from a subscription + parseJSON _= fail "Subscription"++-- | an update from a subscription data Update = Update { uSubscriptionID :: Integer ,uObject :: Text@@ -529,11 +529,11 @@ ,uTime :: POSIXTime } deriving (Show,Eq,Typeable)- --- | to json as per Instagram format ++-- | to json as per Instagram format instance ToJSON Update where toJSON u=object ["subscription_id" .= uSubscriptionID u ,"object" .= uObject u,"object_id" .= uObjectID u- ,"changed_aspect" .= uChangedAspect u,"time" .= toJSON ((round $ uTime u) :: Integer)] + ,"changed_aspect" .= uChangedAspect u,"time" .= toJSON ((round $ uTime u) :: Integer)] -- | from json as per Instagram format instance FromJSON Update where@@ -545,34 +545,34 @@ v .: "object_id" <*> v .: "changed_aspect" <*> pure (fromIntegral ct)- parseJSON _= fail "Update" + parseJSON _= fail "Update" -- | Tag Name type TagName = Text --- | a Tag +-- | a Tag data Tag = Tag { tName :: TagName, tMediaCount :: Integer }- deriving (Show,Read,Eq,Ord,Typeable) - --- | to json as per Instagram format + deriving (Show,Read,Eq,Ord,Typeable)++-- | to json as per Instagram format instance ToJSON Tag where- toJSON t=object ["name" .= tName t,"media_count" .= tMediaCount t] + toJSON t=object ["name" .= tName t,"media_count" .= tMediaCount t] -- | from json as per Instagram format instance FromJSON Tag where parseJSON (Object v) = Tag <$> v .: "name" <*> v .:? "media_count" .!= 0- parseJSON _= fail "Tag" - --- | outgoing relationship status + parseJSON _= fail "Tag"++-- | outgoing relationship status data OutgoingStatus = Follows | Requested | OutNone deriving (Show,Read,Eq,Ord,Bounded,Enum,Typeable) --- | to json as per Instagram format +-- | to json as per Instagram format instance ToJSON OutgoingStatus where toJSON Follows = String "follows" toJSON Requested = String "requested"@@ -583,13 +583,13 @@ parseJSON (String "follows")=pure Follows parseJSON (String "requested")=pure Requested parseJSON (String "none")=pure OutNone- parseJSON _= fail "OutgoingStatus" - --- | incoming relationship status + parseJSON _= fail "OutgoingStatus"++-- | incoming relationship status data IncomingStatus = FollowedBy | RequestedBy | BlockedByYou | InNone deriving (Show,Read,Eq,Ord,Bounded,Enum,Typeable) --- | to json as per Instagram format +-- | to json as per Instagram format instance ToJSON IncomingStatus where toJSON FollowedBy = String "followed_by" toJSON RequestedBy = String "requested_by"@@ -602,19 +602,19 @@ parseJSON (String "requested_by")=pure RequestedBy parseJSON (String "blocked_by_you")=pure BlockedByYou parseJSON (String "none")=pure InNone- parseJSON _= fail "IncomingStatus" - + parseJSON _= fail "IncomingStatus"+ -- | a relationship between two users data Relationship = Relationship { rOutgoing :: OutgoingStatus ,rIncoming :: IncomingStatus ,rTargetUserPrivate :: Bool -- ^ not present in doc }- deriving (Show,Read,Eq,Ord,Typeable) + deriving (Show,Read,Eq,Ord,Typeable) --- | to json as per Instagram format +-- | to json as per Instagram format instance ToJSON Relationship where- toJSON r=object ["outgoing_status" .= rOutgoing r,"incoming_status" .= rIncoming r,"target_user_is_private" .= rTargetUserPrivate r] + toJSON r=object ["outgoing_status" .= rOutgoing r,"incoming_status" .= rIncoming r,"target_user_is_private" .= rTargetUserPrivate r] -- | from json as per Instagram format instance FromJSON Relationship where@@ -622,22 +622,22 @@ v .:? "outgoing_status" .!= OutNone <*> v .:? "incoming_status" .!= InNone <*> v .:? "target_user_is_private" .!= False- parseJSON _= fail "Relationship" + parseJSON _= fail "Relationship" -- | Instagram returns data:null for nothing, but Aeson considers that () maps to an empty array...--- so we model the fact that we expect null via NoResult +-- so we model the fact that we expect null via NoResult data NoResult = NoResult deriving (Show,Read,Eq,Ord,Typeable) --- | to json as per Instagram format +-- | to json as per Instagram format instance ToJSON NoResult where toJSON _=Null -- | from json as per Instagram format instance FromJSON NoResult where- parseJSON Null = pure NoResult - parseJSON _= fail "NoResult" + parseJSON Null = pure NoResult+ parseJSON _= fail "NoResult" --- | geography ID +-- | geography ID type GeographyID = Text