normalize responses and add types
This commit is contained in:
parent
b8db546f64
commit
8fb1f8db78
@ -14,6 +14,7 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Vue from 'vue'
|
import Vue from 'vue'
|
||||||
import AlbumList from '@/library/album/AlbumList.vue'
|
import AlbumList from '@/library/album/AlbumList.vue'
|
||||||
|
import { Album } from '@/shared/api'
|
||||||
|
|
||||||
export default Vue.extend({
|
export default Vue.extend({
|
||||||
components: {
|
components: {
|
||||||
@ -22,10 +23,10 @@
|
|||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
loading: true as boolean,
|
loading: true as boolean,
|
||||||
recent: [],
|
recent: [] as Album[],
|
||||||
newest: [],
|
newest: [] as Album[],
|
||||||
frequent: [],
|
frequent: [] as Album[],
|
||||||
random: [],
|
random: [] as Album[],
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<TrackList :tracks="album.song" />
|
<TrackList :tracks="album.tracks" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -29,6 +29,7 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Vue from 'vue'
|
import Vue from 'vue'
|
||||||
import TrackList from '@/library/TrackList.vue'
|
import TrackList from '@/library/TrackList.vue'
|
||||||
|
import { Album } from '@/shared/api'
|
||||||
|
|
||||||
export default Vue.extend({
|
export default Vue.extend({
|
||||||
components: {
|
components: {
|
||||||
@ -39,7 +40,7 @@
|
|||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
album: null,
|
album: null as null | Album,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
async mounted() {
|
async mounted() {
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Vue from 'vue'
|
import Vue from 'vue'
|
||||||
import AlbumList from './AlbumList.vue'
|
import AlbumList from './AlbumList.vue'
|
||||||
import { AlbumSort } from '@/shared/api'
|
import { AlbumSort, Album } from '@/shared/api'
|
||||||
|
|
||||||
export default Vue.extend({
|
export default Vue.extend({
|
||||||
components: {
|
components: {
|
||||||
@ -17,7 +17,7 @@
|
|||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
sort: 'newest',
|
sort: 'newest',
|
||||||
albums: null,
|
albums: null as null | Album[],
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Vue from 'vue'
|
import Vue from 'vue'
|
||||||
import ArtistList from './ArtistList.vue'
|
import ArtistList from './ArtistList.vue'
|
||||||
|
import { Artist } from '@/shared/api'
|
||||||
|
|
||||||
export default Vue.extend({
|
export default Vue.extend({
|
||||||
components: {
|
components: {
|
||||||
@ -11,7 +12,7 @@
|
|||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
items: []
|
items: [] as Artist[]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
|
@ -3,6 +3,50 @@ import { AuthService } from '@/auth/service'
|
|||||||
|
|
||||||
export type AlbumSort = 'alphabeticalByName' | 'newest' | 'recent' | 'frequent' | 'random'
|
export type AlbumSort = 'alphabeticalByName' | 'newest' | 'recent' | 'frequent' | 'random'
|
||||||
|
|
||||||
|
export interface Album {
|
||||||
|
id: string
|
||||||
|
name: string
|
||||||
|
artist: string
|
||||||
|
artistId: string
|
||||||
|
year: number
|
||||||
|
starred: boolean
|
||||||
|
image?: string
|
||||||
|
tracks?: Track[]
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Artist {
|
||||||
|
id: string
|
||||||
|
name: string
|
||||||
|
albumCount: number
|
||||||
|
description?: string
|
||||||
|
starred: boolean
|
||||||
|
image?: string
|
||||||
|
lastFmUrl?: string
|
||||||
|
musicBrainzUrl?: string
|
||||||
|
similarArtist?: Artist[]
|
||||||
|
albums?: Album[]
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Track {
|
||||||
|
id: string
|
||||||
|
title: string
|
||||||
|
duration: number
|
||||||
|
starred: boolean
|
||||||
|
image?: string
|
||||||
|
url?: string
|
||||||
|
track?: number
|
||||||
|
album?: string
|
||||||
|
albumId?: string
|
||||||
|
artist?: string
|
||||||
|
artistId?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SearchResult {
|
||||||
|
artists: Artist[]
|
||||||
|
albums: Album[]
|
||||||
|
tracks: Track[]
|
||||||
|
}
|
||||||
|
|
||||||
export class API {
|
export class API {
|
||||||
readonly http: AxiosInstance;
|
readonly http: AxiosInstance;
|
||||||
readonly get: (path: string, params?: any) => Promise<any>;
|
readonly get: (path: string, params?: any) => Promise<any>;
|
||||||
@ -67,70 +111,41 @@ export class API {
|
|||||||
const response = await this.get('rest/getSongsByGenre', params)
|
const response = await this.get('rest/getSongsByGenre', params)
|
||||||
return {
|
return {
|
||||||
name: id,
|
name: id,
|
||||||
tracks: this.normalizeTrackList(response.songsByGenre?.song || []),
|
tracks: (response.songsByGenre?.song || []).map(this.normalizeTrack, this),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async getArtists() {
|
async getArtists(): Promise<Artist[]> {
|
||||||
const response = await this.get('rest/getArtists')
|
const response = await this.get('rest/getArtists')
|
||||||
return (response.artists?.index || []).flatMap((index: any) => index.artist.map((artist: any) => ({
|
return (response.artists?.index || [])
|
||||||
id: artist.id,
|
.flatMap((index: any) => index.artist)
|
||||||
name: artist.name,
|
.map(this.normalizeArtist, this)
|
||||||
...artist
|
|
||||||
})))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async getAlbums(sort: AlbumSort, size = 500) {
|
async getAlbums(sort: AlbumSort, size = 500): Promise<Album[]> {
|
||||||
const params = {
|
const params = {
|
||||||
type: sort,
|
type: sort,
|
||||||
offset: '0',
|
offset: '0',
|
||||||
size: size,
|
size: size,
|
||||||
}
|
}
|
||||||
const response = await this.get('rest/getAlbumList2', params)
|
const response = await this.get('rest/getAlbumList2', params)
|
||||||
return (response.albumList2?.album || []).map((item: any) => ({
|
const albums = response.albumList2?.album || []
|
||||||
...item,
|
return albums.map(this.normalizeAlbum, this)
|
||||||
image: item.coverArt ? this.getCoverArtUrl(item) : undefined,
|
|
||||||
}))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async getArtistDetails(id: string) {
|
async getArtistDetails(id: string): Promise<Artist> {
|
||||||
const params = { id }
|
const params = { id }
|
||||||
const [info1, info2] = await Promise.all([
|
const [info1, info2] = await Promise.all([
|
||||||
this.get('rest/getArtist', params).then(r => r.artist),
|
this.get('rest/getArtist', params).then(r => r.artist),
|
||||||
this.get('rest/getArtistInfo2', params).then(r => r.artistInfo2),
|
this.get('rest/getArtistInfo2', params).then(r => r.artistInfo2),
|
||||||
])
|
])
|
||||||
return {
|
return this.normalizeArtist({ ...info1, ...info2 })
|
||||||
id: info1.id,
|
|
||||||
name: info1.name,
|
|
||||||
description: (info2.biography || '').replace(/<a[^>]*>.*?<\/a>/gm, ''),
|
|
||||||
image: info2.largeImageUrl || info2.mediumImageUrl || info2.smallImageUrl,
|
|
||||||
lastFmUrl: info2.lastFmUrl,
|
|
||||||
musicBrainzUrl: info2.musicBrainzId
|
|
||||||
? `https://musicbrainz.org/artist/${info2.musicBrainzId}` : null,
|
|
||||||
albums: info1.album.map((album: any) => this.normalizeAlbum(album)),
|
|
||||||
similarArtist: (info2.similarArtist || []).map((artist: any) => ({
|
|
||||||
id: artist.id,
|
|
||||||
name: artist.name,
|
|
||||||
...artist
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async getAlbumDetails(id: string) {
|
async getAlbumDetails(id: string): Promise<Album> {
|
||||||
const params = { id }
|
const params = { id }
|
||||||
const data = await this.get('rest/getAlbum', params)
|
const data = await this.get('rest/getAlbum', params)
|
||||||
const item = data.album
|
return this.normalizeAlbum(data.album)
|
||||||
const image = this.getCoverArtUrl(item)
|
|
||||||
const trackList = item.song.map((s: any) => ({
|
|
||||||
...s,
|
|
||||||
image,
|
|
||||||
url: this.getStreamUrl(s.id),
|
|
||||||
}))
|
|
||||||
return {
|
|
||||||
...item,
|
|
||||||
image,
|
|
||||||
song: trackList,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async getPlaylists() {
|
async getPlaylists() {
|
||||||
@ -154,7 +169,7 @@ export class API {
|
|||||||
return {
|
return {
|
||||||
...response.playlist,
|
...response.playlist,
|
||||||
name: response.playlist.name || '(Unnamed)',
|
name: response.playlist.name || '(Unnamed)',
|
||||||
tracks: this.normalizeTrackList(response.playlist.entry || []),
|
tracks: (response.playlist.entry || []).map(this.normalizeTrack, this),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -183,12 +198,12 @@ export class API {
|
|||||||
await this.get('rest/updatePlaylist', params)
|
await this.get('rest/updatePlaylist', params)
|
||||||
}
|
}
|
||||||
|
|
||||||
async getRandomSongs() {
|
async getRandomSongs(): Promise<Track[]> {
|
||||||
const params = {
|
const params = {
|
||||||
size: 200,
|
size: 200,
|
||||||
}
|
}
|
||||||
const response = await this.get('rest/getRandomSongs', params)
|
const response = await this.get('rest/getRandomSongs', params)
|
||||||
return this.normalizeTrackList(response.randomSongs?.song || [])
|
return (response.randomSongs?.song || []).map(this.normalizeTrack, this)
|
||||||
}
|
}
|
||||||
|
|
||||||
async getStarred() {
|
async getStarred() {
|
||||||
@ -196,7 +211,7 @@ export class API {
|
|||||||
return {
|
return {
|
||||||
albums: (response.starred2?.album || []).map(this.normalizeAlbum, this),
|
albums: (response.starred2?.album || []).map(this.normalizeAlbum, this),
|
||||||
artists: (response.starred2?.artist || []).map(this.normalizeArtist, this),
|
artists: (response.starred2?.artist || []).map(this.normalizeArtist, this),
|
||||||
tracks: this.normalizeTrackList(response.starred2?.song || [])
|
tracks: (response.starred2?.song || []).map(this.normalizeTrack, this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -218,37 +233,61 @@ export class API {
|
|||||||
await this.get('rest/unstar', params)
|
await this.get('rest/unstar', params)
|
||||||
}
|
}
|
||||||
|
|
||||||
async search(query: string) {
|
async search(query: string): Promise<SearchResult> {
|
||||||
const params = {
|
const params = {
|
||||||
query,
|
query,
|
||||||
}
|
}
|
||||||
const data = await this.get('rest/search3', params)
|
const data = await this.get('rest/search3', params)
|
||||||
return {
|
return {
|
||||||
tracks: this.normalizeTrackList(data.searchResult3.song || []),
|
tracks: (data.searchResult3.song || []).map(this.normalizeTrack, this),
|
||||||
albums: (data.searchResult3.album || []).map((x: any) => this.normalizeAlbum(x)),
|
albums: (data.searchResult3.album || []).map(this.normalizeAlbum, this),
|
||||||
artists: (data.searchResult3.artist || []).map((x: any) => this.normalizeArtist(x)),
|
artists: (data.searchResult3.artist || []).map(this.normalizeArtist, this),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private normalizeTrackList(items: any[]) {
|
private normalizeTrack(item: any): Track {
|
||||||
return items.map(item => ({
|
return {
|
||||||
...item,
|
id: item.id,
|
||||||
|
title: item.title,
|
||||||
|
duration: item.duration,
|
||||||
|
starred: !!item.starred,
|
||||||
|
track: item.track,
|
||||||
|
album: item.album,
|
||||||
|
albumId: item.albumId,
|
||||||
|
artist: item.artist,
|
||||||
|
artistId: item.artistId,
|
||||||
url: this.getStreamUrl(item.id),
|
url: this.getStreamUrl(item.id),
|
||||||
image: this.getCoverArtUrl(item),
|
image: this.getCoverArtUrl(item),
|
||||||
}))
|
|
||||||
}
|
|
||||||
|
|
||||||
private normalizeAlbum(item: any) {
|
|
||||||
return {
|
|
||||||
...item,
|
|
||||||
image: this.getCoverArtUrl(item)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private normalizeArtist(item: any) {
|
private normalizeAlbum(item: any): Album {
|
||||||
return {
|
return {
|
||||||
...item,
|
id: item.id,
|
||||||
image: this.getCoverArtUrl(item)
|
name: item.name,
|
||||||
|
artist: item.artist,
|
||||||
|
artistId: item.artistId,
|
||||||
|
image: this.getCoverArtUrl(item),
|
||||||
|
year: item.year || 0,
|
||||||
|
starred: !!item.starred,
|
||||||
|
tracks: (item.song || []).map(this.normalizeTrack, this)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private normalizeArtist(item: any): Artist {
|
||||||
|
return {
|
||||||
|
id: item.id,
|
||||||
|
name: item.name,
|
||||||
|
description: (item.biography || '').replace(/<a[^>]*>.*?<\/a>/gm, ''),
|
||||||
|
starred: !!item.starred,
|
||||||
|
image: item.largeImageUrl || item.mediumImageUrl || item.smallImageUrl,
|
||||||
|
albumCount: item.albumCount,
|
||||||
|
lastFmUrl: item.lastFmUrl,
|
||||||
|
musicBrainzUrl: item.musicBrainzId
|
||||||
|
? `https://musicbrainz.org/artist/${item.musicBrainzId}`
|
||||||
|
: undefined,
|
||||||
|
albums: item.album?.map(this.normalizeAlbum, this),
|
||||||
|
similarArtist: (item.similarArtist || []).map(this.normalizeArtist, this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user