Skip to content

Instantly share code, notes, and snippets.

@sn123
Last active April 13, 2020 08:48
Show Gist options
  • Save sn123/dc903fb6d19ad793505fecc1b52536f7 to your computer and use it in GitHub Desktop.
Save sn123/dc903fb6d19ad793505fecc1b52536f7 to your computer and use it in GitHub Desktop.
A #Mopidy client for Mustard. Displays the currently playing tracks along with album art & tags from last.fm
<template>
<div class="center mopidy">
<h4>Now Playing</h4>
<div :v-if="model.name">
<img :src="model.albumArt" />
<div>
<h4>{{ model.artist }}</h4>
<h3>{{ model.name }}</h3>
<p>{{ model.tags }}</p>
</div>
</div>
</div>
</template>
<script lang="ts">
import { Component, Prop, Vue } from "vue-property-decorator";
import { scriptLoader } from "../script-loader";
type TrackModel = {
name: string;
artist: string;
album: string;
albumArt: string;
tags: string;
};
type NameType = { name: string };
type TrackInfo = { name: string; album: NameType; artists: Array<NameType> };
type T1Track = { track: TrackInfo };
type MopidyTrack = { tl_track: T1Track };
@Component
export default class MopidyClient extends Vue {
@Prop() private mopidyWsUrl?: string;
private lastFmKey?: string = process.env.VUE_APP_LASTFM_KEY;
private model: TrackModel = {
name: "",
artist: "",
album: "",
albumArt: "https://via.placeholder.com/150",
tags: ""
};
mounted() {
scriptLoader(
"https://github.com/mopidy/mopidy.js/releases/download/v1.1.0/mopidy-1.1.0.js",
true
).then(() => {
const options = {
webSocketUrl: this.mopidyWsUrl
},
mopidy = new (window as any).Mopidy(options);
mopidy.on("event:trackPlaybackStarted", (track: MopidyTrack) => {
// eslint-disable-next-line @typescript-eslint/camelcase
const { tl_track, ...rest } = track,
// eslint-disable-next-line @typescript-eslint/camelcase
trackInfo = tl_track,
nowPlaying: TrackModel = {
name: trackInfo.track.name,
album: trackInfo.track.album ? trackInfo.track.album.name : "",
artist: Array.isArray(trackInfo.track.artists)
? trackInfo.track.artists[0].name
: "",
albumArt: "https://via.placeholder.com/150",
tags: ""
};
this.model = { ...nowPlaying };
if ((this.lastFmKey || "").length > 0) {
(async () => {
const lastQuery = {
format: "json",
method: "album.getInfo",
album: this.model.album,
artist: this.model.artist,
// eslint-disable-next-line @typescript-eslint/camelcase
api_key: this.lastFmKey
},
qs = this.objectToQs(lastQuery);
try {
const response = await fetch(
`https://ws.audioscrobbler.com/2.0/?${qs}`,
{
method: "GET"
}
),
jsonResponse = await response.json();
if (jsonResponse.error) {
// console.warn("received error", jsonResponse);
return;
}
if (
!jsonResponse.album ||
!Array.isArray(jsonResponse.album.image)
) {
// console.warn("didn't get album", jsonResponse.album);
return;
}
const image = (jsonResponse.album.image as []).find(
(el: any) => el.size === "large"
),
tags = (jsonResponse.album.tags.tag as [])
.map((t: any) => t.name)
.join(", ");
if (!image) {
return;
}
const albumArt = image["#text"];
this.model = { ...this.model, albumArt, tags };
} catch (err) {
// console.warn(err);
}
})();
}
});
});
}
objectToQs(object: Record<string, any>) {
return Object.keys(object)
.map(key => {
return encodeURIComponent(key) + "=" + encodeURIComponent(object[key]);
})
.join("&");
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped lang="scss">
.mopidy {
background: #2a9d8f;
flex-direction: column;
> h4 {
padding-bottom: 10px;
}
> div {
display: flex;
flex-direction: row;
> img {
margin-left: 5px;
border-radius: 5px;
max-width: 150px;
}
}
}
</style>
@sn123
Copy link
Author

sn123 commented Apr 12, 2020

A Now playing widget for Mustard .

Setting up

Install this gist by running $ mustard -gist=dc903fb6d19ad793505fecc1b52536f7

Configuration

In App.Vue add this component and set your Mopidy WebSockets Url. If the Mopidy has Cors protection, than mustard host and port have to be whitelisted in mopidy http configuration.

<MopidyClient mopidyWsUrl="ws://<MopidyServer>/mopidy/ws/" />

Album info and art

Requires last.fm API key - these need to be set in .env file in /client folder:
.env:

VUE_APP_LASTFM_KEY=VUE_APP_LASTFM_KEY

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment