elm-twitch/src/Twitch.elm

136 lines
3.2 KiB
Elm

module Twitch exposing (Playlist, Video, fetchPlaylists)
import Html.Parser
import Http
import Json.Decode as Decode
import Task exposing (Task)
type alias Playlist =
{ name : String
, videos : List Video
}
type alias Video =
{ name : String
, url : String
}
get : { url : String, resolver : Http.Resolver x a } -> Task x a
get { url, resolver } =
Http.task
{ body = Http.emptyBody
, headers = []
, method = "GET"
, resolver = resolver
, timeout = Nothing
, url = url
}
fetchPlaylists : Task x (List Playlist)
fetchPlaylists =
fetchPlaylistPath |> Task.andThen fetchPlaylistsMapper
fetchPlaylistPath : Task x (List String)
fetchPlaylistPath =
get
{ url = "/videos"
, resolver = Http.stringResolver parsePlaylistPath
}
fetchPlaylist : String -> Task x Playlist
fetchPlaylist name =
get
{ url = "/videos/" ++ name ++ "/description.json"
, resolver = Http.stringResolver parsePlaylist
}
fetchPlaylistsMapper : List String -> Task x (List Playlist)
fetchPlaylistsMapper names =
Task.sequence (List.map fetchPlaylist names)
parsePlaylist : Http.Response String -> Result x Playlist
parsePlaylist result =
case result of
Http.GoodStatus_ _ content ->
case Decode.decodeString decodePlaylist content of
Ok p ->
Ok p
_ ->
Ok { name = "", videos = [] }
_ ->
Ok { name = "", videos = [] }
parsePlaylistPath : Http.Response String -> Result x (List String)
parsePlaylistPath result =
case result of
Http.GoodStatus_ _ content ->
let
withoutDoctype =
if String.startsWith "<!doctype" (String.toLower content) then
String.lines content |> 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 h
_ ->
Ok []
_ ->
Ok []
findHrefsAux : List String -> Html.Parser.Node -> List String
findHrefsAux acc node =
case node of
Html.Parser.Element string (( key, value ) :: t) nodes ->
let
newAcc =
if key == "href" then
value :: acc
else
acc
in
findHrefsAux newAcc (Html.Parser.Element string t nodes)
Html.Parser.Element string [] (h :: t) ->
let
attrs =
findHrefsAux [] h
in
findHrefsAux (acc ++ attrs) (Html.Parser.Element string [] t)
_ ->
acc
findHrefs : List Html.Parser.Node -> List String
findHrefs x =
findHrefsAux [] (Html.Parser.Element "" [] x)
decodePlaylist : Decode.Decoder Playlist
decodePlaylist =
Decode.map (\x -> Playlist x []) (Decode.field "title" Decode.string)