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