diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 3c12652a..b228fea0 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -165,7 +165,7 @@ dependencies { androidTestImplementation("androidx.test:core") //implementation("io.karn:khttp-android:0.1.2") //okhttp instead -// implementation("org.jsoup:jsoup:1.13.1") + // implementation("org.jsoup:jsoup:1.13.1") implementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.13.1") implementation("androidx.preference:preference-ktx:1.2.0") @@ -220,8 +220,8 @@ dependencies { implementation("androidx.work:work-runtime-ktx:2.8.1") // Networking -// implementation("com.squareup.okhttp3:okhttp:4.9.2") -// implementation("com.squareup.okhttp3:okhttp-dnsoverhttps:4.9.1") + // implementation("com.squareup.okhttp3:okhttp:4.9.2") + // implementation("com.squareup.okhttp3:okhttp-dnsoverhttps:4.9.1") implementation("com.github.Blatzar:NiceHttp:0.4.3") // To fix SSL fuckery on android 9 implementation("org.conscrypt:conscrypt-android:2.2.1") @@ -243,11 +243,9 @@ dependencies { // used for subtitle decoding https://github.com/albfernandez/juniversalchardet implementation("com.github.albfernandez:juniversalchardet:2.4.0") - // slow af yt - //implementation("com.github.HaarigerHarald:android-youtubeExtractor:master-SNAPSHOT") - // newpipe yt taken from https://github.com/TeamNewPipe/NewPipe/blob/dev/app/build.gradle#L204 - implementation("com.github.TeamNewPipe:NewPipeExtractor:8495ad619e") + // this should be updated frequently to avoid trailer fu*kery + implementation("com.github.TeamNewPipe:NewPipeExtractor:1f08d28") coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:1.1.6") // Library/extensions searching with Levenshtein distance diff --git a/app/src/main/java/com/lagradost/cloudstream3/syncproviders/providers/SimklApi.kt b/app/src/main/java/com/lagradost/cloudstream3/syncproviders/providers/SimklApi.kt index 64cebfc6..b4a9d789 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/syncproviders/providers/SimklApi.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/syncproviders/providers/SimklApi.kt @@ -60,8 +60,8 @@ class SimklApi(index: Int) : AccountManager(index), SyncAPI { private var lastScoreTime = -1L companion object { - private const val clientId = BuildConfig.SIMKL_CLIENT_ID - private const val clientSecret = BuildConfig.SIMKL_CLIENT_SECRET + private const val clientId: String = BuildConfig.SIMKL_CLIENT_ID + private const val clientSecret: String = BuildConfig.SIMKL_CLIENT_SECRET private var lastLoginState = "" const val SIMKL_TOKEN_KEY: String = "simkl_token" @@ -498,6 +498,9 @@ class SimklApi(index: Int) : AccountManager(index), SyncAPI { val episodes: Array?, override var isFavorite: Boolean? = null, override var maxEpisodes: Int? = null, + /** Save seen episodes separately to know the change from old to new. + * Required to remove seen episodes if count decreases */ + val oldEpisodes: Int, ) : SyncAPI.AbstractSyncStatus() override suspend fun getStatus(id: String): SyncAPI.AbstractSyncStatus? { @@ -521,7 +524,8 @@ class SimklApi(index: Int) : AccountManager(index), SyncAPI { score = foundItem.user_rating, watchedEpisodes = foundItem.watched_episodes_count, maxEpisodes = foundItem.total_episodes_count, - episodes = episodes + episodes = episodes, + oldEpisodes = foundItem.watched_episodes_count ?: 0, ) } else { return if (searchResult != null) { @@ -530,7 +534,8 @@ class SimklApi(index: Int) : AccountManager(index), SyncAPI { score = 0, watchedEpisodes = 0, maxEpisodes = if (searchResult.type == "movie") 0 else null, - episodes = episodes + episodes = episodes, + oldEpisodes = 0, ) } else { null @@ -604,32 +609,46 @@ class SimklApi(index: Int) : AccountManager(index), SyncAPI { SimklListStatusType.ReWatching.value ).contains(status.status) ) { - val cutEpisodes = simklStatus.episodes.take(watchedEpisodes) - - val (seasons, episodes) = if (cutEpisodes.any { it.season != null }) { - EpisodeMetadata.convertToSeasons(cutEpisodes) to null - } else { - null to EpisodeMetadata.convertToEpisodes(cutEpisodes) + suspend fun postEpisodes( + url: String, + rawEpisodes: List + ): Boolean { + val (seasons, episodes) = if (rawEpisodes.any { it.season != null }) { + EpisodeMetadata.convertToSeasons(rawEpisodes) to null + } else { + null to EpisodeMetadata.convertToEpisodes(rawEpisodes) + } + debugPrint { "Synced history using $url: seasons=${seasons?.toList()}, episodes=${episodes?.toList()}" } + return app.post( + url, + json = StatusRequest( + shows = listOf( + HistoryMediaObject( + null, + null, + MediaObject.Ids.fromMap(parsedId), + seasons, + episodes + ) + ), + movies = emptyList() + ), + interceptor = interceptor + ).isSuccessful } - debugPrint { "Synced history for ${status.watchedEpisodes} given size of ${simklStatus.episodes.size}: seasons=${seasons?.toList()}, episodes=${episodes?.toList()}" } - val episodeResponse = app.post( - "$mainUrl/sync/history", - json = StatusRequest( - shows = listOf( - HistoryMediaObject( - null, - null, - MediaObject.Ids.fromMap(parsedId), - seasons, - episodes - ) - ), - movies = emptyList() - ), - interceptor = interceptor - ) - episodeResponse.isSuccessful + // If episodes decrease: remove all episodes beyond watched episodes. + val removeResponse = if (simklStatus.oldEpisodes > watchedEpisodes) { + val removeEpisodes = simklStatus.episodes + .drop(watchedEpisodes) + postEpisodes("$mainUrl/sync/history/remove", removeEpisodes) + } else { + true + } + val cutEpisodes = simklStatus.episodes.take(watchedEpisodes) + val addResponse = postEpisodes("$mainUrl/sync/history/", cutEpisodes) + + removeResponse && addResponse } else true val newStatus = diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/result/ResultViewModel2.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/result/ResultViewModel2.kt index 011d133d..2fe3b012 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/result/ResultViewModel2.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/result/ResultViewModel2.kt @@ -1707,7 +1707,7 @@ class ResultViewModel2 : ViewModel() { else -> { if (response.type.isLiveStream()) R.string.play_livestream_button - else if (response.type.isMovieType()) // this wont break compatibility as you only need to override isMovieType + else if (response.isMovie()) // this wont break compatibility as you only need to override isMovieType R.string.play_movie_button else null } @@ -2340,4 +2340,4 @@ class ResultViewModel2 : ViewModel() { } } } -} \ No newline at end of file +}