···11+module Sources.Services exposing (initialData, keyToType, labels, makeTrackUrl, makeTree, parseErrorResponse, parsePreparationResponse, parseTreeResponse, postProcessTree, prepare, properties, typeToKey)
22+33+{-| Service functions used in other modules.
44+-}
55+66+import Http
77+import Sources exposing (..)
88+import Sources.Processing exposing (..)
99+import Sources.Services.AmazonS3 as AmazonS3
1010+import Time
1111+1212+1313+1414+-- FUNCTIONS
1515+1616+1717+initialData : Service -> SourceData
1818+initialData service =
1919+ case service of
2020+ AmazonS3 ->
2121+ AmazonS3.initialData
2222+2323+2424+makeTrackUrl : Service -> Time.Posix -> SourceData -> HttpMethod -> String -> String
2525+makeTrackUrl service =
2626+ case service of
2727+ AmazonS3 ->
2828+ AmazonS3.makeTrackUrl
2929+3030+3131+makeTree :
3232+ Service
3333+ -> SourceData
3434+ -> Marker
3535+ -> Time.Posix
3636+ -> (Result Http.Error String -> msg)
3737+ -> Cmd msg
3838+makeTree service =
3939+ case service of
4040+ AmazonS3 ->
4141+ AmazonS3.makeTree
4242+4343+4444+parseErrorResponse : Service -> String -> String
4545+parseErrorResponse service =
4646+ case service of
4747+ AmazonS3 ->
4848+ AmazonS3.parseErrorResponse
4949+5050+5151+parsePreparationResponse : Service -> String -> SourceData -> Marker -> PrepationAnswer Marker
5252+parsePreparationResponse service =
5353+ case service of
5454+ AmazonS3 ->
5555+ AmazonS3.parsePreparationResponse
5656+5757+5858+parseTreeResponse : Service -> String -> Marker -> TreeAnswer Marker
5959+parseTreeResponse service =
6060+ case service of
6161+ AmazonS3 ->
6262+ AmazonS3.parseTreeResponse
6363+6464+6565+postProcessTree : Service -> List String -> List String
6666+postProcessTree service =
6767+ case service of
6868+ AmazonS3 ->
6969+ AmazonS3.postProcessTree
7070+7171+7272+prepare :
7373+ Service
7474+ -> String
7575+ -> SourceData
7676+ -> Marker
7777+ -> (Result Http.Error String -> msg)
7878+ -> Maybe (Cmd msg)
7979+prepare service =
8080+ case service of
8181+ AmazonS3 ->
8282+ AmazonS3.prepare
8383+8484+8585+properties : Service -> List Property
8686+properties service =
8787+ case service of
8888+ AmazonS3 ->
8989+ AmazonS3.properties
9090+9191+9292+9393+-- KEYS & LABELS
9494+9595+9696+keyToType : String -> Maybe Service
9797+keyToType str =
9898+ case str of
9999+ "AmazonS3" ->
100100+ Just AmazonS3
101101+102102+ _ ->
103103+ Nothing
104104+105105+106106+typeToKey : Service -> String
107107+typeToKey service =
108108+ case service of
109109+ AmazonS3 ->
110110+ "AmazonS3"
111111+112112+113113+{-| Service labels.
114114+Maps a service key to a label.
115115+-}
116116+labels : List ( String, String )
117117+labels =
118118+ [ ( typeToKey AmazonS3, "Amazon S3" )
119119+ ]
+168
src/Library/Sources/Services/AmazonS3.elm
···11+module Sources.Services.AmazonS3 exposing (defaults, initialData, makeTrackUrl, makeTree, parseErrorResponse, parsePreparationResponse, parseTreeResponse, postProcessTree, prepare, properties)
22+33+{-| Amazon S3 Service.
44+55+Resources:
66+77+ - <http://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-query-string-auth.html>
88+99+-}
1010+1111+import Dict
1212+import Http
1313+import Sources exposing (..)
1414+import Sources.Pick
1515+import Sources.Processing exposing (..)
1616+import Sources.Services.AmazonS3.Parser as Parser
1717+import Sources.Services.AmazonS3.Presign exposing (..)
1818+import Sources.Services.Common exposing (cleanPath, nameProperty, noPrep)
1919+import Time
2020+2121+2222+2323+-- PROPERTIES
2424+-- 📟
2525+2626+2727+defaults =
2828+ { directoryPath = "/"
2929+ , name = "Music from Amazon S3"
3030+ , region = "eu-west-1"
3131+ }
3232+3333+3434+{-| The list of properties we need from the user.
3535+-}
3636+properties : List Property
3737+properties =
3838+ [ { prop = "accessKey", labl = "Access key", plho = "Fv6EWfLfCcMo", pass = False }
3939+ , { prop = "secretKey", labl = "Secret key", plho = "qeNcqiMpgqC8", pass = True }
4040+ , { prop = "bucketName", labl = "Bucket name", plho = "music", pass = False }
4141+ , { prop = "region", labl = "Region", plho = defaults.region, pass = False }
4242+ , { prop = "directoryPath", labl = "Directory", plho = defaults.directoryPath, pass = False }
4343+ , { prop = "host", labl = "Host (optional)", plho = "http://127.0.0.1:9000", pass = False }
4444+4545+ --
4646+ , nameProperty defaults.name
4747+ ]
4848+4949+5050+{-| Initial data set.
5151+-}
5252+initialData : SourceData
5353+initialData =
5454+ Dict.fromList
5555+ [ ( "accessKey", "" )
5656+ , ( "bucketName", "" )
5757+ , ( "directoryPath", defaults.directoryPath )
5858+ , ( "host", "" )
5959+ , ( "name", defaults.name )
6060+ , ( "region", defaults.region )
6161+ , ( "secretKey", "" )
6262+ ]
6363+6464+6565+6666+-- PREPARATION
6767+6868+6969+prepare : String -> SourceData -> Marker -> (Result Http.Error String -> msg) -> Maybe (Cmd msg)
7070+prepare _ _ _ _ =
7171+ Nothing
7272+7373+7474+7575+-- TREE
7676+7777+7878+{-| Create a directory tree.
7979+8080+List all the tracks in the bucket.
8181+Or a specific directory in the bucket.
8282+8383+-}
8484+makeTree : SourceData -> Marker -> Time.Posix -> (Result Http.Error String -> msg) -> Cmd msg
8585+makeTree srcData marker currentTime resultMsg =
8686+ let
8787+ directoryPath =
8888+ srcData
8989+ |> Dict.get "directoryPath"
9090+ |> Maybe.withDefault defaults.directoryPath
9191+ |> cleanPath
9292+9393+ initialParams =
9494+ [ ( "list-type", "2" )
9595+ , ( "max-keys", "1000" )
9696+ ]
9797+9898+ prefix =
9999+ if String.length directoryPath > 0 then
100100+ [ ( "prefix", directoryPath ) ]
101101+102102+ else
103103+ []
104104+105105+ continuation =
106106+ case marker of
107107+ InProgress s ->
108108+ [ ( "continuation-token", s ) ]
109109+110110+ _ ->
111111+ []
112112+113113+ params =
114114+ initialParams ++ prefix ++ continuation
115115+116116+ url =
117117+ presignedUrl Get (60 * 5) params currentTime srcData "/"
118118+ in
119119+ Http.get
120120+ { url = url
121121+ , expect = Http.expectString resultMsg
122122+ }
123123+124124+125125+{-| Re-export parser functions.
126126+-}
127127+parsePreparationResponse : String -> SourceData -> Marker -> PrepationAnswer Marker
128128+parsePreparationResponse =
129129+ noPrep
130130+131131+132132+parseTreeResponse : String -> Marker -> TreeAnswer Marker
133133+parseTreeResponse =
134134+ Parser.parseTreeResponse
135135+136136+137137+parseErrorResponse : String -> String
138138+parseErrorResponse =
139139+ Parser.parseErrorResponse
140140+141141+142142+143143+-- Post
144144+145145+146146+{-| Post process the tree results.
147147+148148+Make sure we only use music files that we can use.
149149+150150+-}
151151+postProcessTree : List String -> List String
152152+postProcessTree =
153153+ Sources.Pick.selectMusicFiles
154154+155155+156156+157157+-- Track URL
158158+159159+160160+{-| Create a public url for a file.
161161+162162+We need this to play the track.
163163+Creates a presigned url that's valid for 48 hours
164164+165165+-}
166166+makeTrackUrl : Time.Posix -> SourceData -> HttpMethod -> String -> String
167167+makeTrackUrl currentTime srcData method pathToFile =
168168+ presignedUrl method 172800 [] currentTime srcData pathToFile