Skip to content

Commit

Permalink
v0.2.7 testing
Browse files Browse the repository at this point in the history
  • Loading branch information
Iliano101 committed Dec 24, 2024
2 parents 87fe2f0 + 4225832 commit 085251d
Show file tree
Hide file tree
Showing 8 changed files with 109 additions and 50 deletions.
4 changes: 2 additions & 2 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ android {
applicationId = "com.maxrave.simpmusic"
minSdk = 26
targetSdk = 35
versionCode = 23
versionName = "0.2.6"
versionCode = 24
versionName = "0.2.7"
vectorDrawables.useSupportLibrary = true

ksp {
Expand Down
1 change: 1 addition & 0 deletions fastlane/metadata/android/en-US/changelogs/24.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- Hot fix YouTube API issue
1 change: 1 addition & 0 deletions fastlane/metadata/android/vi-VN/changelogs/24.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- Sửa lỗi API YouTube
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ import com.maxrave.kotlinytmusicscraper.models.response.spotify.search.SpotifySe
import com.maxrave.kotlinytmusicscraper.models.response.toLikeStatus
import com.maxrave.kotlinytmusicscraper.models.simpmusic.GithubResponse
import com.maxrave.kotlinytmusicscraper.models.sponsorblock.SkipSegments
import com.maxrave.kotlinytmusicscraper.models.youtube.GhostResponse
import com.maxrave.kotlinytmusicscraper.models.youtube.Transcript
import com.maxrave.kotlinytmusicscraper.models.youtube.YouTubeInitialPage
import com.maxrave.kotlinytmusicscraper.pages.AlbumPage
Expand Down Expand Up @@ -1280,12 +1281,52 @@ class YouTube {
}.joinToString("")
val playerResponse =
try {
Log.w("Player Response", "Try Android")
ytMusic.player(if (cookie != null) ANDROID_MUSIC else IOS, videoId, playlistId, cpn).body<PlayerResponse>()
// Log.w("Player Response", "Try Android")
ytMusic.player(if (!cookie.isNullOrEmpty()) ANDROID_MUSIC else IOS, videoId, playlistId, cpn).body<PlayerResponse>().also {
if (it.playabilityStatus.status != "OK") throw Exception(it.playabilityStatus.status)
}
} catch (e: Exception) {
println("Player Response Error $e")
Log.w("Player Response", "Try IOS")
ytMusic.noLogInPlayer(videoId).body<PlayerResponse>()
// Log.w("Player Response", "Try IOS")
val ghostRequest = ytMusic.ghostRequest(videoId)
val cookie =
"PREF=hl=en&tz=UTC; SOCS=CAI; ${ghostRequest.headers
.getAll("set-cookie")
?.map {
it.split(";").first()
}?.filter {
it.lastOrNull() != '='
}?.joinToString("; ")}"
var response = ""
val ksoupHtmlParser =
KsoupHtmlParser(
object : KsoupHtmlHandler {
override fun onText(text: String) {
super.onText(text)
if (text.contains("var ytInitialPlayerResponse")) {
print("Text $text")
val temp = text.replace("var ytInitialPlayerResponse = ", "").split(";var").firstOrNull()
println("Scrape Temp $temp")
temp?.let {
response = it.trimIndent()
}
}
}
},
)
ksoupHtmlParser.write(ghostRequest.bodyAsText())
ksoupHtmlParser.end()
val json = Json { ignoreUnknownKeys = true }
val jsonData = json.decodeFromString<GhostResponse>(response)
val visitorData =
jsonData.responseContext.serviceTrackingParams
?.find { it.service == "GFEEDBACK" }
?.params
?.find { it.key == "visitor_data" }
?.value
println("Visitor Data $visitorData")
println("Cookie $cookie")
ytMusic.noLogInPlayer(videoId, cookie, visitorData).body<PlayerResponse>()
}
println("Player Response $playerResponse")
println("Thumbnails " + playerResponse.videoDetails?.thumbnail)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -377,32 +377,50 @@ class Ytmusic {
contentType(ContentType.Application.Json)
}

suspend fun noLogInPlayer(videoId: String) =
httpClient.post("https://www.youtube.com/youtubei/v1/player") {
accept(ContentType.Application.Json)
contentType(ContentType.Application.Json)
header("Host", "www.youtube.com")
header("Origin", "https://www.youtube.com")
header("Sec-Fetch-Mode", "navigate")
header(HttpHeaders.UserAgent, IOS.userAgent)
header(
"Set-Cookie",
"PREF=hl=en&tz=UTC; SOCS=CAI; GPS=1; YSC=ftafXBDpV4c; VISITOR_INFO1_LIVE=mk4zk5sq6VY; VISITOR_PRIVACY_METADATA=CgJWThIEGgAgRQ%3D%3D",
)
header("X-Goog-Visitor-Id", "CgttazR6azVzcTZWWSiMp6u7BjIKCgJWThIEGgAgRQ%3D%3D")
header("X-YouTube-Client-Name", IOS.clientName)
header("X-YouTube-Client-Version", IOS.clientVersion)
setBody(
PlayerBody(
context = IOS.toContext(locale, null),
playlistId = null,
cpn = null,
videoId = videoId,
playbackContext = PlayerBody.PlaybackContext(),
),
)
parameter("prettyPrint", false)
}
suspend fun ghostRequest(videoId: String) =
httpClient
.get("https://www.youtube.com/watch?v=$videoId&bpctr=9999999999&has_verified=1") {
headers {
header("Connection", "close")
header("Host", "www.youtube.com")
header("Cookie", "PREF=hl=en&tz=UTC; SOCS=CAI")
header("Sec-Fetch-Mode", "navigate")
header(
"User-Agent",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.71 Safari/537.36",
)
}
}

suspend fun noLogInPlayer(
videoId: String,
cookie: String,
visitorData: String?,
) = httpClient.post("https://www.youtube.com/youtubei/v1/player") {
accept(ContentType.Application.Json)
contentType(ContentType.Application.Json)
header("Host", "www.youtube.com")
header("Origin", "https://www.youtube.com")
header("Sec-Fetch-Mode", "navigate")
header(HttpHeaders.UserAgent, IOS.userAgent)
header(
"Set-Cookie",
cookie,
)
header("X-Goog-Visitor-Id", visitorData ?: this@Ytmusic.visitorData)
header("X-YouTube-Client-Name", IOS.clientName)
header("X-YouTube-Client-Version", IOS.clientVersion)
setBody(
PlayerBody(
context = IOS.toContext(locale, null),
playlistId = null,
cpn = null,
videoId = videoId,
playbackContext = PlayerBody.PlaybackContext(),
),
)
parameter("prettyPrint", false)
}

suspend fun player(
client: YouTubeClient,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import kotlinx.serialization.Serializable

@Serializable
data class ResponseContext(
val visitorData: String?,
val visitorData: String? = null,
val serviceTrackingParams: List<ServiceTrackingParam>?,
) {
@Serializable
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.maxrave.kotlinytmusicscraper.models.youtube

import com.maxrave.kotlinytmusicscraper.models.ResponseContext
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

Expand Down Expand Up @@ -37,4 +38,9 @@ data class YouTubeInitialPage(
}
}
}
}
}

@Serializable
data class GhostResponse(
val responseContext: ResponseContext,
)
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.maxrave.kotlinytmusicscraper.test

import com.google.gson.annotations.SerializedName
import com.maxrave.kotlinytmusicscraper.YouTube
import com.maxrave.kotlinytmusicscraper.Ytmusic
import com.maxrave.kotlinytmusicscraper.models.GridRenderer
import com.maxrave.kotlinytmusicscraper.models.MusicResponsiveListItemRenderer
Expand All @@ -10,11 +11,8 @@ import com.maxrave.kotlinytmusicscraper.models.SectionListRenderer
import com.maxrave.kotlinytmusicscraper.models.Thumbnail
import com.maxrave.kotlinytmusicscraper.models.YouTubeClient
import com.maxrave.kotlinytmusicscraper.models.YouTubeLocale
import com.maxrave.kotlinytmusicscraper.models.response.PlayerResponse
import io.ktor.client.call.body
import io.ktor.client.statement.bodyAsText
import kotlinx.coroutines.runBlocking
import java.util.Collections.addAll

fun main() {
runBlocking {
Expand All @@ -24,20 +22,14 @@ fun main() {

fun testPlayer() {
runBlocking {
Ytmusic()
YouTube()
.apply {}
.noLogInPlayer("Fwsl_XS4sYQ")
.body<PlayerResponse>()
.also {
println(it.playabilityStatus.status)
val listFormat = (it.streamingData?.formats?.toMutableList() ?: mutableListOf())
listFormat.addAll(it.streamingData?.adaptiveFormats ?: mutableListOf())
listFormat
.map {
it.itag to it.url
}.forEach { data ->
println(data)
}
.player(
"Fwsl_XS4sYQ",
).onSuccess {
println(it)
}.onFailure {
it.printStackTrace()
}
}
}
Expand Down

0 comments on commit 085251d

Please sign in to comment.