Files
music_library/lib/last_fm/session.ex
T
Claudio Ortolina 9e1dbfd530 Re-enable Credo ModuleDoc check
Closes #108
2026-03-13 10:52:01 +00:00

95 lines
2.0 KiB
Elixir

defmodule LastFm.Session do
@moduledoc false
require Record
defstruct [:name, :key, :pro]
@type t :: %__MODULE__{
name: String.t() | nil,
key: String.t() | nil,
pro: boolean() | nil
}
Record.defrecord(
:xmlAttribute,
Record.extract(:xmlAttribute, from_lib: "xmerl/include/xmerl.hrl")
)
Record.defrecord(:xmlText, Record.extract(:xmlText, from_lib: "xmerl/include/xmerl.hrl"))
@doc """
Parses a Last.fm session XML response into a Session struct.
## Examples
iex> xml = \"\"\"
...> <?xml version="1.0" encoding="UTF-8"?>
...> <lfm status="ok">
...> <session>
...> <name>cloud8421</name>
...> <key>super-secret</key>
...> <subscriber>1</subscriber>
...> </session>
...> </lfm>
...> \"\"\"
iex> LastFm.Session.parse(xml)
%LastFm.Session{
name: "cloud8421",
key: "super-secret",
pro: true
}
"""
@spec parse(String.t()) :: t()
def parse(xml_string) do
doc = scan(xml_string)
name =
doc
|> first("//lfm/session/name")
|> text()
key =
doc
|> first("//lfm/session/key")
|> text()
subscriber =
doc
|> first("//lfm/session/subscriber")
|> text()
%__MODULE__{
name: name,
key: key,
pro: subscriber == "1"
}
end
defp scan(xml_string) do
{doc, []} =
xml_string
|> :binary.bin_to_list()
|> :xmerl_scan.string(quiet: true)
doc
end
defp first(node, path), do: node |> xpath(path) |> take_one()
defp take_one([head | _]), do: head
defp take_one(_), do: nil
defp xpath(nil, _), do: []
defp xpath(node, path) do
:xmerl_xpath.string(to_charlist(path), node)
end
@spec text(tuple() | nil) :: String.t() | nil
def text(node), do: node |> xpath(~c"./text()") |> extract_text()
defp extract_text([xmlText(value: value)]), do: List.to_string(value)
defp extract_text(_x), do: nil
end