A music player that connects to your cloud/distributed storage.
at main 135 lines 3.8 kB view raw
1module Sources.Services.WebDav.Parser exposing (..) 2 3import Maybe.Extra as Maybe 4import Sources.Pick exposing (isMusicFile) 5import Sources.Processing exposing (Marker, TreeAnswer) 6import Sources.Services.Ipfs.Marker as Marker 7import String.Ext as String 8import Url 9import Xml.Decode exposing (..) 10import XmlParser 11 12 13 14-- TREE 15 16 17parseTreeResponse : String -> Marker -> TreeAnswer Marker 18parseTreeResponse response previousMarker = 19 let 20 currentDir = 21 Maybe.withDefault "//" (Marker.takeOne previousMarker) 22 23 parseResult = 24 XmlParser.parse response 25 26 namespace = 27 parseResult 28 |> Result.map 29 (\xml -> 30 case xml.root of 31 XmlParser.Element nodeName _ _ -> 32 nodeName 33 |> String.split ":" 34 |> List.head 35 36 _ -> 37 Nothing 38 ) 39 |> Result.withDefault Nothing 40 |> (\maybe -> 41 case maybe of 42 Just n -> 43 n ++ ":" 44 45 Nothing -> 46 if String.contains "<d:" response then 47 "d:" 48 49 else 50 "D:" 51 ) 52 53 entries = 54 response 55 |> decodeString (treeDecoder namespace) 56 |> Result.withDefault [] 57 |> List.map Url.percentDecode 58 |> Maybe.values 59 |> List.filter ((/=) currentDir) 60 61 ( dirs, files ) = 62 List.partition (String.endsWith "/") entries 63 in 64 { filePaths = 65 List.map (String.chopStart "/") files 66 , marker = 67 previousMarker 68 |> Marker.removeOne 69 |> Marker.concat dirs 70 } 71 72 73treeDecoder : String -> Decoder (List String) 74treeDecoder namespace = 75 path 76 [ namespace ++ "response" ] 77 (leakyList <| treeItemDecoder namespace) 78 79 80treeItemDecoder : String -> Decoder String 81treeItemDecoder namespace = 82 let 83 withNamespace = 84 String.append namespace 85 in 86 string 87 |> single 88 |> path [ withNamespace "href" ] 89 |> andThen 90 (\href -> 91 oneOf 92 [ -- Audio 93 -------- 94 string 95 |> single 96 |> path [ withNamespace "propstat", withNamespace "prop", withNamespace "getcontenttype" ] 97 |> andThen (mustBeAudio href) 98 |> map (\_ -> href) 99 100 -- Directory 101 ------------ 102 , string 103 |> single 104 |> path [ withNamespace "propstat", withNamespace "prop", withNamespace "resourcetype", withNamespace "collection" ] 105 |> andThen 106 (\_ -> 107 if String.endsWith "/@eaDir/" href then 108 fail "Ignore Synology metadata" 109 110 else 111 succeed href 112 ) 113 ] 114 ) 115 116 117mustBeAudio : String -> String -> Decoder String 118mustBeAudio href contentType = 119 if isMusicFile href then 120 succeed contentType 121 122 else if String.startsWith "audio/" contentType then 123 succeed contentType 124 125 else 126 fail "Ignore this, not an audio file" 127 128 129 130-- ERROR 131 132 133parseErrorResponse : String -> Maybe String 134parseErrorResponse = 135 Just