packages feed

gopro-plus 0.2.0.0 → 0.3.0.0

raw patch · 4 files changed

+72/−36 lines, 4 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

+ GoPro.Plus.Media: Burst :: MediumType
+ GoPro.Plus.Media: Photo :: MediumType
+ GoPro.Plus.Media: TimeLapse :: MediumType
+ GoPro.Plus.Media: TimeLapseVideo :: MediumType
+ GoPro.Plus.Media: Video :: MediumType
+ GoPro.Plus.Media: ViewFailure :: ReadyToViewType
+ GoPro.Plus.Media: ViewLoading :: ReadyToViewType
+ GoPro.Plus.Media: ViewProcessing :: ReadyToViewType
+ GoPro.Plus.Media: ViewReady :: ReadyToViewType
+ GoPro.Plus.Media: ViewRegistered :: ReadyToViewType
+ GoPro.Plus.Media: ViewTranscoding :: ReadyToViewType
+ GoPro.Plus.Media: ViewUploading :: ReadyToViewType
+ GoPro.Plus.Media: data MediumType
+ GoPro.Plus.Media: data ReadyToViewType
+ GoPro.Plus.Media: instance Data.Aeson.Types.FromJSON.FromJSON GoPro.Plus.Media.MediumType
+ GoPro.Plus.Media: instance Data.Aeson.Types.FromJSON.FromJSON GoPro.Plus.Media.ReadyToViewType
+ GoPro.Plus.Media: instance Data.Aeson.Types.ToJSON.ToJSON GoPro.Plus.Media.MediumType
+ GoPro.Plus.Media: instance Data.Aeson.Types.ToJSON.ToJSON GoPro.Plus.Media.ReadyToViewType
+ GoPro.Plus.Media: instance GHC.Classes.Eq GoPro.Plus.Media.MediumType
+ GoPro.Plus.Media: instance GHC.Classes.Eq GoPro.Plus.Media.ReadyToViewType
+ GoPro.Plus.Media: instance GHC.Read.Read GoPro.Plus.Media.MediumType
+ GoPro.Plus.Media: instance GHC.Read.Read GoPro.Plus.Media.ReadyToViewType
+ GoPro.Plus.Media: instance GHC.Show.Show GoPro.Plus.Media.MediumType
+ GoPro.Plus.Media: instance GHC.Show.Show GoPro.Plus.Media.ReadyToViewType
+ GoPro.Plus.Upload: getUpload :: (HasGoProAuth m, MonadIO m) => UploadID -> DerivativeID -> Int -> Int -> Uploader m Upload
- GoPro.Plus.Auth: withAuth :: (Monad m, HasGoProAuth m) => AuthInfo -> AuthReader m a -> m a
+ GoPro.Plus.Auth: withAuth :: AuthInfo -> AuthReader m a -> m a
- GoPro.Plus.Media: Medium :: MediumID -> Maybe String -> UTCTime -> UTCTime -> Maybe Int -> Int -> String -> Maybe String -> String -> String -> Maybe Int -> Maybe Int -> Medium
+ GoPro.Plus.Media: Medium :: MediumID -> Maybe String -> UTCTime -> UTCTime -> Maybe Int -> Int -> ReadyToViewType -> Maybe String -> MediumType -> String -> Maybe Int -> Maybe Int -> Medium
- GoPro.Plus.Media: [_medium_ready_to_view] :: Medium -> String
+ GoPro.Plus.Media: [_medium_ready_to_view] :: Medium -> ReadyToViewType
- GoPro.Plus.Media: [_medium_type] :: Medium -> String
+ GoPro.Plus.Media: [_medium_type] :: Medium -> MediumType
- GoPro.Plus.Media: medium_ready_to_view :: Lens' Medium String
+ GoPro.Plus.Media: medium_ready_to_view :: Lens' Medium ReadyToViewType
- GoPro.Plus.Media: medium_type :: Lens' Medium String
+ GoPro.Plus.Media: medium_type :: Lens' Medium MediumType
- GoPro.Plus.Upload: setMediumType :: Monad m => Text -> Uploader m ()
+ GoPro.Plus.Upload: setMediumType :: Monad m => MediumType -> Uploader m ()

Files

gopro-plus.cabal view
@@ -4,10 +4,10 @@ -- -- see: https://github.com/sol/hpack ----- hash: 5e05f8a01680acbd25e66b1641f2c5a02799d5bf8e23075385e768184d45927c+-- hash: 4bb7255d2a4a022d5784c1045d89a42542f454252c098c0e9cd6953c1255c7a7  name:           gopro-plus-version:        0.2.0.0+version:        0.3.0.0 synopsis:       GoPro Plus Client API. description:    Please see the README on GitHub at <https://github.com/dustin/gopro-plus#readme> category:       Web
src/GoPro/Plus/Auth.hs view
@@ -9,11 +9,10 @@ GoPro Plus authentication. -} -{-# LANGUAGE DeriveGeneric        #-}-{-# LANGUAGE FlexibleInstances    #-}-{-# LANGUAGE RecordWildCards      #-}-{-# LANGUAGE TemplateHaskell      #-}-{-# LANGUAGE TypeSynonymInstances #-}+{-# LANGUAGE DeriveGeneric     #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE RecordWildCards   #-}+{-# LANGUAGE TemplateHaskell   #-}  module GoPro.Plus.Auth (   authenticate, refreshAuth,@@ -83,7 +82,7 @@   goproAuth = ask  -- | Convenient function for passing around auth info.  You probably--- don't want to use this, but it can be conven ient when+-- don't want to use this, but it can be convenient when -- experimenting.-withAuth :: (Monad m, HasGoProAuth m) => AuthInfo -> AuthReader m a -> m a+withAuth :: AuthInfo -> AuthReader m a -> m a withAuth = flip runReaderT
src/GoPro/Plus/Media.hs view
@@ -20,7 +20,7 @@   fetchThumbnail,   -- * Data Types   PageInfo(..), current_page, per_page, total_items, total_pages,-  MediumID,+  MediumID, MediumType(..), ReadyToViewType(..),   Medium(..), medium_id, medium_camera_model, medium_captured_at,   medium_created_at, medium_file_size, medium_moments_count,   medium_ready_to_view, medium_source_duration, medium_type,@@ -49,8 +49,10 @@                                                genericParseJSON,                                                genericToEncoding, genericToJSON,                                                (.:))+import qualified Data.Aeson                   as J import           Data.Aeson.Types             (typeMismatch) import qualified Data.ByteString.Lazy         as BL+import           Data.Char                    (toLower, toUpper) import qualified Data.Map.Strict              as Map import qualified Data.Text                    as T import           Data.Time.Clock              (UTCTime)@@ -78,6 +80,29 @@  type MediumID = T.Text +data MediumType = Photo | Video | TimeLapse | TimeLapseVideo | Burst+  deriving (Show, Read, Eq)++instance ToJSON MediumType where+  toJSON = J.String . T.pack . show++instance FromJSON MediumType where+  parseJSON (J.String x) = pure . read . T.unpack $ x+  parseJSON invalid      = typeMismatch "Response" invalid++data ReadyToViewType = ViewReady | ViewFailure | ViewLoading+                     | ViewRegistered | ViewTranscoding | ViewProcessing | ViewUploading+  deriving (Show, Read, Eq)++instance ToJSON ReadyToViewType where+  toJSON = J.String . T.pack . fmap toLower . drop 4 . show++instance FromJSON ReadyToViewType where+  parseJSON (J.String s) = pure . read . trans . T.unpack $ s+    where trans (x:xs) = "View" <> (toUpper x : xs)+          trans []     = error "empty ready to view type"+  parseJSON invalid      = typeMismatch "Response" invalid+ data Medium = Medium {   _medium_id              :: MediumID,   _medium_camera_model    :: Maybe String,@@ -85,9 +110,9 @@   _medium_created_at      :: UTCTime,   _medium_file_size       :: Maybe Int,   _medium_moments_count   :: Int,-  _medium_ready_to_view   :: String,+  _medium_ready_to_view   :: ReadyToViewType,   _medium_source_duration :: Maybe String,-  _medium_type            :: String,+  _medium_type            :: MediumType,   _medium_token           :: String,   _medium_width           :: Maybe Int,   _medium_height          :: Maybe Int@@ -137,8 +162,8 @@ list :: (HasGoProAuth m, MonadIO m) => Int -> Int -> m ([Medium], PageInfo) list psize page = do   r <- jgetAuth ("https://api.gopro.com/media/search?fields=captured_at,created_at,file_size,id,moments_count,ready_to_view,source_duration,type,token,width,height,camera_model&order_by=created_at&per_page=" <> show psize <> "&page=" <> show page)-  pure $ (r ^.. media . folded,-          r ^. pages)+  pure (r ^.. media . folded,+        r ^. pages)  -- | List all media. listAll :: (HasGoProAuth m, MonadIO m) => m [Medium]@@ -146,8 +171,7 @@  -- | List all media while returned batches pass the given predicate. listWhile :: (HasGoProAuth m, MonadIO m) => ([Medium] -> Bool) -> m [Medium]-listWhile f = do-  Map.elems <$> dig 0 mempty+listWhile f = Map.elems <$> dig 0 mempty     where       dig n m = do         (ms, _) <- list 100 n
src/GoPro/Plus/Upload.hs view
@@ -20,7 +20,7 @@   -- * Low-level upload parts.   runUpload, resumeUpload,   createMedium, createSource, createDerivative, createUpload,-  completeUpload, uploadChunk, markAvailable,+  completeUpload, getUpload, uploadChunk, markAvailable,   -- * Data Types   UploadID, DerivativeID,   UploadPart(..), uploadLength, uploadPart, uploadURL,@@ -62,7 +62,9 @@ import           GoPro.Plus.Auth              (AuthInfo (..), HasGoProAuth (..)) import           GoPro.Plus.Internal.AuthHTTP import           GoPro.Plus.Internal.HTTP-import           GoPro.Plus.Media             (Medium (..), MediumID, list,+import           GoPro.Plus.Media             (Medium (..), MediumID,+                                               MediumType (..),+                                               ReadyToViewType (..), list,                                                putMedium)  type UploadID = T.Text@@ -83,7 +85,7 @@  data Env m = Env {   fileList   :: [FilePath],-  mediumType :: T.Text,+  mediumType :: MediumType,   extension  :: T.Text,   filename   :: String,   mediumID   :: MediumID,@@ -92,15 +94,14 @@  -- | List all media in uploading state. listUploading :: (HasGoProAuth m, MonadIO m) => m [Medium]-listUploading = do-  filter (\Medium{..} -> _medium_ready_to_view == "uploading") . fst <$> list 30 1+listUploading = filter (\Medium{..} -> _medium_ready_to_view == ViewUploading) . fst <$> list 30 1  -- | Run an Uploader monad to create a single medium and upload the content for it. runUpload :: (HasGoProAuth m, MonadFail m, MonadIO m)           => [FilePath]   -- ^ The list of files to include in the medium.           -> Uploader m a -- ^ The action to perform.           -> m a          -- ^ The result of the inner action.-runUpload fileList a = resumeUpload fileList "" a+runUpload fileList = resumeUpload fileList ""  -- | Run an Uploader monad for which we already know the MediumID -- (i.e., we're resuming an upload we previously began).@@ -114,11 +115,11 @@     mediumType = fileType extension     logAction _ = pure () -    fileType "JPG" = "Photo"-    fileType _     = "Video"+    fileType "JPG" = Photo+    fileType _     = Video  -- | Override the detected medium type.-setMediumType :: Monad m => T.Text -> Uploader m ()+setMediumType :: Monad m => MediumType -> Uploader m () setMediumType t = modify (\m -> m{mediumType=t})  -- | Set the logging action to report retries (or whatever other@@ -139,7 +140,7 @@   AuthInfo{..} <- goproAuth   let m1 = J.Object (mempty & at "file_extension" ?~ J.String extension                      & at "filename" ?~ J.String (T.pack filename)-                     & at "type" ?~ J.String mediumType+                     & at "type" ?~ J.toJSON mediumType                      & at "on_public_profile" ?~ J.Bool False                      & at "content_title" ?~ J.String (T.pack filename)                      & at "content_source" ?~ J.String "web_media_library"@@ -207,28 +208,40 @@                      & at "access_token" ?~ J.String _access_token                      & at "gopro_user_id" ?~ J.String _resource_owner_id)   ur <- jpost "https://api.gopro.com/user-uploads" u1-   let Just upid = ur ^? key "id" . _String+  getUpload upid did part fsize++  where+    popts tok = authOpts tok & header "Accept" .~  ["application/vnd.gopro.jk.user-uploads+json; version=2.0.0"]+    jpost :: (HasGoProAuth m, MonadIO m) => String -> J.Value -> m J.Value+    jpost u p = (_access_token <$> goproAuth) >>= \tok -> jpostVal (popts tok) u p++getUpload :: (HasGoProAuth m, MonadIO m)+          => UploadID+          -> DerivativeID+          -> Int+          -> Int+          -> Uploader m Upload+getUpload upid did part fsize = do+  Env{..} <- get+  AuthInfo{..} <- goproAuth++  let pages = (ceiling ((fromIntegral fsize :: Double) / fromIntegral chunkSize)) :: Int       upopts = authOpts _access_token & params .~ [("id", upid),                                                    ("page", "1"),-                                                   ("per_page", "100"),+                                                   ("per_page", (T.pack . show) pages),                                                    ("item_number", (T.pack . show) part),                                                    ("camera_position", "default"),                                                    ("file_size", (T.pack . show) fsize),                                                    ("part_size", (T.pack . show) chunkSize)]                & header "Accept" .~  ["application/vnd.gopro.jk.user-uploads+json; version=2.0.0"]-  upaths <- (jgetWith upopts (T.unpack ("https://api.gopro.com/user-uploads/" <> did)))+  upaths <- jgetWith upopts (T.unpack ("https://api.gopro.com/user-uploads/" <> did))   let Just ups = (upaths :: J.Value) ^? key "_embedded" . key "authorizations" . _Array . to V.toList   pure $ Upload upid (fromJust $ traverse aChunk ups)    where-    popts tok = authOpts tok & header "Accept" .~  ["application/vnd.gopro.jk.user-uploads+json; version=2.0.0"]-    jpost :: (HasGoProAuth m, MonadIO m) => String -> J.Value -> m J.Value-    jpost u p = (_access_token <$> goproAuth) >>= \tok -> jpostVal (popts tok) u p-     tInt :: T.Text -> Integer     tInt = read . T.unpack-     aChunk v = liftA3 UploadPart (v ^? key "Content-Length" . _String . to tInt)                                  (v ^? key "part" . _Integer . to toInteger)                                  (v ^? key "url" . _String . to T.unpack)@@ -244,7 +257,7 @@     hSeek fh AbsoluteSeek ((_uploadPart - 1) * chunkSize)     void $ putWith defOpts _uploadURL =<< BL.hGet fh (fromIntegral _uploadLength) -    where policy = exponentialBackoff 2000000 <> limitRetries 5+    where policy = exponentialBackoff 2000000 <> limitRetries 9           retryMsg a = mconcat ["Retrying upload of ", show fp,                                 " part ", show _uploadPart, " attempt ", show a] @@ -282,7 +295,7 @@    _ <- liftIO $ putWith (popts _access_token) (T.unpack ("https://api.gopro.com/derivatives/" <> did)) d2 -  now <- liftIO $ getCurrentTime+  now <- liftIO getCurrentTime   let done = J.Object (mempty & at "upload_completed_at" ?~ J.toJSON now                        & at "client_updated_at" ?~ J.toJSON now                        & at "revision_number" ?~ J.Number 0