Handle if video redirects to explore page instead of loading it

This commit is contained in:
Gergely Hegedus 2025-11-02 22:37:00 +02:00
parent af0ead9396
commit 9aa54ab28d
4 changed files with 49 additions and 2 deletions

View file

@ -10,12 +10,17 @@ class ThrowIfVideoIsDeletedResponse {
"statusMsg\":\"[^\"]*status_audit_not_pass" "statusMsg\":\"[^\"]*status_audit_not_pass"
) )
private val redirectedToExplorePage = "\"seo.abtest\":{\"canonical\":\"https:\\u002F\\u002Fwww.tiktok.com\\u002Fexplore\""
@Throws(VideoDeletedException::class) @Throws(VideoDeletedException::class)
fun invoke(html: String) { fun invoke(html: String) {
potentialIssues.forEach { potentialIssues.forEach {
if (html.contains(it.toRegex())) { if (html.contains(it.toRegex())) {
throw VideoDeletedException(html = html) throw VideoDeletedException(html = html)
} }
if (html.contains(redirectedToExplorePage)) {
throw VideoDeletedException(html = html)
}
} }
} }
} }

View file

@ -273,9 +273,22 @@ class TikTokDownloadRemoteSourceTest {
} }
} }
@Test
fun GIVEN_deleted_video_response_v2_THEN_proper_Exception_is_Returned() {
Assertions.assertThrows(VideoDeletedException::class.java) {
runBlocking<Unit> {
val deletedResponse = readResourceFileDeletedV2UrlResponse()
mockWebServer.enqueue(MockResponse().setResponseCode(200).setBody(deletedResponse))
sut.getVideo(VideoInPending("", TEST_URL))
}
}
}
companion object { companion object {
private const val SHORTENED_URL_RESPONSE = "response/shortened_url_response.html" private const val SHORTENED_URL_RESPONSE = "response/shortened_url_response.html"
private const val DELETED_V1_URL_RESPONSE = "response/video_deleted_v1.html" private const val DELETED_V1_URL_RESPONSE = "response/video_deleted_v1.html"
private const val DELETED_V2_URL_RESPONSE = "response/video_deleted_v2.html"
private const val CAPTCHA_REQUIRED_RESPONSE_ONE = "response/captcha_required_one.html" private const val CAPTCHA_REQUIRED_RESPONSE_ONE = "response/captcha_required_one.html"
private const val CAPTCHA_REQUIRED_RESPONSE_TWO = "response/captcha_required_two.html" private const val CAPTCHA_REQUIRED_RESPONSE_TWO = "response/captcha_required_two.html"
private const val MAIN_PAGE_VARIANT_1_RESPONSE = "response/main_page_v1.html" private const val MAIN_PAGE_VARIANT_1_RESPONSE = "response/main_page_v1.html"
@ -314,6 +327,9 @@ class TikTokDownloadRemoteSourceTest {
private fun Any.readResourceFileDeletedV1UrlResponse() = private fun Any.readResourceFileDeletedV1UrlResponse() =
readResourceFile(DELETED_V1_URL_RESPONSE) readResourceFile(DELETED_V1_URL_RESPONSE)
private fun Any.readResourceFileDeletedV2UrlResponse() =
readResourceFile(DELETED_V2_URL_RESPONSE)
@JvmStatic @JvmStatic
private fun captchaResponses() = Stream.of( private fun captchaResponses() = Stream.of(
Arguments.of(CAPTCHA_REQUIRED_RESPONSE_ONE, readCaptchaOneResponse()), Arguments.of(CAPTCHA_REQUIRED_RESPONSE_ONE, readCaptchaOneResponse()),

View file

@ -69,8 +69,11 @@ class TikTokDownloadRemoteSourceUpToDateTest {
@Test @Test
fun GIVEN_private_WHEN_downloading_THEN_proper_exception_is_thrown() { fun GIVEN_private_WHEN_downloading_THEN_proper_exception_is_thrown() {
val parameter = VideoInPending("123", PRIVATE_VIDEO_URL) val parameter = VideoInPending("123", PRIVATE_VIDEO_URL)
Assertions.assertThrows(VideoPrivateException::class.java) { Assertions.assertThrows(VideoDeletedException::class.java) {
runBlocking { sut.getVideo(parameter) } // DELETED response is also accepted: sometimes cant differentiate
Assertions.assertThrows(VideoPrivateException::class.java) {
runBlocking { sut.getVideo(parameter) }
}
} }
} }

File diff suppressed because one or more lines are too long