Skip to content

Commit 39458e4

Browse files
committed
Spotify album search
1 parent 42344aa commit 39458e4

File tree

4 files changed

+153
-29
lines changed

4 files changed

+153
-29
lines changed

DiscordMusicBotController/config.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
2-
<widget id="com.simontod.discordmusicbotcontroller" version="0.3.0" xmlns="http://www.w3.org/ns/widgets" xmlns:vs="http://schemas.microsoft.com/appx/2014/htmlapps" xmlns:cdv="http://cordova.apache.org/ns/1.0" defaultLocale="fr-FR" android-versionCode="3">
2+
<widget id="com.simontod.discordmusicbotcontroller" version="0.4.0" xmlns="http://www.w3.org/ns/widgets" xmlns:vs="http://schemas.microsoft.com/appx/2014/htmlapps" xmlns:cdv="http://cordova.apache.org/ns/1.0" defaultLocale="fr-FR" android-versionCode="4">
33
<name>DiscordMusicBotController</name>
44
<description>A project made with Ionic Framework and Cordova</description>
55
<author email="[email protected]" href="http://taco.visualstudio.com">DiscordMusicBotController</author>

DiscordMusicBotController/src/app/app.module.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import { ConfigurePage } from '../pages/configure/configure';
1010
import { DiscordApiProvider } from '../providers/DiscordApi';
1111
import { AlertsProvider } from '../providers/Alerts';
1212
import { YoutubePage, youTubeServiceInjectables, YoutubeSearchResultComponent, YoutubeSearchBox } from '../pages/youtube/youtube';
13-
import { SpotifyPage, spotifyServiceInjectables, SpotifySearchResultComponent, SpotifySearchBox } from '../pages/spotify/spotify';
13+
import { SpotifyPage, spotifyServiceInjectables, SpotifyTracksSearchResultComponent, SpotifyAlbumsSearchResultComponent, SpotifySearchBox } from '../pages/spotify/spotify';
1414

1515
@NgModule({
1616
declarations: [
@@ -24,7 +24,8 @@ import { SpotifyPage, spotifyServiceInjectables, SpotifySearchResultComponent, S
2424
YoutubeSearchResultComponent,
2525
YoutubeSearchBox,
2626
SpotifyPage,
27-
SpotifySearchResultComponent,
27+
SpotifyTracksSearchResultComponent,
28+
SpotifyAlbumsSearchResultComponent,
2829
SpotifySearchBox
2930
],
3031
imports: [
@@ -43,7 +44,8 @@ import { SpotifyPage, spotifyServiceInjectables, SpotifySearchResultComponent, S
4344
YoutubeSearchResultComponent,
4445
YoutubeSearchBox,
4546
SpotifyPage,
46-
SpotifySearchResultComponent,
47+
SpotifyTracksSearchResultComponent,
48+
SpotifyAlbumsSearchResultComponent,
4749
SpotifySearchBox
4850
],
4951
providers: [DiscordApiProvider, AlertsProvider, youTubeServiceInjectables, spotifyServiceInjectables, { provide: ErrorHandler, useClass: IonicErrorHandler }],

DiscordMusicBotController/src/pages/spotify/spotify.html

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,33 @@ <h2>
1313
<div class="row">
1414
<div class="input-group input-group-lg col-md-12">
1515
<spotify-search-box (loading)="loading = $event"
16-
(results)="updateResults($event)"></spotify-search-box>
16+
(tracksResults)="updateTracksResults($event)"
17+
(albumsResults)="updateAlbumsResults($event)"></spotify-search-box>
1718
</div>
1819
</div>
19-
<div class="row">
20-
<spotify-search-result *ngFor="let result of results"
21-
[result]="result">
22-
</spotify-search-result>
20+
<div padding>
21+
<ion-segment [(ngModel)]="type">
22+
<ion-segment-button value="tracks">
23+
Tracks
24+
</ion-segment-button>
25+
<ion-segment-button value="albums">
26+
Albums
27+
</ion-segment-button>
28+
</ion-segment>
29+
</div>
30+
<div [ngSwitch]="type">
31+
<div class="row" *ngSwitchCase="'tracks'">
32+
<spotify-tracks-search-result *ngFor="let result of tracksResults"
33+
[result]="result">
34+
</spotify-tracks-search-result>
35+
</div>
36+
37+
<div class="row" *ngSwitchCase="'albums'">
38+
<spotify-albums-search-result *ngFor="let result of albumsResults"
39+
[result]="result">
40+
</spotify-albums-search-result>
41+
</div>
2342
</div>
43+
2444
</div>
2545
</ion-content>

DiscordMusicBotController/src/pages/spotify/spotify.ts

Lines changed: 122 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,12 @@ class Token {
2323
}
2424
}
2525

26-
class SpotifySearchResult {
26+
class SpotifyTrackSearchResult {
2727
id: string;
2828
name: string;
2929
type: string;
3030
artists: Array<string>;
31-
album: Album;
31+
album: SpotifyAlbumSearchResult;
3232
uri: string;
3333

3434
constructor(obj?: any) {
@@ -37,19 +37,23 @@ class SpotifySearchResult {
3737
this.type = obj && obj.type || null;
3838
this.artists = obj && obj.artists || null;
3939
this.album = obj && obj.album || null;
40-
this.uri = obj && obj.uri || null
40+
this.uri = obj && obj.uri || null;
4141
}
4242
}
4343

44-
class Album {
44+
class SpotifyAlbumSearchResult {
4545
id: string;
4646
name: string;
4747
image: string;
48+
artists: Array<string>;
49+
uri: string;
4850

4951
constructor(obj?: any) {
5052
this.id = obj && obj.id || null;
5153
this.name = obj && obj.name || null;
5254
this.image = obj && obj.image || null;
55+
this.artists = obj && obj.artists || null;
56+
this.uri = obj && obj.uri || null;
5357
}
5458
}
5559

@@ -66,7 +70,7 @@ export class SpotifyService {
6670

6771
}
6872

69-
search(query: string): Observable<SpotifySearchResult[]> {
73+
searchTracks(query: string): Observable<SpotifyTrackSearchResult[]> {
7074
let params: string = [
7175
`q=${query}`,
7276
`type=track`
@@ -81,12 +85,12 @@ export class SpotifyService {
8185
for (var i = 0; i < item.artists.length; i++) {
8286
artists.push(item.artists[i].name);
8387
}
84-
var album = new Album({
88+
var album = new SpotifyAlbumSearchResult({
8589
id: item.album.id,
8690
name: item.album.name,
87-
image: item.album.images[0].url
91+
image: item.album.images[0].url,
8892
})
89-
return new SpotifySearchResult({
93+
return new SpotifyTrackSearchResult({
9094
id: item.id,
9195
name: item.name,
9296
type: item.type,
@@ -98,6 +102,32 @@ export class SpotifyService {
98102
});
99103
}
100104

105+
searchAlbums(query: string): Observable<SpotifyAlbumSearchResult[]> {
106+
let params: string = [
107+
`q=${query}`,
108+
`type=album`
109+
].join('&');
110+
let queryUrl: string = `${this.apiBase}search?${params}`;
111+
112+
return Observable.fromPromise(this.getToken())
113+
.flatMap(token => this.http.get(queryUrl, { headers: new Headers({ 'Authorization': `${token.token_type} ${token.access_token}` }) }))
114+
.map((response: Response) => {
115+
return (<any>response.json()).albums.items.map(item => {
116+
var artists = new Array<string>();
117+
for (var i = 0; i < item.artists.length; i++) {
118+
artists.push(item.artists[i].name);
119+
}
120+
return new SpotifyAlbumSearchResult({
121+
id: item.id,
122+
name: item.name,
123+
image: item.images[0].url,
124+
artists: artists,
125+
uri: item.uri
126+
});
127+
});
128+
});
129+
}
130+
101131
getToken(): Promise<Token> {
102132
let params: string = "grant_type=client_credentials";
103133
let headers = new Headers({
@@ -127,7 +157,7 @@ export var spotifyServiceInjectables: Array<any> = [
127157
];
128158

129159
@Component({
130-
outputs: ['loading', 'results'],
160+
outputs: ['loading', 'tracksResults', 'albumsResults'],
131161
selector: 'spotify-search-box',
132162
template: `
133163
<p>Enter something in the field and see the asynchronous results!</p>
@@ -137,24 +167,26 @@ export var spotifyServiceInjectables: Array<any> = [
137167

138168
export class SpotifySearchBox implements OnInit {
139169
loading: EventEmitter<boolean> = new EventEmitter<boolean>();
140-
results: EventEmitter<SpotifySearchResult[]> = new EventEmitter<SpotifySearchResult[]>();
170+
tracksResults: EventEmitter<SpotifyTrackSearchResult[]> = new EventEmitter<SpotifyTrackSearchResult[]>();
171+
albumsResults: EventEmitter<SpotifyAlbumSearchResult[]> = new EventEmitter<SpotifyAlbumSearchResult[]>();
141172

142173
constructor(public spotify: SpotifyService,
143174
private el: ElementRef) {
144175
}
145176

146177
ngOnInit(): void {
178+
//tracks
147179
Observable.fromEvent(this.el.nativeElement, 'keyup')
148180
.map((e: any) => e.target.value)
149181
.filter((text: string) => text.length > 1)
150182
.debounceTime(250)
151183
.do(() => this.loading.next(true))
152-
.map((query: string) => this.spotify.search(query))
184+
.map((query: string) => this.spotify.searchTracks(query))
153185
.switch()
154186
.subscribe(
155-
(results: SpotifySearchResult[]) => {
187+
(tracksResults: SpotifyTrackSearchResult[]) => {
156188
this.loading.next(false);
157-
this.results.next(results);
189+
this.tracksResults.next(tracksResults);
158190
},
159191
(err: any) => {
160192
console.log(err);
@@ -164,12 +196,34 @@ export class SpotifySearchBox implements OnInit {
164196
this.loading.next(false);
165197
}
166198
);
199+
200+
//albums
201+
Observable.fromEvent(this.el.nativeElement, 'keyup')
202+
.map((e: any) => e.target.value)
203+
.filter((text: string) => text.length > 1)
204+
.debounceTime(250)
205+
.do(() => this.loading.next(true))
206+
.map((query: string) => this.spotify.searchAlbums(query))
207+
.switch()
208+
.subscribe(
209+
(albumsResults: SpotifyAlbumSearchResult[]) => {
210+
this.loading.next(false);
211+
this.albumsResults.next(albumsResults);
212+
},
213+
(err: any) => {
214+
console.log(err);
215+
this.loading.next(false);
216+
},
217+
() => {
218+
this.loading.next(false);
219+
}
220+
)
167221
}
168222
}
169223

170224
@Component({
171225
inputs: ['result'],
172-
selector: 'spotify-search-result',
226+
selector: 'spotify-tracks-search-result',
173227
template: `
174228
<ion-card>
175229
<ion-item>
@@ -195,8 +249,49 @@ export class SpotifySearchBox implements OnInit {
195249
`
196250
})
197251

198-
export class SpotifySearchResultComponent {
199-
result: SpotifySearchResult;
252+
export class SpotifyTracksSearchResultComponent {
253+
tracksResult: SpotifyTrackSearchResult;
254+
255+
constructor(public navCtrl: NavController, public discordApi: DiscordApiProvider) {
256+
257+
}
258+
259+
Play(query) {
260+
this.discordApi.sendCommand(this.discordApi.Commands.play, query);
261+
this.navCtrl.pop();
262+
}
263+
}
264+
265+
@Component({
266+
inputs: ['result'],
267+
selector: 'spotify-albums-search-result',
268+
template: `
269+
<ion-card>
270+
<ion-item>
271+
<ion-avatar item-start>
272+
<img src="{{result.image}}">
273+
</ion-avatar>
274+
<h2>{{result.name}}</h2>
275+
<!--<p>{{result.artists}}</p>-->
276+
</ion-item>
277+
<img src="{{result.image}}">
278+
<ion-card-content>
279+
<p>Album: {{result.name}}</p>
280+
</ion-card-content>
281+
<ion-row>
282+
<ion-col>
283+
<button ion-button icon-left clear small (click)="Play(result.uri)">
284+
<ion-icon name="play"></ion-icon>
285+
<div>Play</div>
286+
</button>
287+
</ion-col>
288+
</ion-row>
289+
</ion-card>
290+
`
291+
})
292+
293+
export class SpotifyAlbumsSearchResultComponent {
294+
albumsResult: SpotifyAlbumSearchResult;
200295

201296
constructor(public navCtrl: NavController, public discordApi: DiscordApiProvider) {
202297

@@ -213,16 +308,23 @@ export class SpotifySearchResultComponent {
213308
templateUrl: 'spotify.html'
214309
})
215310
export class SpotifyPage {
311+
type = "";
312+
tracksResults: SpotifyTrackSearchResult[];
313+
albumsResults: SpotifyAlbumSearchResult[];
216314

217-
constructor(public navCtrl: NavController, public navParams: NavParams) { }
315+
constructor(public navCtrl: NavController, public navParams: NavParams) {
316+
this.type = 'tracks';
317+
}
218318

219319
ionViewDidLoad() {
220320
console.log('ionViewDidLoad SpotifyPage');
221321
}
222322

223-
results: SpotifySearchResult[];
323+
updateTracksResults(results: SpotifyTrackSearchResult[]): void {
324+
this.tracksResults = results;
325+
}
224326

225-
updateResults(results: SpotifySearchResult[]): void {
226-
this.results = results;
327+
updateAlbumsResults(results: SpotifyAlbumSearchResult[]): void {
328+
this.albumsResults = results;
227329
}
228330
}

0 commit comments

Comments
 (0)