Skip to content

Commit 711af0d

Browse files
committed
Fixed home menu videos extraction.
1 parent 5530da9 commit 711af0d

File tree

3 files changed

+31
-2
lines changed

3 files changed

+31
-2
lines changed

Sources/YouTubeKit/BaseStructs/YTVideo.swift

+24
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,30 @@ public struct YTVideo: YTSearchResult, YouTubeVideo, Codable, Sendable {
7777
return video
7878
}
7979

80+
/// Give a `lockupViewModel` to decode.
81+
public static func decodeLockupJSON(json: JSON) -> YTVideo? {
82+
guard let videoId = json["contentId"].string, json["contentType"] == "LOCKUP_CONTENT_TYPE_VIDEO" else { return nil }
83+
84+
var video = YTVideo(videoId: videoId)
85+
86+
video.title = json["metadata"]["lockupMetadataViewModel"]["title"]["content"].string
87+
88+
if let channelJSON = json["metadata"]["lockupMetadataViewModel"]["metadata"]["contentMetadataViewModel"]["metadataRows"].array?.first(where: { $0["metadataParts"].array?.first?["text"]["commandRuns"].array?.first?["onTap"]["innertubeCommand"]["commandMetadata"]["webCommandMetadata"]["webPageType"].string == "WEB_PAGE_TYPE_CHANNEL" }), let channelId = channelJSON["metadataParts"].array?.first?["text"]["commandRuns"].array?.first?["onTap"]["innertubeCommand"]["browseEndpoint"]["browseId"].string {
89+
video.channel = YTLittleChannelInfos(channelId: channelId, name: channelJSON["metadataParts"].array?.first?["text"]["content"].string)
90+
}
91+
92+
let viewCountAndDateJSON = json["metadata"]["lockupMetadataViewModel"]["metadata"]["contentMetadataViewModel"]["metadataRows"].array?.first(where: { $0["metadataParts"].array?.first?["text"]["commandRuns"].array?.first?["onTap"]["innertubeCommand"]["commandMetadata"]["webCommandMetadata"]["webPageType"].string != "WEB_PAGE_TYPE_CHANNEL" })
93+
94+
video.viewCount = viewCountAndDateJSON?["metadataParts"].array?.first?["text"]["content"].string
95+
video.timePosted = viewCountAndDateJSON?["metadataParts"].array?.last?["text"]["content"].string
96+
97+
YTThumbnail.appendThumbnails(json: json["contentImage"]["thumbnailViewModel"], thumbnailList: &video.thumbnails)
98+
99+
video.timeLength = json["contentImage"]["thumbnailViewModel"]["overlays"].array?.first?["thumbnailOverlayBadgeViewModel"]["thumbnailBadges"].array?.first?["thumbnailBadgeViewModel"]["text"].string
100+
101+
return video
102+
}
103+
80104
public static let type: YTSearchResultType = .video
81105

82106
public var id: Int?

Sources/YouTubeKit/YouTubeResponseTypes/Home/HomeScreenResponse.swift

+4
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ public struct HomeScreenResponse: ContinuableResponse {
3737
for video in videosArray {
3838
if video["richItemRenderer"]["content"]["videoRenderer"]["videoId"].string != nil, let decodedVideo = YTVideo.decodeJSON(json: video["richItemRenderer"]["content"]["videoRenderer"]) {
3939
toReturn.results.append(decodedVideo)
40+
} else if video["richItemRenderer"]["content"]["lockupViewModel"].exists(), let video = YTVideo.decodeLockupJSON(json: video["richItemRenderer"]["content"]["lockupViewModel"]) {
41+
toReturn.results.append(video)
4042
} else if let continuationToken = video["continuationItemRenderer"]["continuationEndpoint"]["continuationCommand"]["token"].string {
4143
toReturn.continuationToken = continuationToken
4244
}
@@ -71,6 +73,8 @@ public struct HomeScreenResponse: ContinuableResponse {
7173
for video in continuationItemsArray {
7274
if video["richItemRenderer"]["content"]["videoRenderer"]["videoId"].string != nil, let decodedVideo = YTVideo.decodeJSON(json: video["richItemRenderer"]["content"]["videoRenderer"]) {
7375
toReturn.results.append(decodedVideo)
76+
} else if video["richItemRenderer"]["content"]["lockupViewModel"].exists(), let video = YTVideo.decodeLockupJSON(json: video["richItemRenderer"]["content"]["lockupViewModel"]) {
77+
toReturn.results.append(video)
7478
} else if let continuationToken = video["continuationItemRenderer"]["continuationEndpoint"]["continuationCommand"]["token"].string {
7579
toReturn.continuationToken = continuationToken
7680
}

Tests/YouTubeKitTests/YouTubeKitTests.swift

+3-2
Original file line numberDiff line numberDiff line change
@@ -797,9 +797,10 @@ final class YouTubeKitTests: XCTestCase {
797797
}
798798

799799
func testHomeResponse() async throws {
800+
YTM.cookies = self.cookies
800801
let TEST_NAME = "Test: testHomeResponse() -> "
801802

802-
var homeMenuResult = try await HomeScreenResponse.sendThrowingRequest(youtubeModel: YTM, data: [:])
803+
var homeMenuResult = try await HomeScreenResponse.sendThrowingRequest(youtubeModel: YTM, data: [:], useCookies: true)
803804
guard homeMenuResult.continuationToken != nil else {
804805
// Could fail because sometimes YouTube gives an empty page telling you to start browsing. We check this case here.
805806
if !(homeMenuResult.results.count == 0 && homeMenuResult.visitorData != nil) {
@@ -810,7 +811,7 @@ final class YouTubeKitTests: XCTestCase {
810811

811812
XCTAssertNotNil(homeMenuResult.visitorData, TEST_NAME + "Checking if homeMenuResult.visitorData is defined.")
812813

813-
let homeMenuContinuationResult = try await homeMenuResult.fetchContinuationThrowing(youtubeModel: YTM)
814+
let homeMenuContinuationResult = try await homeMenuResult.fetchContinuationThrowing(youtubeModel: YTM, useCookies: true)
814815

815816
guard homeMenuContinuationResult.continuationToken != nil else { XCTFail(TEST_NAME + "Checking if homeMenuContinuationResult.continuationToken is defined."); return }
816817

0 commit comments

Comments
 (0)