@@ -37,8 +37,14 @@ public final class PlaylistParser {
37
37
/// Remove season number and episode number "S--E--" from the name of media.
38
38
public static let removeSeriesInfoFromText = Options ( rawValue: 1 << 0 )
39
39
40
+ /// Extract id from the URL (usually last path component removing the extension)
41
+ public static let extractIdFromURL = Options ( rawValue: 1 << 1 )
42
+
40
43
/// All available options.
41
- public static let all : Options = [ . removeSeriesInfoFromText]
44
+ public static let all : Options = [
45
+ . removeSeriesInfoFromText,
46
+ . extractIdFromURL,
47
+ ]
42
48
}
43
49
44
50
/// Parser options.
@@ -77,7 +83,7 @@ public final class PlaylistParser {
77
83
78
84
if let metadataLine = lastMetadataLine, let url = lastURL {
79
85
do {
80
- let metadata = try self . parseMetadata ( ( lineNumber, metadataLine) )
86
+ let metadata = try self . parseMetadata ( line : lineNumber, rawString : metadataLine, url : url )
81
87
let kind = self . parseMediaKind ( url)
82
88
medias. append ( . init( metadata: metadata, kind: kind, url: url) )
83
89
lastMetadataLine = nil
@@ -127,7 +133,7 @@ public final class PlaylistParser {
127
133
128
134
if let metadataLine = lastMetadataLine, let url = lastURL {
129
135
do {
130
- let metadata = try self . parseMetadata ( ( lineNumber, metadataLine) )
136
+ let metadata = try self . parseMetadata ( line : lineNumber, rawString : metadataLine, url : url )
131
137
let kind = self . parseMediaKind ( url)
132
138
handler ( . init( metadata: metadata, kind: kind, url: url) )
133
139
lastMetadataLine = nil
@@ -216,23 +222,23 @@ public final class PlaylistParser {
216
222
217
223
internal typealias Show = ( name: String , se: ( s: Int , e: Int ) ? )
218
224
219
- internal func parseMetadata( _ input : ( line: Int , rawString: String ) ) throws -> Playlist . Media . Metadata {
220
- let duration = try extractDuration ( input )
221
- let attributes = parseAttributes ( input . rawString)
222
- let name = parseSeasonEpisode ( extractName ( input . rawString) ) . name
225
+ internal func parseMetadata( line: Int , rawString: String , url : URL ) throws -> Playlist . Media . Metadata {
226
+ let duration = try extractDuration ( line : line , rawString : rawString )
227
+ let attributes = parseAttributes ( rawString: rawString , url : url )
228
+ let name = parseSeasonEpisode ( extractName ( rawString) ) . name
223
229
return ( duration, attributes, name)
224
230
}
225
231
226
232
internal func isInfoLine( _ input: String ) -> Bool {
227
233
return input. starts ( with: " #EXTINF: " )
228
234
}
229
235
230
- internal func extractDuration( _ input : ( line: Int , rawString: String ) ) throws -> Int {
236
+ internal func extractDuration( line: Int , rawString: String ) throws -> Int {
231
237
guard
232
- let match = durationRegex. firstMatch ( in: input . rawString) ,
238
+ let match = durationRegex. firstMatch ( in: rawString) ,
233
239
let duration = Int ( match)
234
240
else {
235
- throw ParsingError . missingDuration ( input . line, input . rawString)
241
+ throw ParsingError . missingDuration ( line, rawString)
236
242
}
237
243
return duration
238
244
}
@@ -241,6 +247,10 @@ public final class PlaylistParser {
241
247
return nameRegex. firstMatch ( in: input) ?? " "
242
248
}
243
249
250
+ internal func extractId( _ input: URL ) -> String {
251
+ String ( input. lastPathComponent. split ( separator: " . " ) . first ?? " " )
252
+ }
253
+
244
254
internal func parseMediaKind( _ input: URL ) -> Playlist . Media . Kind {
245
255
let string = input. absoluteString
246
256
if mediaKindMSeriesRegex. numberOfMatches ( source: string) == 1 {
@@ -255,33 +265,35 @@ public final class PlaylistParser {
255
265
return . unknown
256
266
}
257
267
258
- internal func parseAttributes( _ input : String ) -> Playlist . Media . Attributes {
268
+ internal func parseAttributes( rawString : String , url : URL ) -> Playlist . Media . Attributes {
259
269
var attributes = Playlist . Media. Attributes ( )
260
- if let id = attributesIdRegex. firstMatch ( in: input) {
261
- attributes. id = id
270
+ let id = attributesIdRegex. firstMatch ( in: rawString) ?? " "
271
+ attributes. id = id
272
+ if id. isEmpty && options. contains ( . extractIdFromURL) {
273
+ attributes. id = extractId ( url)
262
274
}
263
- if let name = attributesNameRegex. firstMatch ( in: input ) {
275
+ if let name = attributesNameRegex. firstMatch ( in: rawString ) {
264
276
let show = parseSeasonEpisode ( name)
265
277
attributes. name = show. name
266
278
attributes. seasonNumber = show. se? . s
267
279
attributes. episodeNumber = show. se? . e
268
280
}
269
- if let country = attributesCountryRegex. firstMatch ( in: input ) {
281
+ if let country = attributesCountryRegex. firstMatch ( in: rawString ) {
270
282
attributes. country = country
271
283
}
272
- if let language = attributesLanguageRegex. firstMatch ( in: input ) {
284
+ if let language = attributesLanguageRegex. firstMatch ( in: rawString ) {
273
285
attributes. language = language
274
286
}
275
- if let logo = attributesLogoRegex. firstMatch ( in: input ) {
287
+ if let logo = attributesLogoRegex. firstMatch ( in: rawString ) {
276
288
attributes. logo = logo
277
289
}
278
- if let channelNumber = attributesChannelNumberRegex. firstMatch ( in: input ) {
290
+ if let channelNumber = attributesChannelNumberRegex. firstMatch ( in: rawString ) {
279
291
attributes. channelNumber = channelNumber
280
292
}
281
- if let shift = attributesShiftRegex. firstMatch ( in: input ) {
293
+ if let shift = attributesShiftRegex. firstMatch ( in: rawString ) {
282
294
attributes. shift = shift
283
295
}
284
- if let groupTitle = attributesGroupTitleRegex. firstMatch ( in: input ) {
296
+ if let groupTitle = attributesGroupTitleRegex. firstMatch ( in: rawString ) {
285
297
attributes. groupTitle = groupTitle
286
298
}
287
299
return attributes
0 commit comments