Skip to content

Instantly share code, notes, and snippets.

@killerswan
Created May 2, 2012 09:16
Show Gist options
  • Save killerswan/2575439 to your computer and use it in GitHub Desktop.
Save killerswan/2575439 to your computer and use it in GitHub Desktop.
Haskell namespaces seem weak
-- snip
updateStatus :: Token -> String -> IO ()
updateStatus token status = runOAuthM token $ do
_ <- doRequest POST "statuses/update" [("status",status)]
return ()
data StatusAttr = ReplyTo String
| LatLon Double Double
| PlaceID String
| DisplayCoords
deriving (Eq, Show)
updateStatusWithAttr :: Token -> String -> [StatusAttr] -> IO Status
updateStatusWithAttr token status attrs =
runOAuthM token . return . parseOne $ doRequest POST "statuses/update" query
where
processAttr :: StatusAttr -> [(String, String)]
processAttr (ReplyTo id) = [("in_reply_to_status_id", id)]
processAttr (LatLon lat lon) = [("lat", show lat), ("long", show lon)]
processAttr (PlaceID place) = [("place_id" place)]
processAttr DisplayCoords = [("display_coordinates", "true")] -- assume Twitter default is "false"
query = ("status", status) : (processAttr =<< attrs)
-- | Update the authenticating user's timeline with a status and an uploaded image
uploadImage :: Token -> String -> FilePath -> IO Status
uploadImage token status imageName =
uploadImageWithAttr token status imageName []
-- | Optional attributes for an image upload
data ImageAttr = PossiblySensitive -- note that this image is risqué
| ReplyTo String -- the tweet this is in reply to
| LatLon Double Double -- a latitude and longitude
| PlaceID String -- a location code retrieved from geo/reverse_geocode
| DisplayCoords -- tell Twitter to display the location
deriving (Eq, Show)
-- | Like `uploadImage`, but supporting the optional attributes in ImageAttr
uploadImageWithAttr :: Token -> String -> FilePath -> [ImageAttr] -> IO Status
uploadImageWithAttr token status imageName attrs =
runOAuthM token $ do
rsp <- doRequestMultipart POST "statuses/update_with_media" [] payload
return . parseOne $ rsp
where
-- make one FormDataPart
toPart :: String -> String -> FormDataPart
toPart name value =
FormDataPart
{ postName = name
, contentType = Just "form-data"
, content = ContentString value
, showName = Nothing
, extraHeaders = []
}
-- make any ImageAttr into FormDataPart(s)
processAttr :: ImageAttr -> [FormDataPart]
processAttr PossiblySensitive = [toPart "possibly_sensitive" "true"] -- assume Twitter default is "false"
processAttr (ReplyTo id) = [toPart "in_reply_to_status_id" id]
processAttr (LatLon lat lon) = [toPart "lat" (show lat), toPart "long" (show lon)]
processAttr (PlaceID place) = [toPart "place_id" place]
processAttr DisplayCoords = [toPart "display_coordinates" "true"] -- assume Twitter default is "false"
-- collect our set of parts
-- allowing duplicates, which Twitter may or may not reject
payload :: [FormDataPart]
payload =
[ toPart "status" status
, FormDataPart
{ postName = "media[]"
, contentType = Just "Content"
, content = ContentFile imageName
, showName = Nothing
, extraHeaders = []
}
]
++
(processAttr =<< attrs)
-- snip
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment