module Strive.Actions where
import Data.Aeson (FromJSON, Value, encode)
import Data.ByteString (ByteString)
import Data.ByteString.Char8 (unpack)
import Data.ByteString.Lazy (toStrict)
import Data.Default (Default, def)
import Data.List (intercalate)
import Data.Monoid ((<>))
import Data.Time.Clock (UTCTime)
import Network.HTTP.Conduit (RequestBody (RequestBodyBS), requestBody,
responseBody, responseStatus)
import Network.HTTP.Types (Query, methodDelete, methodPost, noContent204,
renderQuery, toQuery)
import Strive.Client (Client, buildClient)
import Strive.Internal.HTTP (buildRequest, decodeValue, delete, get,
performRequest, post, put)
import qualified Strive.Options as O
import qualified Strive.Types as T
with :: Default a => [a -> a] -> a
with = foldr ($) def
infixr 0 ?
(?) :: Default a => (a -> b) -> [a -> a] -> b
(?) = (. with)
buildAuthorizeUrl :: Integer -> String -> O.BuildAuthorizeUrlOptions -> String
buildAuthorizeUrl clientId redirectUri options =
"https://www.strava.com/oauth/authorize" <> unpack (renderQuery True query)
where
query = toQuery
[ ("client_id", show clientId)
, ("redirect_uri", redirectUri)
, ("response_type", "code")
] <> toQuery options
exchangeToken :: Integer -> String -> String -> IO (Either String T.TokenExchangeResponse)
exchangeToken clientId clientSecret code = do
client <- buildClient ""
post client resource query
where
resource = "oauth/token"
query =
[ ("client_id", show clientId)
, ("client_secret", clientSecret)
, ("code", code)
]
deauthorize :: Client -> IO (Either String T.DeauthorizationResponse)
deauthorize client = post client resource query
where
resource = "oauth/deauthorize"
query = [] :: Query
getCurrentAthlete :: Client -> IO (Either String T.AthleteDetailed)
getCurrentAthlete client = get client resource query
where
resource = "api/v3/athlete"
query = [] :: Query
getAthlete :: Client -> Integer -> IO (Either String T.AthleteSummary)
getAthlete client athleteId = get client resource query
where
resource = "api/v3/athletes/" <> show athleteId
query = [] :: Query
updateCurrentAthlete :: Client -> O.UpdateCurrentAthleteOptions -> IO (Either String T.AthleteDetailed)
updateCurrentAthlete client options = put client resource query
where
resource = "api/v3/athlete"
query = toQuery options
getAthleteCrs :: Client -> Integer -> O.GetAthleteCrsOptions -> IO (Either String [T.EffortDetailed])
getAthleteCrs client athleteId options = get client resource query
where
resource = "api/v3/athletes/" <> show athleteId <> "/koms"
query = toQuery options
getCurrentFriends :: Client -> O.GetCurrentFriendsOptions -> IO (Either String [T.AthleteSummary])
getCurrentFriends client options = get client resource query
where
resource = "api/v3/athlete/friends"
query = toQuery options
getFriends :: Client -> Integer -> O.GetFriendsOptions -> IO (Either String [T.AthleteSummary])
getFriends client athleteId options = get client resource query
where
resource = "api/v3/athletes/" <> show athleteId <> "/friends"
query = toQuery options
getCurrentFollowers :: Client -> O.GetCurrentFollowersOptions -> IO (Either String [T.AthleteSummary])
getCurrentFollowers client options = get client resource query
where
resource = "api/v3/athlete/followers"
query = toQuery options
getFollowers :: Client -> Integer -> O.GetFollowersOptions -> IO (Either String [T.AthleteSummary])
getFollowers client athleteId options = get client resource query
where
resource = "api/v3/athletes/" <> show athleteId <> "/followers"
query = toQuery options
getCommonFriends :: Client -> Integer -> O.GetCommonFriendsOptions -> IO (Either String [T.AthleteSummary])
getCommonFriends client athleteId options = get client resource query
where
resource = "api/v3/athletes/" <> show athleteId <> "/both-following"
query = toQuery options
createActivity :: Client -> String -> String -> UTCTime -> Integer -> O.CreateActivityOptions -> IO (Either String T.ActivityDetailed)
createActivity client name type_ startDateLocal elapsedTime options = post client resource query
where
resource = "api/v3/activities"
query = toQuery
[ ("name", name)
, ("type", type_)
, ("start_date_local", unpack (toStrict (encode startDateLocal)))
, ("elapsed_time", show elapsedTime)
] <> toQuery options
getActivity :: Client -> Integer -> O.GetActivityOptions -> IO (Either String T.ActivitySummary)
getActivity client activityId options = get client resource query
where
resource = "api/v3/activities/" <> show activityId
query = toQuery options
updateActivity :: Client -> Integer -> O.UpdateActivityOptions -> IO (Either String T.ActivityDetailed)
updateActivity client activityId options = put client resource query
where
resource = "api/v3/activities/" <> show activityId
query = toQuery options
deleteActivity :: Client -> Integer -> IO (Either String ())
deleteActivity client activityId = do
request <- buildRequest methodDelete client resource query
response <- performRequest client request
return (if responseStatus response == noContent204
then Right ()
else Left (unpack (toStrict (responseBody response))))
where
resource = "api/v3/activities/" <> show activityId
query = [] :: Query
getCurrentActivities :: Client -> O.GetCurrentActivitiesOptions -> IO (Either String [T.ActivitySummary])
getCurrentActivities client options = get client resource query
where
resource = "api/v3/athlete/activities"
query = toQuery options
getFeed :: Client -> O.GetFeedOptions -> IO (Either String [T.ActivitySummary])
getFeed client options = get client resource query
where
resource = "api/v3/activities/following"
query = toQuery options
getActivityZones :: Client -> Integer -> IO (Either String [T.ActivityZoneDetailed])
getActivityZones client activityId = get client resource query
where
resource = "api/v3/activities/" <> show activityId <> "/zones"
query = [] :: Query
getActivityLaps :: Client -> Integer -> IO (Either String [T.ActivityLapSummary])
getActivityLaps client activityId = get client resource query
where
resource = "api/v3/activities/" <> show activityId <> "/laps"
query = [] :: Query
getActivityComments :: Client -> Integer -> O.GetActivityCommentsOptions -> IO (Either String [T.CommentSummary])
getActivityComments client activityId options = get client resource query
where
resource = "api/v3/activities/" <> show activityId <> "/comments"
query = toQuery options
getActivityKudoers :: Client -> Integer -> O.GetActivityKudoersOptions -> IO (Either String [T.AthleteSummary])
getActivityKudoers client activityId options = get client resource query
where
resource = "api/v3/activities/" <> show activityId <> "/kudos"
query = toQuery options
getActivityPhotos :: Client -> Integer -> IO (Either String [T.PhotoSummary])
getActivityPhotos client activityId = get client resource query
where
resource = "api/v3/activities/" <> show activityId <> "/photos"
query = [] :: Query
getClub :: Client -> Integer -> IO (Either String T.ClubDetailed)
getClub client clubId = get client resource query
where
resource = "api/v3/clubs/" <> show clubId
query = [] :: Query
getCurrentClubs :: Client -> IO (Either String [T.ClubSummary])
getCurrentClubs client = get client resource query
where
resource = "api/v3/athlete/clubs"
query = [] :: Query
getClubMembers :: Client -> Integer -> O.GetClubMembersOptions -> IO (Either String [T.AthleteSummary])
getClubMembers client clubId options = get client resource query
where
resource = "api/v3/clubs/" <> show clubId <> "/members"
query = toQuery options
getClubActivities :: Client -> Integer -> O.GetClubActivitiesOptions -> IO (Either String [T.ActivitySummary])
getClubActivities client clubId options = get client resource query
where
resource = "api/v3/clubs/" <> show clubId <> "/activities"
query = toQuery options
getGear :: Client -> String -> IO (Either String T.GearDetailed)
getGear client gearId = get client resource query
where
resource = "api/v3/gear/" <> gearId
query = [] :: Query
getSegment :: Client -> Integer -> IO (Either String T.SegmentDetailed)
getSegment client segmentId = get client resource query
where
resource = "api/v3/segments/" <> show segmentId
query = [] :: Query
getStarredSegments :: Client -> O.GetStarredSegmentsOptions -> IO (Either String [T.SegmentSummary])
getStarredSegments client options = get client resource query
where
resource = "api/v3/segments/starred"
query = toQuery options
getSegmentEfforts :: Client -> Integer -> O.GetSegmentEffortsOptions -> IO (Either String [T.EffortDetailed])
getSegmentEfforts client segmentId options = get client resource query
where
resource = "api/v3/segments/" <> show segmentId <> "/all_efforts"
query = toQuery options
getSegmentLeaderboard :: Client -> Integer -> O.GetSegmentLeaderboardOptions -> IO (Either String T.SegmentLeaderboardResponse)
getSegmentLeaderboard client segmentId options = get client resource query
where
resource = "api/v3/segments/" <> show segmentId <> "/leaderboard"
query = toQuery options
exploreSegments :: Client -> (Double, Double, Double, Double) -> O.ExploreSegmentsOptions -> IO (Either String T.SegmentExplorerResponse)
exploreSegments client (south, west, north, east) options = get client resource query
where
resource = "api/v3/segments/explore"
query = toQuery
[ ("bounds", intercalate "," (fmap show [south, west, north, east]))
] <> toQuery options
getSegmentEffort :: Client -> Integer -> IO (Either String T.EffortDetailed)
getSegmentEffort client effortId = get client resource query
where
resource = "api/v3/segment_efforts/" <> show effortId
query = [] :: Query
getActivityStreams :: Client -> Integer -> [String] -> O.GetStreamsOptions -> IO (Either String [T.StreamDetailed])
getActivityStreams = flip getStreams "activities"
getEffortStreams :: Client -> Integer -> [String] -> O.GetStreamsOptions -> IO (Either String [T.StreamDetailed])
getEffortStreams = flip getStreams "segment_efforts"
getSegmentStreams :: Client -> Integer -> [String] -> O.GetStreamsOptions -> IO (Either String [T.StreamDetailed])
getSegmentStreams = flip getStreams "segments"
getStreams :: FromJSON a => Client -> String -> Integer -> [String] -> O.GetStreamsOptions -> IO (Either String a)
getStreams client kind id types options = get client resource query
where
resource = concat
[ "api/v3/"
, kind
, "/"
, show id
, "/streams/"
, intercalate "," types
]
query = toQuery options
uploadActivity :: Client -> ByteString -> String -> O.UploadActivityOptions -> IO (Either String T.UploadStatus)
uploadActivity client body dataType options = do
initialRequest <- buildRequest methodPost client resource query
let request = initialRequest
{ requestBody = RequestBodyBS body
}
response <- performRequest client request
return (decodeValue response)
where
resource = "api/v3/uploads"
query = toQuery
[ ("data_type", dataType)
] <> toQuery options
getUpload :: Client -> Integer -> IO (Either String T.UploadStatus)
getUpload client uploadId = get client resource query
where
resource = "api/v3/uploads/" <> show uploadId
query = [] :: Query