@@ -96,107 +96,111 @@ enum PlaylistParser {
9696 return header
9797 }
9898
99- // Try musicDetailHeaderRenderer (most common for playlists)
100- if let headerRenderer = headerDict [ " musicDetailHeaderRenderer " ] as? [ String : Any ] {
101- if let text = ParsingHelpers . extractTitle ( from: headerRenderer ) {
102- header. title = text
103- }
99+ // Try each header renderer type in order of preference
100+ applyDetailHeaderRenderer ( from : headerDict, to : & header )
101+ applyImmersiveHeaderRenderer ( from: headerDict , to : & header )
102+ applyVisualHeaderRenderer ( from : headerDict , to : & header)
103+ applyEditablePlaylistHeaderRenderer ( from : headerDict , to : & header )
104104
105- if let descData = headerRenderer [ " description " ] as? [ String : Any ] ,
106- let runs = descData [ " runs " ] as? [ [ String : Any ] ]
107- {
108- header. description = runs. compactMap { $0 [ " text " ] as? String } . joined ( )
109- }
105+ return header
106+ }
110107
111- let thumbnails = ParsingHelpers . extractThumbnails ( from : headerRenderer )
112- header . thumbnailURL = thumbnails . last . flatMap { URL ( string : $0 ) }
108+ private static func applyDetailHeaderRenderer ( from headerDict : [ String : Any ] , to header : inout HeaderData ) {
109+ guard let renderer = headerDict [ " musicDetailHeaderRenderer " ] as? [ String : Any ] else { return }
113110
114- if let subtitleData = headerRenderer [ " subtitle " ] as? [ String : Any ] ,
115- let runs = subtitleData [ " runs " ] as? [ [ String : Any ] ]
116- {
117- let texts = runs. compactMap { $0 [ " text " ] as? String }
118- header. author = texts. first
119- }
111+ if let text = ParsingHelpers . extractTitle ( from: renderer) {
112+ header. title = text
113+ }
120114
121- if let secondSubtitleData = headerRenderer [ " secondSubtitle " ] as? [ String : Any ] ,
122- let runs = secondSubtitleData [ " runs " ] as? [ [ String : Any ] ]
123- {
124- let texts = runs. compactMap { $0 [ " text " ] as? String }
125- header. duration = texts. joined ( )
126- }
115+ if let descData = renderer [ " description " ] as? [ String : Any ] ,
116+ let runs = descData [ " runs " ] as? [ [ String : Any ] ]
117+ {
118+ header. description = runs. compactMap { $0 [ " text " ] as? String } . joined ( )
127119 }
128120
129- // Try musicImmersiveHeaderRenderer (used by some albums)
130- if let immersiveHeader = headerDict [ " musicImmersiveHeaderRenderer " ] as? [ String : Any ] {
131- if header. title == " Unknown Playlist " ,
132- let text = ParsingHelpers . extractTitle ( from: immersiveHeader)
133- {
134- header. title = text
135- }
121+ let thumbnails = ParsingHelpers . extractThumbnails ( from: renderer)
122+ header. thumbnailURL = thumbnails. last. flatMap { URL ( string: $0) }
136123
137- // Always try to get thumbnail from immersive header if we don't have one
138- if header . thumbnailURL == nil {
139- let thumbnails = ParsingHelpers . extractThumbnails ( from : immersiveHeader )
140- header. thumbnailURL = thumbnails . last . flatMap { URL ( string : $0 ) }
141- }
124+ if let subtitleData = renderer [ " subtitle " ] as? [ String : Any ] ,
125+ let runs = subtitleData [ " runs " ] as? [ [ String : Any ] ]
126+ {
127+ header. author = runs . compactMap { $0 [ " text " ] as? String } . first
128+ }
142129
143- if header . description == nil ,
144- let descData = immersiveHeader [ " description " ] as? [ String : Any ] ,
145- let runs = descData [ " runs " ] as? [ [ String : Any ] ]
146- {
147- header . description = runs . compactMap { $0 [ " text " ] as? String } . joined ( )
148- }
130+ if let secondSubtitleData = renderer [ " secondSubtitle " ] as? [ String : Any ] ,
131+ let runs = secondSubtitleData [ " runs " ] as? [ [ String : Any ] ]
132+ {
133+ header . duration = runs . compactMap { $0 [ " text " ] as? String } . joined ( )
134+ }
135+ }
149136
150- // Try subtitle for author if not set
151- if header. author == nil ,
152- let subtitleData = immersiveHeader [ " subtitle " ] as? [ String : Any ] ,
153- let runs = subtitleData [ " runs " ] as? [ [ String : Any ] ]
154- {
155- let texts = runs. compactMap { $0 [ " text " ] as? String }
156- header. author = texts. first
157- }
137+ private static func applyImmersiveHeaderRenderer( from headerDict: [ String : Any ] , to header: inout HeaderData ) {
138+ guard let renderer = headerDict [ " musicImmersiveHeaderRenderer " ] as? [ String : Any ] else { return }
139+
140+ if header. title == " Unknown Playlist " ,
141+ let text = ParsingHelpers . extractTitle ( from: renderer)
142+ {
143+ header. title = text
158144 }
159145
160- // Try musicVisualHeaderRenderer (alternative format for some albums/artists)
161- if let visualHeader = headerDict [ " musicVisualHeaderRenderer " ] as? [ String : Any ] {
162- if header. title == " Unknown Playlist " ,
163- let text = ParsingHelpers . extractTitle ( from: visualHeader)
164- {
165- header. title = text
166- }
146+ if header. thumbnailURL == nil {
147+ let thumbnails = ParsingHelpers . extractThumbnails ( from: renderer)
148+ header. thumbnailURL = thumbnails. last. flatMap { URL ( string: $0) }
149+ }
167150
168- if header. thumbnailURL == nil {
169- let thumbnails = ParsingHelpers . extractThumbnails ( from: visualHeader)
170- header. thumbnailURL = thumbnails. last. flatMap { URL ( string: $0) }
171- }
151+ if header. description == nil ,
152+ let descData = renderer [ " description " ] as? [ String : Any ] ,
153+ let runs = descData [ " runs " ] as? [ [ String : Any ] ]
154+ {
155+ header. description = runs. compactMap { $0 [ " text " ] as? String } . joined ( )
172156 }
173157
174- // Try musicEditablePlaylistDetailHeaderRenderer (for user-editable playlists)
175- if let editableHeader = headerDict [ " musicEditablePlaylistDetailHeaderRenderer " ] as? [ String : Any ] ,
176- let nestedHeaderData = editableHeader [ " header " ] as? [ String : Any ] ,
177- let detailHeader = nestedHeaderData [ " musicDetailHeaderRenderer " ] as? [ String : Any ]
158+ if header. author == nil ,
159+ let subtitleData = renderer [ " subtitle " ] as? [ String : Any ] ,
160+ let runs = subtitleData [ " runs " ] as? [ [ String : Any ] ]
178161 {
179- if header. title == " Unknown Playlist " ,
180- let text = ParsingHelpers . extractTitle ( from: detailHeader)
181- {
182- header. title = text
183- }
162+ header. author = runs. compactMap { $0 [ " text " ] as? String } . first
163+ }
164+ }
184165
185- if header. thumbnailURL == nil {
186- let thumbnails = ParsingHelpers . extractThumbnails ( from: detailHeader)
187- header. thumbnailURL = thumbnails. last. flatMap { URL ( string: $0) }
188- }
166+ private static func applyVisualHeaderRenderer( from headerDict: [ String : Any ] , to header: inout HeaderData ) {
167+ guard let renderer = headerDict [ " musicVisualHeaderRenderer " ] as? [ String : Any ] else { return }
189168
190- if header. author == nil ,
191- let subtitleData = detailHeader [ " subtitle " ] as? [ String : Any ] ,
192- let runs = subtitleData [ " runs " ] as? [ [ String : Any ] ]
193- {
194- let texts = runs. compactMap { $0 [ " text " ] as? String }
195- header. author = texts. first
196- }
169+ if header. title == " Unknown Playlist " ,
170+ let text = ParsingHelpers . extractTitle ( from: renderer)
171+ {
172+ header. title = text
197173 }
198174
199- return header
175+ if header. thumbnailURL == nil {
176+ let thumbnails = ParsingHelpers . extractThumbnails ( from: renderer)
177+ header. thumbnailURL = thumbnails. last. flatMap { URL ( string: $0) }
178+ }
179+ }
180+
181+ private static func applyEditablePlaylistHeaderRenderer( from headerDict: [ String : Any ] , to header: inout HeaderData ) {
182+ guard let editableHeader = headerDict [ " musicEditablePlaylistDetailHeaderRenderer " ] as? [ String : Any ] ,
183+ let nestedHeaderData = editableHeader [ " header " ] as? [ String : Any ] ,
184+ let detailHeader = nestedHeaderData [ " musicDetailHeaderRenderer " ] as? [ String : Any ]
185+ else { return }
186+
187+ if header. title == " Unknown Playlist " ,
188+ let text = ParsingHelpers . extractTitle ( from: detailHeader)
189+ {
190+ header. title = text
191+ }
192+
193+ if header. thumbnailURL == nil {
194+ let thumbnails = ParsingHelpers . extractThumbnails ( from: detailHeader)
195+ header. thumbnailURL = thumbnails. last. flatMap { URL ( string: $0) }
196+ }
197+
198+ if header. author == nil ,
199+ let subtitleData = detailHeader [ " subtitle " ] as? [ String : Any ] ,
200+ let runs = subtitleData [ " runs " ] as? [ [ String : Any ] ]
201+ {
202+ header. author = runs. compactMap { $0 [ " text " ] as? String } . first
203+ }
200204 }
201205
202206 // MARK: - Track Parsing
0 commit comments