144 lines
3.9 KiB
JavaScript
144 lines
3.9 KiB
JavaScript
// Lovelace card for retrieving the current playlist for one of DR's radio stations
|
|
|
|
import {
|
|
LitElement,
|
|
html,
|
|
css,
|
|
until,
|
|
} from "https://cdn.jsdelivr.net/gh/lit/dist@2/all/lit-all.min.js";
|
|
|
|
class DrPlaylistCard extends LitElement {
|
|
baseUrl = "https://api.dr.dk/radio/v2/indexpoints/live";
|
|
radioStations = ["p2", "p3", "p4kbh", "p5kbh", "p6beat", "p8jazz"];
|
|
|
|
static get properties() {
|
|
return {
|
|
hass: {},
|
|
_config: {},
|
|
};
|
|
}
|
|
|
|
setConfig(config) {
|
|
if (!config.entity) {
|
|
throw new Error("You need to define an entity");
|
|
}
|
|
this._config = config;
|
|
}
|
|
|
|
render() {
|
|
const radioStation = this.hass.states[this._config.entity];
|
|
|
|
if (!this.radioStations.includes(radioStation.state)) {
|
|
return html``;
|
|
}
|
|
|
|
return html`${until(
|
|
this.getPlaylist(radioStation.state).then((data) => {
|
|
if (!data) {
|
|
return html`Failed to load playlist`;
|
|
}
|
|
return html`
|
|
<ha-card>
|
|
<h1 class="card-header">
|
|
<div class="name">${data.channel.title}</div>
|
|
</h1>
|
|
<table class="playlist">
|
|
<tbody>
|
|
${data.items.map(
|
|
(song) =>
|
|
html`<tr>
|
|
<td class="song">
|
|
<span class="title">${song.title}</span
|
|
><span class="artist">${song.roles[0].name}</span>
|
|
</td>
|
|
<td class="played">${song.playedTime}</td>
|
|
</tr>`
|
|
)}
|
|
</tbody>
|
|
</table>
|
|
</ha-card>
|
|
`;
|
|
}),
|
|
html`Loading`
|
|
)}`;
|
|
}
|
|
|
|
getCardSize() {
|
|
return 5;
|
|
}
|
|
|
|
async getPlaylist(station) {
|
|
const localCache = localStorage.getItem(station);
|
|
|
|
if (localCache) {
|
|
const localData = JSON.parse(localCache);
|
|
|
|
if (localData.created > Date.now() - 60000) {
|
|
return localData.data;
|
|
}
|
|
}
|
|
|
|
const response = await fetch(`${this.baseUrl}/${station}`, {
|
|
headers: {
|
|
Accept: "application/json",
|
|
},
|
|
});
|
|
|
|
if (!response.ok && localCache) {
|
|
return localData;
|
|
} else if (!response.ok) {
|
|
return null;
|
|
}
|
|
|
|
let data = await response.json();
|
|
|
|
data.items.forEach((element) => {
|
|
let played = new Date(element.playedTime);
|
|
element.playedTime = played.toTimeString().substring(0, 5);
|
|
});
|
|
|
|
const playlist = {
|
|
data: data,
|
|
created: Date.now(),
|
|
};
|
|
|
|
localStorage.setItem(station, JSON.stringify(playlist));
|
|
|
|
return data;
|
|
}
|
|
|
|
static get styles() {
|
|
return css`
|
|
table {
|
|
padding: 0 16px 16px;
|
|
width: 100%;
|
|
}
|
|
|
|
tr:nth-child(2n) {
|
|
background-color: var(--secondary-background-color, #eee);
|
|
}
|
|
|
|
td {
|
|
padding: 5px;
|
|
text-align: left;
|
|
}
|
|
|
|
.song .title {
|
|
border-right: 1px solid var(--primary-text-color);
|
|
font-weight: bold;
|
|
padding-right: 7px;
|
|
}
|
|
|
|
.artist {
|
|
padding-left: 5px;
|
|
}
|
|
|
|
.played {
|
|
text-align: right;
|
|
}
|
|
`;
|
|
}
|
|
}
|
|
|
|
customElements.define("dr-playlist-card", DrPlaylistCard);
|