diff --git a/src/Twitch.elm b/src/Twitch.elm index 1c07ee0..86aa6a3 100644 --- a/src/Twitch.elm +++ b/src/Twitch.elm @@ -15,6 +15,7 @@ type alias Playlist = type alias Video = { name : String , url : String + , duration : Float } @@ -47,8 +48,50 @@ fetchPlaylist : String -> Task x Playlist fetchPlaylist name = get { url = "/videos/" ++ name ++ "/description.json" - , resolver = Http.stringResolver parsePlaylist + , resolver = Http.stringResolver parsePlaylistName } + |> Task.andThen + (\a -> + Task.map (\b -> Playlist a b) + (get + { url = "/videos/" ++ name + , resolver = Http.stringResolver parsePlaylistVideoPaths + } + |> Task.andThen (\c -> fetchVideos name c) + ) + ) + + +fetchVideo : String -> String -> Task x Video +fetchVideo playlist video = + let + url = + "/videos/" ++ playlist ++ video + in + get + { url = "/videos/" ++ playlist ++ "/" ++ video ++ "/description.json" + , resolver = Http.stringResolver (parseVideo url) + } + + +fetchVideos : String -> List String -> Task x (List Video) +fetchVideos playlist videos = + Task.sequence (List.map (fetchVideo playlist) videos) + + +parseVideo : String -> Http.Response String -> Result x Video +parseVideo url result = + case result of + Http.GoodStatus_ _ content -> + case Decode.decodeString (decodeVideo url) content of + Ok v -> + Ok v + + _ -> + Ok { name = "", url = url, duration = 0 } + + _ -> + Ok { name = "", url = url, duration = 0 } fetchPlaylistsMapper : List String -> Task x (List Playlist) @@ -56,19 +99,48 @@ fetchPlaylistsMapper names = Task.sequence (List.map fetchPlaylist names) -parsePlaylist : Http.Response String -> Result x Playlist -parsePlaylist result = +parsePlaylistName : Http.Response String -> Result x String +parsePlaylistName result = case result of Http.GoodStatus_ _ content -> - case Decode.decodeString decodePlaylist content of + case Decode.decodeString decodePlaylistName content of Ok p -> Ok p _ -> - Ok { name = "", videos = [] } + Ok "" _ -> - Ok { name = "", videos = [] } + Ok "" + + +parsePlaylistVideoPaths : Http.Response String -> Result x (List String) +parsePlaylistVideoPaths result = + case result of + Http.GoodStatus_ _ content -> + let + withoutDoctype = + if String.startsWith " List.drop 1 |> String.join "\n" + + else + content + + decoded = + Html.Parser.run withoutDoctype + + hrefs = + Result.map findHrefs decoded + in + case hrefs of + Ok h -> + Ok (List.filter (String.endsWith "/") h) + + _ -> + Ok [] + + _ -> + Ok [] parsePlaylistPath : Http.Response String -> Result x (List String) @@ -130,6 +202,13 @@ findHrefs x = findHrefsAux [] (Html.Parser.Element "" [] x) -decodePlaylist : Decode.Decoder Playlist -decodePlaylist = - Decode.map (\x -> Playlist x []) (Decode.field "title" Decode.string) +decodePlaylistName : Decode.Decoder String +decodePlaylistName = + Decode.field "title" Decode.string + + +decodeVideo : String -> Decode.Decoder Video +decodeVideo url = + Decode.map2 (\x y -> Video x url y) + (Decode.field "title" Decode.string) + (Decode.field "duration" Decode.float)