@@ -66,6 +66,41 @@ type TraktMoviesResponse struct {
66
66
Movie * TraktMovie `json:"movie"`
67
67
}
68
68
69
+ type TraktShowIds struct {
70
+ Trakt int `json:"trakt"`
71
+ Slug string `json:"slug"`
72
+ Tvdb int `json:"tvdb"`
73
+ Imdb string `json:"imdb"`
74
+ Tmdb int `json:"tmdb"`
75
+ }
76
+
77
+ type TraktShow struct {
78
+ Title string `json:"title"`
79
+ Year int `json:"year"`
80
+ Ids TraktShowIds `json:"ids"`
81
+ Overview string `json:"overview"`
82
+ FirstAired time.Time `json:"first_aired"`
83
+ Runtime int `json:"runtime"`
84
+ Certification string `json:"certification"`
85
+ Network string `json:"network"`
86
+ Country string `json:"country"`
87
+ Trailer string `json:"trailer"`
88
+ Homepage string `json:"homepage"`
89
+ Status string `json:"status"`
90
+ Rating float64 `json:"rating"`
91
+ Votes int `json:"votes"`
92
+ CommentCount int `json:"comment_count"`
93
+ Language string `json:"language"`
94
+ AvailableTranslations []string `json:"available_translations"`
95
+ Genres []string `json:"genres"`
96
+ AiredEpisodes int `json:"aired_episodes"`
97
+ }
98
+
99
+ type TraktShowsResponse struct {
100
+ TraktShow
101
+ Show * TraktShow `json:"show"`
102
+ }
103
+
69
104
/* Initializer */
70
105
71
106
func NewTrakt () * Trakt {
@@ -79,7 +114,9 @@ func NewTrakt() *Trakt {
79
114
80
115
genres : make (map [int ]string , 0 ),
81
116
82
- supportedShowsSearchTypes : []string {},
117
+ supportedShowsSearchTypes : []string {
118
+ SearchTypePopular ,
119
+ },
83
120
supportedMoviesSearchTypes : []string {
84
121
SearchTypeTrending ,
85
122
SearchTypeUpcoming ,
@@ -94,7 +131,7 @@ func NewTrakt() *Trakt {
94
131
func (p * Trakt ) Init (mediaType MediaType , cfg map [string ]string ) error {
95
132
// validate we support this media type
96
133
switch mediaType {
97
- case Movie :
134
+ case Movie , Show :
98
135
break
99
136
default :
100
137
return errors .New ("unsupported media type" )
@@ -142,7 +179,15 @@ func (p *Trakt) SupportsMoviesSearchType(searchType string) bool {
142
179
}
143
180
144
181
func (p * Trakt ) GetShows (searchType string , logic map [string ]interface {}, params map [string ]string ) (map [string ]config.MediaItem , error ) {
145
- return nil , errors .New ("unsupported media type" )
182
+
183
+ switch searchType {
184
+ case SearchTypePopular :
185
+ return p .getShows ("/shows/popular" , logic , params )
186
+ default :
187
+ break
188
+ }
189
+
190
+ return nil , fmt .Errorf ("unsupported search_type: %q" , searchType )
146
191
}
147
192
148
193
func (p * Trakt ) GetMovies (searchType string , logic map [string ]interface {}, params map [string ]string ) (map [string ]config.MediaItem , error ) {
@@ -197,7 +242,7 @@ func (p *Trakt) getRequestParams(params map[string]string) req.Param {
197
242
return reqParams
198
243
}
199
244
200
- func (p * Trakt ) translateTraktMovie (response TraktMoviesResponse ) * TraktMovie {
245
+ func (p * Trakt ) translateMovie (response TraktMoviesResponse ) * TraktMovie {
201
246
if response .Movie != nil {
202
247
return response .Movie
203
248
}
@@ -229,6 +274,40 @@ func (p *Trakt) translateTraktMovie(response TraktMoviesResponse) *TraktMovie {
229
274
}
230
275
}
231
276
277
+ func (p * Trakt ) translateShow (response TraktShowsResponse ) * TraktShow {
278
+ if response .Show != nil {
279
+ return response .Show
280
+ }
281
+
282
+ return & TraktShow {
283
+ Title : response .Title ,
284
+ Year : response .Year ,
285
+ Ids : TraktShowIds {
286
+ Trakt : response .Ids .Trakt ,
287
+ Slug : response .Ids .Slug ,
288
+ Tvdb : response .Ids .Tvdb ,
289
+ Imdb : response .Ids .Imdb ,
290
+ Tmdb : response .Ids .Tmdb ,
291
+ },
292
+ Overview : response .Overview ,
293
+ FirstAired : response .FirstAired ,
294
+ Runtime : response .Runtime ,
295
+ Certification : response .Certification ,
296
+ Network : response .Network ,
297
+ Country : response .Country ,
298
+ Trailer : response .Trailer ,
299
+ Homepage : response .Homepage ,
300
+ Status : response .Status ,
301
+ Rating : response .Rating ,
302
+ Votes : response .Votes ,
303
+ CommentCount : response .CommentCount ,
304
+ Language : response .Language ,
305
+ AvailableTranslations : response .AvailableTranslations ,
306
+ Genres : response .Genres ,
307
+ AiredEpisodes : response .AiredEpisodes ,
308
+ }
309
+ }
310
+
232
311
func (p * Trakt ) getMovies (endpoint string , logic map [string ]interface {}, params map [string ]string ) (map [string ]config.MediaItem , error ) {
233
312
// set request params
234
313
reqParams := p .getRequestParams (params )
@@ -279,7 +358,7 @@ func (p *Trakt) getMovies(endpoint string, logic map[string]interface{}, params
279
358
// process response
280
359
for _ , item := range s {
281
360
// set movie item
282
- var movieItem * TraktMovie = p .translateTraktMovie (item )
361
+ var movieItem * TraktMovie = p .translateMovie (item )
283
362
if movieItem == nil {
284
363
p .log .Tracef ("Failed translating trakt movie: %#v" , item )
285
364
continue
@@ -377,3 +456,145 @@ func (p *Trakt) getMovies(endpoint string, logic map[string]interface{}, params
377
456
p .log .WithField ("accepted_items" , mediaItemsSize ).Info ("Retrieved media items" )
378
457
return mediaItems , nil
379
458
}
459
+
460
+ func (p * Trakt ) getShows (endpoint string , logic map [string ]interface {}, params map [string ]string ) (map [string ]config.MediaItem , error ) {
461
+ // set request params
462
+ reqParams := p .getRequestParams (params )
463
+
464
+ p .log .Tracef ("Request params: %+v" , params )
465
+
466
+ // parse logic params
467
+ limit := 0
468
+ limitReached := false
469
+
470
+ if v := getLogicParam (logic , "limit" ); v != nil {
471
+ limit = v .(int )
472
+ }
473
+
474
+ // fetch all page results
475
+ mediaItems := make (map [string ]config.MediaItem , 0 )
476
+ mediaItemsSize := 0
477
+ ignoredItemsSize := 0
478
+
479
+ page := 1
480
+
481
+ for {
482
+ // set params
483
+ reqParams ["page" ] = page
484
+
485
+ // send request
486
+ resp , err := web .GetResponse (web .GET , web .JoinURL (p .apiUrl , endpoint ), providerDefaultTimeout , p .apiHeaders ,
487
+ reqParams , & p .reqRetry , p .reqRatelimit )
488
+ if err != nil {
489
+ return nil , errors .WithMessage (err , "failed retrieving shows api response" )
490
+ }
491
+
492
+ // validate response
493
+ if resp .Response ().StatusCode != 200 {
494
+ _ = resp .Response ().Body .Close ()
495
+ return nil , fmt .Errorf ("failed retrieving valid shows api response: %s" , resp .Response ().Status )
496
+ }
497
+
498
+ // decode response
499
+ var s []TraktShowsResponse
500
+ if err := resp .ToJSON (& s ); err != nil {
501
+ _ = resp .Response ().Body .Close ()
502
+ return nil , errors .WithMessage (err , "failed decoding shows api response" )
503
+ }
504
+
505
+ _ = resp .Response ().Body .Close ()
506
+
507
+ // process response
508
+ for _ , item := range s {
509
+ // set movie item
510
+ var showItem * TraktShow = p .translateShow (item )
511
+ if showItem == nil {
512
+ p .log .Tracef ("Failed translating trakt show: %#v" , item )
513
+ continue
514
+ }
515
+
516
+ // skip this item?
517
+ if showItem .Ids .Slug == "" {
518
+ continue
519
+ } else if showItem .Runtime == 0 {
520
+ continue
521
+ } else if showItem .FirstAired .IsZero () {
522
+ continue
523
+ }
524
+
525
+ // does item already exist?
526
+ itemId := strconv .Itoa (showItem .Ids .Tvdb )
527
+ if _ , exists := mediaItems [itemId ]; exists {
528
+ continue
529
+ } else if _ , exists := mediaItems [showItem .Ids .Imdb ]; exists {
530
+ continue
531
+ }
532
+
533
+ // init media item
534
+ mediaItem := config.MediaItem {
535
+ Provider : "trakt" ,
536
+ TvdbId : itemId ,
537
+ TmdbId : strconv .Itoa (showItem .Ids .Tmdb ),
538
+ ImdbId : showItem .Ids .Imdb ,
539
+ Slug : showItem .Ids .Slug ,
540
+ Title : showItem .Title ,
541
+ Country : showItem .Country ,
542
+ Network : showItem .Network ,
543
+ Date : showItem .FirstAired ,
544
+ Year : showItem .FirstAired .Year (),
545
+ Runtime : showItem .Runtime ,
546
+ Genres : showItem .Genres ,
547
+ Languages : []string {showItem .Language },
548
+ }
549
+
550
+ // media item wanted?
551
+ if p .fnAcceptMediaItem != nil && ! p .fnAcceptMediaItem (& mediaItem ) {
552
+ p .log .Tracef ("Ignoring: %+v" , mediaItem )
553
+ ignoredItemsSize += 1
554
+ continue
555
+ } else {
556
+ p .log .Debugf ("Accepted: %+v" , mediaItem )
557
+ }
558
+
559
+ // set media item
560
+ mediaItems [itemId ] = mediaItem
561
+ mediaItemsSize += 1
562
+
563
+ // stop when limit reached
564
+ if limit > 0 && mediaItemsSize >= limit {
565
+ // limit was supplied via cli and we have reached this limit
566
+ limitReached = true
567
+ break
568
+ }
569
+ }
570
+
571
+ // parse pages information
572
+ totalPages := 0
573
+ tmp := resp .Response ().Header .Get ("X-Pagination-Page-Count" )
574
+ if v , err := strconv .Atoi (tmp ); err == nil {
575
+ totalPages = v
576
+ }
577
+
578
+ p .log .WithFields (logrus.Fields {
579
+ "page" : page ,
580
+ "pages" : totalPages ,
581
+ "accepted" : mediaItemsSize ,
582
+ "ignored" : ignoredItemsSize ,
583
+ }).Info ("Retrieved" )
584
+
585
+ // loop logic
586
+ if limitReached {
587
+ // the limit has been reached for accepted items
588
+ break
589
+ }
590
+
591
+ if page >= totalPages {
592
+ break
593
+ } else {
594
+ page += 1
595
+ }
596
+ }
597
+
598
+ p .log .WithField ("accepted_items" , mediaItemsSize ).Info ("Retrieved media items" )
599
+ return mediaItems , nil
600
+ }
0 commit comments