sure! i realized afterwards that it would be a better approach to just delete/add tracks to the same playlists instead of recreating the whole playlist every time. Most of the script is also quite specific for my use case, but the parts with 'get track recommendations" and “add songs to playlist” should give you a good starter to create your own little playlist creator.
To make this more usable i also integrated a template which extracts the IDs from the given Spotify Playlists link(s), so it is possible to just paste the full song link into the field.
i used ai to remove some personal data in the script, just let me know if this broke something:
alias: Spotify | Create Playlist
sequence:
- alias: Create Playlist
sequence:
- variables:
mix_number: |-
{%- if mix_title == 'Chill Mix 🌿' -%}
1
{%- elif mix_title == 'Happy Mix 🔆' -%}
2
{%- elif mix_title == 'Work Mix ☕' -%}
3
{%- elif mix_title == 'Psy Mix 🕉️' -%}
4
{%- endif -%}
alias: Set mix_number
- variables:
ids_extracted: |-
{%- set ids = '' -%} {%- for track in mix_tracks -%}
{%- if track is string -%}
{%- set url_parts = track.split('?')[0] -%}
{%- if 'playlist/' in url_parts -%}
{%- set id = url_parts.split('playlist/')[1] -%}
{%- elif 'track/' in url_parts -%}
{%- set id = url_parts.split('track/')[1] -%}
{%- endif -%}
{%- if id is defined -%}
{%- if not loop.first -%},{%- endif -%}
{{- id -}}
{%- endif -%}
{%- endif -%}
{%- endfor -%}
alias: Extract Spotify IDs
enabled: true
- action: input_text.set_value
metadata: {}
data:
value: "{{ ids_extracted }}"
target:
entity_id: input_text.mix_{{ mix_number }}_playlist_tracks
alias: Save Selected Tracks
- action: spotifyplus.unfollow_playlist
metadata: {}
data:
entity_id: media_player.your_spotifyplus_player
playlist_id: >-
{{ states('input_text.mix_' ~ mix_number ~ '_playlist_url') |
regex_replace(find='spotify:playlist:', replace='',
ignorecase=False) }}
alias: SpotifyPlus | Delete Playlist
enabled: true
- alias: SpotifyPlus | Get Songs
action: spotifyplus.get_track_recommendations
data:
entity_id: media_player.your_spotifyplus_player
limit: 50
seed_tracks: |-
{% if ids_extracted != '' %}
{{ ids_extracted }}
{% else %}
{{ states('input_text.mix_' ~ mix_number ~ '_playlist_tracks') }}
{% endif %}
max_speechiness: "{{ max_speechiness | default (false) }}"
min_popularity: "{{ min_popularity | default (false) }}"
min_liveness: "{{ min_liveness | default (false) }}"
min_instrumentalness: "{{ min_instrumentalness | default (false) }}"
min_energy: "{{ min_energy | default (false) }}"
min_acousticness: "{{ min_acousticness | default (false) }}"
enabled: true
response_variable: track_recommendations
- alias: SpotifyPlus | Create Playlist
data:
entity_id: media_player.your_spotifyplus_player
name: "{{ mix_title }} | {{ now().strftime('%-d.%m.%y') }}"
description: >-
#{{ track_recommendations.result.tracks[0].artists[0].name }}, #{{
track_recommendations.result.tracks[1].artists[0].name }}, #{{
track_recommendations.result.tracks[2].artists[0].name }}, #{{
track_recommendations.result.tracks[3].artists[0].name }}, #{{
track_recommendations.result.tracks[4].artists[0].name }}, #MORE
🧙♂️🪄 50 Songs, specially created for you on {{ now().strftime('%-d.%m.%y') }} at {{
states('sensor.time') }}!
public: false
collaborative: false
image_path: www/images/Playlists/mix_{{ mix_number }}.jpg
action: spotifyplus.playlist_create
response_variable: playlist
- data:
entity_id: media_player.your_spotifyplus_player
playlist_id: >-
{{ playlist.result.href |
regex_replace(find='https://api.spotify.com/v1/playlists/',
replace='', ignorecase=False) }}
uris: >-
{{ track_recommendations.result.tracks[0].uri }}, {{
track_recommendations.result.tracks[1].uri }}, {{
track_recommendations.result.tracks[2].uri }}, {{
track_recommendations.result.tracks[3].uri }}, {{
track_recommendations.result.tracks[4].uri }}, {{
track_recommendations.result.tracks[5].uri }}, {{
track_recommendations.result.tracks[6].uri }}, {{
track_recommendations.result.tracks[7].uri }}, {{
track_recommendations.result.tracks[8].uri }}, {{
track_recommendations.result.tracks[9].uri }}, {{
track_recommendations.result.tracks[10].uri }}, {{
track_recommendations.result.tracks[11].uri }}, {{
track_recommendations.result.tracks[12].uri }}, {{
track_recommendations.result.tracks[13].uri }}, {{
track_recommendations.result.tracks[14].uri }}, {{
track_recommendations.result.tracks[15].uri }}, {{
track_recommendations.result.tracks[16].uri }}, {{
track_recommendations.result.tracks[17].uri }}, {{
track_recommendations.result.tracks[18].uri }}, {{
track_recommendations.result.tracks[19].uri }}, {{
track_recommendations.result.tracks[20].uri }}, {{
track_recommendations.result.tracks[21].uri }}, {{
track_recommendations.result.tracks[22].uri }}, {{
track_recommendations.result.tracks[23].uri }}, {{
track_recommendations.result.tracks[24].uri }}, {{
track_recommendations.result.tracks[25].uri }}, {{
track_recommendations.result.tracks[26].uri }}, {{
track_recommendations.result.tracks[27].uri }}, {{
track_recommendations.result.tracks[28].uri }}, {{
track_recommendations.result.tracks[29].uri }}, {{
track_recommendations.result.tracks[30].uri }}, {{
track_recommendations.result.tracks[31].uri }}, {{
track_recommendations.result.tracks[32].uri }}, {{
track_recommendations.result.tracks[33].uri }}, {{
track_recommendations.result.tracks[34].uri }}, {{
track_recommendations.result.tracks[35].uri }}, {{
track_recommendations.result.tracks[36].uri }}, {{
track_recommendations.result.tracks[37].uri }}, {{
track_recommendations.result.tracks[38].uri }}, {{
track_recommendations.result.tracks[39].uri }}, {{
track_recommendations.result.tracks[40].uri }}, {{
track_recommendations.result.tracks[41].uri }}, {{
track_recommendations.result.tracks[42].uri }}, {{
track_recommendations.result.tracks[43].uri }}, {{
track_recommendations.result.tracks[44].uri }}, {{
track_recommendations.result.tracks[45].uri }}, {{
track_recommendations.result.tracks[46].uri }}, {{
track_recommendations.result.tracks[47].uri }}, {{
track_recommendations.result.tracks[48].uri }}, {{
track_recommendations.result.tracks[49].uri }}
action: spotifyplus.playlist_items_add
enabled: true
alias: SpotifyPlus | Add Songs to Playlist
- action: input_text.set_value
metadata: {}
data:
value: >-
{{ playlist.result.href |
regex_replace(find='https://api.spotify.com/v1/playlists/',
replace='spotify:playlist:', ignorecase=False) }}
target:
entity_id: input_text.mix_{{ mix_number }}_playlist_url
enabled: true
alias: Playlist Sensor | Set Playlist URL
- action: spotifyplus.playlist_cover_image_add
metadata: {}
data:
playlist_id: >-
{{ playlist.result.href |
regex_replace(find='https://api.spotify.com/v1/playlists/',
replace='', ignorecase=False) }}
image_path: www/images/Playlists/mix_{{ mix_number }}.jpg
entity_id: media_player.your_spotifyplus_player
alias: SpotifyPlus | Add Cover Image
description: Create dynamic playlist with SpotifyPlus.
icon: mdi:spotify
fields:
mix_title:
selector:
select:
options:
- Chill Mix 🌿
- Happy Mix 🔆
- Work Mix ☕
- Psy Mix 🕉️
name: Playlist Title
required: true
default: Chill Mix 🌿
mix_tracks:
selector:
text:
multiple: true
multiline: false
default: []
name: "Insert Song Links:"
required: true
max_speechiness:
name: Maximum Speechiness
description: Maximum value for speech-like characteristics (0.0 to 1.0)
selector:
number:
min: 0
max: 1
step: 0.1
min_popularity:
name: Minimum Popularity
description: Minimum popularity rating (0 to 100)
selector:
number:
min: 0
max: 100
step: 1
min_liveness:
name: Minimum Liveness
description: Minimum liveness value (0.0 to 1.0)
selector:
number:
min: 0
max: 1
step: 0.1
min_instrumentalness:
name: Minimum Instrumentalness
description: Minimum instrumentalness value (0.0 to 1.0)
selector:
number:
min: 0
max: 1
step: 0.1
min_energy:
name: Minimum Energy
description: Minimum energy value (0.0 to 1.0)
selector:
number:
min: 0
max: 1
step: 0.1
min_acousticness:
name: Minimum Acousticness
description: Minimum acousticness value (0.0 to 1.0)
selector:
number:
min: 0
max: 1
step: 0.1