Skip to content

Instantly share code, notes, and snippets.

@Boettner-eric
Last active October 3, 2023 16:17
Show Gist options
  • Save Boettner-eric/3aaa64347fcf8bdd1f57f5d9513f4a16 to your computer and use it in GitHub Desktop.
Save Boettner-eric/3aaa64347fcf8bdd1f57f5d9513f4a16 to your computer and use it in GitHub Desktop.
Write a spotify playlist to a text file
Mix.install([:httpoison, :poison])
defmodule Spotify do
[playlist_id] = System.argv()
@token_url "https://accounts.spotify.com/api/token"
@playlist_url "https://api.spotify.com/v1/playlists/#{playlist_id}"
def get_token() do
client_id = System.get_env("SPOTIFY_CLIENT_ID")
client_secret = System.get_env("SPOTIFY_CLIENT_SECRET")
HTTPoison.post!(
@token_url,
"grant_type=client_credentials&client_id=#{client_id}&client_secret=#{client_secret}",
[{"Content-Type", "application/x-www-form-urlencoded"}]
)
|> parse_token_resp()
end
defp parse_token_resp(%HTTPoison.Response{status_code: 200, body: body}) do
%{
"access_token" => access_token,
"token_type" => token_type,
"expires_in" => _expires_in
} = Poison.decode!(body)
{:ok, access_token, token_type}
end
defp parse_token_resp(%HTTPoison.Response{status_code: status_code, body: body}) do
{:error, status_code, Poison.decode!(body)}
end
defp parse_token_resp(_) do
{:error, :unexpected_response}
end
def get_playlist({:ok, access_token, token_type}, list \\ [], url \\ @playlist_url) do
{next, items} =
HTTPoison.get!(url, generate_headers(access_token))
|> parse_playlist_resp()
if is_nil(next) do
Enum.uniq(list ++ items)
|> Enum.map(&format_track/1)
|> write_file()
else
get_playlist({:ok, access_token, token_type}, list ++ items, next)
end
end
defp parse_playlist_resp(%HTTPoison.Response{status_code: 200, body: body}) do
Poison.decode!(body)
|> case do
%{"tracks" => %{"next" => next, "items" => items}} -> {next, items}
%{"next" => next, "items" => items} -> {next, items}
end
end
defp format_track(track) do
track["track"]["name"] <>
" - " <> (Enum.map(track["track"]["artists"], & &1["name"]) |> Enum.join(", "))
end
defp generate_headers(access_token) do
[
{"Authorization", "Bearer #{access_token}"},
{"Content-Type", "application/json"}
]
end
defp write_file(tracks) do
{:ok, file} = File.open("playlist.txt", [:append, {:delayed_write, 100, 20}])
Enum.map(tracks, &IO.binwrite(file, "#{&1}\n"))
File.close(file)
end
end
Spotify.get_token()
|> Spotify.get_playlist()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment