1
1
import { Inject , Injectable , Logger } from '@nestjs/common'
2
- import { ScrapedShowTorrent } from '@pct-org/scraper/providers/base'
2
+ import { ScrapedShowTorrents } from '@pct-org/scraper/providers/base'
3
3
import { InjectModel } from '@nestjs/mongoose'
4
- import { SeasonModel , Season } from '@pct-org/mongo-models'
5
- import { TraktSeason } from '@pct-org/services/trakt'
4
+ import { SeasonModel , Season , Show , Episode } from '@pct-org/mongo-models'
6
5
import { EpisodeHelperService } from '@pct-org/scraper/helpers/episode'
6
+ import { TYPE_SEASON } from '@pct-org/constants/item-types'
7
+ import { defaultEpisodeImages , defaultSeasonImages } from '@pct-org/constants/default-image-sizes'
8
+ import { TmdbService } from '@pct-org/services/tmdb'
9
+ import * as pMap from 'p-map'
7
10
8
11
@Injectable ( )
9
12
export class SeasonHelperService {
@@ -14,29 +17,120 @@ export class SeasonHelperService {
14
17
@Inject ( )
15
18
private readonly episodeHelperService : EpisodeHelperService
16
19
20
+ @Inject ( )
21
+ private readonly tmdbService : TmdbService
22
+
17
23
protected readonly logger = new Logger ( 'SeasonHelper' )
18
24
19
- public formatTraktSeasons ( traktSeasons : TraktSeason [ ] , torrents : ScrapedShowTorrent [ ] ) : Season [ ] {
20
- const formattedSeasons = [ ]
25
+ public formatTraktSeasons ( show : Show , torrents : ScrapedShowTorrents ) : Season [ ] {
26
+ const formattedSeasons : Season [ ] = [ ]
27
+ let traktSeasons = show . _traktSeasons
21
28
let seasonNumbers : any [ ] = Object . keys ( torrents )
22
29
23
30
// If we don't have any episodes for specials then also remove it from trakt
24
31
if ( ! seasonNumbers . includes ( '0' ) && ! seasonNumbers . includes ( 0 ) ) {
25
32
traktSeasons = traktSeasons . filter ( ( traktSeason ) => traktSeason . number !== 0 )
26
33
}
27
34
28
- // TODO:: Format the trakt seasons here
35
+ traktSeasons . forEach ( ( traktSeason ) => {
36
+ const formattedEpisodes = traktSeason . episodes . map ( ( traktEpisode ) => (
37
+ this . episodeHelperService . formatTraktEpisode (
38
+ show ,
39
+ traktEpisode ,
40
+ torrents ?. [ traktEpisode . season ] ?. [ traktEpisode . number ] ?? [ ]
41
+ )
42
+ ) )
43
+
44
+ // Remove it from the episodes seasons
45
+ seasonNumbers = seasonNumbers . filter ( ( season ) => parseInt ( season , 10 ) !== traktSeason . number )
46
+
47
+ let seasonFirstAired = Number ( new Date ( traktSeason ?. first_aired ) ) ?? 0
48
+
49
+ // If it's null then use the one from the first episode
50
+ if ( seasonFirstAired === 0 && formattedEpisodes . length > 0 ) {
51
+ const firstEpisode = formattedEpisodes [ 0 ]
29
52
30
- return [ ]
53
+ seasonFirstAired = firstEpisode . firstAired
54
+ }
55
+
56
+ formattedSeasons . push ( {
57
+ _id : `${ show . _id } -${ traktSeason . number } ` ,
58
+ tmdbId : traktSeason . ids . tmdb ,
59
+ showImdbId : show . _id ,
60
+
61
+ firstAired : seasonFirstAired ,
62
+ number : traktSeason . number ,
63
+ synopsis : null ,
64
+ title : traktSeason . title ,
65
+ type : TYPE_SEASON ,
66
+ images : defaultSeasonImages ,
67
+ createdAt : Number ( new Date ( ) ) ,
68
+ updatedAt : Number ( new Date ( ) ) ,
69
+
70
+ episodes : this . sortItems ( formattedEpisodes ) as Episode [ ] ,
71
+
72
+ _traktSeason : true
73
+ } )
74
+ } )
75
+
76
+ // If we still have some seasons left add them with what we can
77
+ if ( seasonNumbers . length > 0 ) {
78
+ // TODO:: Maybe check the titles and check if they match the
79
+ // name of the show then _traktSeason can be true
80
+ // Also rename trakt season then to a better name
81
+ seasonNumbers . forEach ( ( seasonNr ) => {
82
+ const formattedEpisodes : Episode [ ] = [ ]
83
+
84
+ Object . keys ( torrents [ seasonNr ] ) . map ( ( episodeNr ) => {
85
+ formattedEpisodes . push ( this . episodeHelperService . formatUnknownEpisode (
86
+ show ,
87
+ parseInt ( seasonNr , 10 ) ,
88
+ parseInt ( episodeNr , 10 ) ,
89
+ torrents [ seasonNr ] [ episodeNr ]
90
+ ) )
91
+ } )
92
+
93
+ formattedSeasons . push ( {
94
+ _id : `${ show . _id } -${ seasonNr } ` ,
95
+ tmdbId : null ,
96
+ showImdbId : show . _id ,
97
+
98
+ firstAired : Number ( new Date ( ) ) ,
99
+ number : parseInt ( seasonNr , 10 ) ,
100
+ synopsis : null ,
101
+ title : `Season ${ seasonNr } ` ,
102
+ type : TYPE_SEASON ,
103
+ images : defaultSeasonImages ,
104
+ createdAt : Number ( new Date ( ) ) ,
105
+ updatedAt : Number ( new Date ( ) ) ,
106
+
107
+ episodes : this . sortItems ( formattedEpisodes ) as Episode [ ] ,
108
+
109
+ _traktSeason : false
110
+ } )
111
+ } )
112
+ }
113
+
114
+ return this . sortItems ( formattedSeasons ) as Season [ ]
31
115
}
32
116
33
- public async enhanceSeasons ( seasons : Season [ ] ) : Promise < Season [ ] > {
34
- // TODO:: Enhance the seasons here
35
- return seasons
117
+ public async enhanceSeasons ( show : Show , seasons : Season [ ] ) : Promise < Season [ ] > {
118
+ const enhancedSeasons : ( boolean | Season ) [ ] = await pMap (
119
+ seasons ,
120
+ ( season ) => {
121
+ return this . enhanceSeason ( show , season )
122
+ } ,
123
+ {
124
+ concurrency : 1
125
+ }
126
+ )
127
+
128
+ // Remove all the falsy seasons
129
+ return enhancedSeasons . filter ( Boolean ) as Season [ ]
36
130
}
37
131
38
132
public async addSeasonsToDatabase ( seasons : Season [ ] ) : Promise < void > {
39
- await Promise . all ( seasons . map ( this . addSeasonToDatabase ) )
133
+ await Promise . all ( seasons . map ( ( season ) => this . addSeasonToDatabase ( season ) ) )
40
134
}
41
135
42
136
public async updateSeasonsInDatabase ( seasons : Season [ ] ) : Promise < void > {
@@ -71,4 +165,72 @@ export class SeasonHelperService {
71
165
await this . episodeHelperService . updateEpisodesInDatabase ( episodes )
72
166
}
73
167
168
+ private async enhanceSeason ( show : Show , season : Season ) : Promise < Season | boolean > {
169
+ try {
170
+ const tmdbSeason = await this . tmdbService . getSeasonInfo ( show , season )
171
+
172
+ // Also enhance all the episodes
173
+ season . episodes . map ( ( episode ) => {
174
+ const tmdbEpisode = tmdbSeason . episodes . find ( ( tmdbEpisode ) => (
175
+ tmdbEpisode . episodeNumber === episode . number
176
+ ) )
177
+
178
+ // If we have a matching episode then enhance it
179
+ if ( tmdbEpisode ) {
180
+ return {
181
+ ...episode ,
182
+
183
+ title : episode . title !== `Episode ${ episode . number } `
184
+ ? episode . title
185
+ : tmdbEpisode . name ,
186
+ synopsis : episode . synopsis || tmdbEpisode . overview ,
187
+ firstAired : tmdbEpisode . airDate && episode . firstAired === 0
188
+ ? new Date ( tmdbEpisode . airDate ) . getTime ( )
189
+ : episode . firstAired ,
190
+ images : {
191
+ ...episode . images ,
192
+
193
+ poster : tmdbEpisode . stillPath
194
+ ? this . tmdbService . formatImage ( tmdbEpisode . stillPath )
195
+ : defaultEpisodeImages . poster
196
+ }
197
+ }
198
+ }
199
+
200
+ return episode
201
+ } )
202
+
203
+ return {
204
+ ...season ,
205
+
206
+ title : season . title !== `Season ${ season . number } `
207
+ ? season . title
208
+ : tmdbSeason . name ,
209
+ synopsis : season . synopsis || tmdbSeason . overview ,
210
+ firstAired : tmdbSeason . airDate && season . firstAired === 0
211
+ ? new Date ( tmdbSeason . airDate ) . getTime ( )
212
+ : season . firstAired ,
213
+ images : {
214
+ ...season . images ,
215
+
216
+ poster : tmdbSeason . posterPath
217
+ ? this . tmdbService . formatImage ( tmdbSeason . posterPath )
218
+ : defaultSeasonImages . poster
219
+ }
220
+ }
221
+ } catch ( err ) {
222
+ // If it was not a trakt season don't return it at all
223
+ if ( ! season . _traktSeason ) {
224
+ return false
225
+ }
226
+ }
227
+
228
+ // We ware not able to enhance it, return trakt season
229
+ return season
230
+ }
231
+
232
+ private sortItems ( items : Episode [ ] | Season [ ] ) : Episode [ ] | Season [ ] {
233
+ return items . sort ( ( a , b ) => a . number - b . number )
234
+ }
235
+
74
236
}
0 commit comments