From 6df3ef14f66dd3cfc038ee922c563684eb84ce4e Mon Sep 17 00:00:00 2001
From: CranberrySoup <142951702+CranberrySoup@users.noreply.github.com>
Date: Tue, 16 Apr 2024 21:07:28 +0000
Subject: [PATCH 1/5] First steps for multiplatform API (#1003)
* First steps for multiplatform api
* Buildconfig testing
* Fix publishing and classes.jar
* Update build.gradle.kts
---
.idea/gradle.xml | 7 +-
app/build.gradle.kts | 34 ++++++++--
.../com/lagradost/cloudstream3/MainAPI.kt | 2 -
.../lagradost/cloudstream3/mvvm/Lifecycle.kt | 16 +++++
build.gradle.kts | 8 ++-
library/build.gradle.kts | 68 +++++++++++++++++++
library/src/androidMain/AndroidManifest.xml | 2 +
.../kotlin/com/lagradost/api/Log.kt | 21 ++++++
.../kotlin/com/lagradost/api/Log.kt | 8 +++
.../com/lagradost/cloudstream3/MainApi.kt | 3 +
.../cloudstream3/mvvm/ArchComponentExt.kt | 35 +++-------
.../jvmMain/kotlin/com/lagradost/api/Log.kt | 19 ++++++
settings.gradle.kts | 3 +-
13 files changed, 185 insertions(+), 41 deletions(-)
create mode 100644 app/src/main/java/com/lagradost/cloudstream3/mvvm/Lifecycle.kt
create mode 100644 library/build.gradle.kts
create mode 100644 library/src/androidMain/AndroidManifest.xml
create mode 100644 library/src/androidMain/kotlin/com/lagradost/api/Log.kt
create mode 100644 library/src/commonMain/kotlin/com/lagradost/api/Log.kt
create mode 100644 library/src/commonMain/kotlin/com/lagradost/cloudstream3/MainApi.kt
rename {app/src/main/java => library/src/commonMain/kotlin}/com/lagradost/cloudstream3/mvvm/ArchComponentExt.kt (86%)
create mode 100644 library/src/jvmMain/kotlin/com/lagradost/api/Log.kt
diff --git a/.idea/gradle.xml b/.idea/gradle.xml
index c5c0ff3b..d7c08c9c 100644
--- a/.idea/gradle.xml
+++ b/.idea/gradle.xml
@@ -4,17 +4,16 @@
diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index 02946e85..e07162d7 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -1,5 +1,6 @@
import com.android.build.gradle.internal.cxx.configure.gradleLocalProperties
import org.jetbrains.dokka.gradle.DokkaTask
+import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.util.archivesName
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
import java.io.ByteArrayOutputStream
import java.net.URL
@@ -13,6 +14,7 @@ plugins {
val tmpFilePath = System.getProperty("user.home") + "/work/_temp/keystore/"
val prereleaseStoreFile: File? = File(tmpFilePath).listFiles()?.first()
+var isLibraryDebug = false
fun String.execute() = ByteArrayOutputStream().use { baot ->
if (project.exec {
@@ -103,6 +105,7 @@ android {
)
}
debug {
+ isLibraryDebug = true
isDebuggable = true
applicationIdSuffix = ".debug"
proguardFiles(
@@ -232,18 +235,37 @@ dependencies {
implementation("androidx.work:work-runtime:2.9.0")
implementation("androidx.work:work-runtime-ktx:2.9.0")
implementation("com.github.Blatzar:NiceHttp:0.4.11") // HTTP Lib
+
+ implementation(project(":library") {
+ this.extra.set("isDebug", isLibraryDebug)
+ })
}
-tasks.register("androidSourcesJar", Jar::class) {
+tasks.register("androidSourcesJar") {
archiveClassifier.set("sources")
from(android.sourceSets.getByName("main").java.srcDirs) // Full Sources
}
-// For GradLew Plugin
-tasks.register("makeJar", Copy::class) {
- from("build/intermediates/compile_app_classes_jar/prereleaseDebug")
- into("build")
- include("classes.jar")
+tasks.register("copyJar") {
+ from(
+ "build/intermediates/compile_app_classes_jar/prereleaseDebug",
+ "../library/build/libs"
+ )
+ into("build/app-classes")
+ include("classes.jar", "library-jvm*.jar")
+ // Remove the version
+ rename("library-jvm.*.jar", "library-jvm.jar")
+}
+
+// Merge the app classes and the library classes into classes.jar
+tasks.register("makeJar") {
+ dependsOn(tasks.getByName("copyJar"))
+ from(
+ zipTree("build/app-classes/classes.jar"),
+ zipTree("build/app-classes/library-jvm.jar")
+ )
+ destinationDirectory.set(layout.buildDirectory)
+ archivesName = "classes"
}
tasks.withType {
diff --git a/app/src/main/java/com/lagradost/cloudstream3/MainAPI.kt b/app/src/main/java/com/lagradost/cloudstream3/MainAPI.kt
index ecbdcbbc..7b1b5775 100644
--- a/app/src/main/java/com/lagradost/cloudstream3/MainAPI.kt
+++ b/app/src/main/java/com/lagradost/cloudstream3/MainAPI.kt
@@ -743,8 +743,6 @@ fun base64Encode(array: ByteArray): String {
}
}
-class ErrorLoadingException(message: String? = null) : Exception(message)
-
fun MainAPI.fixUrlNull(url: String?): String? {
if (url.isNullOrEmpty()) {
return null
diff --git a/app/src/main/java/com/lagradost/cloudstream3/mvvm/Lifecycle.kt b/app/src/main/java/com/lagradost/cloudstream3/mvvm/Lifecycle.kt
new file mode 100644
index 00000000..3df5197c
--- /dev/null
+++ b/app/src/main/java/com/lagradost/cloudstream3/mvvm/Lifecycle.kt
@@ -0,0 +1,16 @@
+package com.lagradost.cloudstream3.mvvm
+
+import androidx.lifecycle.LifecycleOwner
+import androidx.lifecycle.LiveData
+
+/** NOTE: Only one observer at a time per value */
+fun LifecycleOwner.observe(liveData: LiveData, action: (t: T) -> Unit) {
+ liveData.removeObservers(this)
+ liveData.observe(this) { it?.let { t -> action(t) } }
+}
+
+/** NOTE: Only one observer at a time per value */
+fun LifecycleOwner.observeNullable(liveData: LiveData, action: (t: T) -> Unit) {
+ liveData.removeObservers(this)
+ liveData.observe(this) { action(it) }
+}
diff --git a/build.gradle.kts b/build.gradle.kts
index 801a3c0f..ab1918fe 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -8,6 +8,8 @@ buildscript {
classpath("com.android.tools.build:gradle:8.2.2")
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.9.22")
classpath("org.jetbrains.dokka:dokka-gradle-plugin:1.9.10")
+ // Universal build config
+ classpath("com.codingfeline.buildkonfig:buildkonfig-gradle-plugin:0.15.1")
}
}
@@ -22,6 +24,6 @@ plugins {
id("com.google.devtools.ksp") version "1.9.22-1.0.17" apply false
}
-tasks.register("clean") {
- delete(rootProject.layout.buildDirectory)
-}
+//tasks.register("clean") {
+// delete(rootProject.layout.buildDirectory)
+//}
diff --git a/library/build.gradle.kts b/library/build.gradle.kts
new file mode 100644
index 00000000..42a8c943
--- /dev/null
+++ b/library/build.gradle.kts
@@ -0,0 +1,68 @@
+import com.codingfeline.buildkonfig.compiler.FieldSpec
+
+plugins {
+ kotlin("multiplatform")
+ id("maven-publish")
+ id("com.android.library")
+ id("com.codingfeline.buildkonfig")
+}
+
+kotlin {
+ version = "1.0.0"
+ androidTarget()
+ jvm()
+
+ sourceSets {
+ commonMain.dependencies {
+ implementation("com.github.Blatzar:NiceHttp:0.4.11") // HTTP Lib
+ implementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.13.1") /* JSON Parser
+ ^ Don't Bump Jackson above 2.13.1 , Crashes on Android TV's and FireSticks that have Min API
+ Level 25 or Less. */
+ implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.0")
+ }
+ }
+}
+
+repositories {
+ mavenLocal()
+ maven("https://jitpack.io")
+}
+
+tasks.withType {
+ kotlinOptions.jvmTarget = JavaVersion.VERSION_1_8.toString()
+}
+
+buildkonfig {
+ packageName = "com.lagradost.api"
+ exposeObjectWithName = "BuildConfig"
+
+ defaultConfigs {
+ val isDebug = kotlin.runCatching { extra.get("isDebug") }.getOrNull() == true
+ buildConfigField(FieldSpec.Type.BOOLEAN, "DEBUG", isDebug.toString())
+ }
+}
+
+android {
+ compileSdk = 34
+ sourceSets["main"].manifest.srcFile("src/androidMain/AndroidManifest.xml")
+
+ defaultConfig {
+ minSdk = 21
+ targetSdk = 33
+ }
+
+ // If this is the same com.lagradost.cloudstream3.R stops working
+ namespace = "com.lagradost.api"
+
+ compileOptions {
+ sourceCompatibility = JavaVersion.VERSION_1_8
+ targetCompatibility = JavaVersion.VERSION_1_8
+ }
+}
+publishing {
+ publications {
+ withType {
+ groupId = "com.lagradost.api"
+ }
+ }
+}
\ No newline at end of file
diff --git a/library/src/androidMain/AndroidManifest.xml b/library/src/androidMain/AndroidManifest.xml
new file mode 100644
index 00000000..568741e5
--- /dev/null
+++ b/library/src/androidMain/AndroidManifest.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/library/src/androidMain/kotlin/com/lagradost/api/Log.kt b/library/src/androidMain/kotlin/com/lagradost/api/Log.kt
new file mode 100644
index 00000000..12524411
--- /dev/null
+++ b/library/src/androidMain/kotlin/com/lagradost/api/Log.kt
@@ -0,0 +1,21 @@
+package com.lagradost.api
+
+import android.util.Log
+
+actual object Log {
+ actual fun d(tag: String, message: String) {
+ Log.d(tag, message)
+ }
+
+ actual fun i(tag: String, message: String) {
+ Log.i(tag, message)
+ }
+
+ actual fun w(tag: String, message: String) {
+ Log.w(tag, message)
+ }
+
+ actual fun e(tag: String, message: String) {
+ Log.e(tag, message)
+ }
+}
\ No newline at end of file
diff --git a/library/src/commonMain/kotlin/com/lagradost/api/Log.kt b/library/src/commonMain/kotlin/com/lagradost/api/Log.kt
new file mode 100644
index 00000000..4b8e6329
--- /dev/null
+++ b/library/src/commonMain/kotlin/com/lagradost/api/Log.kt
@@ -0,0 +1,8 @@
+package com.lagradost.api
+
+expect object Log {
+ fun d(tag: String, message: String)
+ fun i(tag: String, message: String)
+ fun w(tag: String, message: String)
+ fun e(tag: String, message: String)
+}
\ No newline at end of file
diff --git a/library/src/commonMain/kotlin/com/lagradost/cloudstream3/MainApi.kt b/library/src/commonMain/kotlin/com/lagradost/cloudstream3/MainApi.kt
new file mode 100644
index 00000000..87ee4815
--- /dev/null
+++ b/library/src/commonMain/kotlin/com/lagradost/cloudstream3/MainApi.kt
@@ -0,0 +1,3 @@
+package com.lagradost.cloudstream3
+
+class ErrorLoadingException(message: String? = null) : Exception(message)
\ No newline at end of file
diff --git a/app/src/main/java/com/lagradost/cloudstream3/mvvm/ArchComponentExt.kt b/library/src/commonMain/kotlin/com/lagradost/cloudstream3/mvvm/ArchComponentExt.kt
similarity index 86%
rename from app/src/main/java/com/lagradost/cloudstream3/mvvm/ArchComponentExt.kt
rename to library/src/commonMain/kotlin/com/lagradost/cloudstream3/mvvm/ArchComponentExt.kt
index 817d7db3..d3b4999a 100644
--- a/app/src/main/java/com/lagradost/cloudstream3/mvvm/ArchComponentExt.kt
+++ b/library/src/commonMain/kotlin/com/lagradost/cloudstream3/mvvm/ArchComponentExt.kt
@@ -1,10 +1,7 @@
package com.lagradost.cloudstream3.mvvm
-import android.util.Log
-import androidx.lifecycle.LifecycleOwner
-import androidx.lifecycle.LiveData
-import com.bumptech.glide.load.HttpException
-import com.lagradost.cloudstream3.BuildConfig
+import com.lagradost.api.BuildConfig
+import com.lagradost.api.Log
import com.lagradost.cloudstream3.ErrorLoadingException
import kotlinx.coroutines.*
import java.io.InterruptedIOException
@@ -49,18 +46,6 @@ inline fun debugWarning(assert: () -> Boolean, message: () -> String) {
}
}
-/** NOTE: Only one observer at a time per value */
-fun LifecycleOwner.observe(liveData: LiveData, action: (t: T) -> Unit) {
- liveData.removeObservers(this)
- liveData.observe(this) { it?.let { t -> action(t) } }
-}
-
-/** NOTE: Only one observer at a time per value */
-fun LifecycleOwner.observeNullable(liveData: LiveData, action: (t: T) -> Unit) {
- liveData.removeObservers(this)
- liveData.observe(this) { action(it) }
-}
-
sealed class Resource {
data class Success(val value: T) : Resource()
data class Failure(
@@ -158,14 +143,14 @@ fun throwAbleToResource(
"Connection Timeout\nPlease try again later."
)
}
- is HttpException -> {
- Resource.Failure(
- false,
- throwable.statusCode,
- null,
- throwable.message ?: "HttpException"
- )
- }
+// is HttpException -> {
+// Resource.Failure(
+// false,
+// throwable.statusCode,
+// null,
+// throwable.message ?: "HttpException"
+// )
+// }
is UnknownHostException -> {
Resource.Failure(true, null, null, "Cannot connect to server, try again later.\n${throwable.message}")
}
diff --git a/library/src/jvmMain/kotlin/com/lagradost/api/Log.kt b/library/src/jvmMain/kotlin/com/lagradost/api/Log.kt
new file mode 100644
index 00000000..e9a0e6b4
--- /dev/null
+++ b/library/src/jvmMain/kotlin/com/lagradost/api/Log.kt
@@ -0,0 +1,19 @@
+package com.lagradost.api
+
+actual object Log {
+ actual fun d(tag: String, message: String) {
+ println("DEBUG $tag: $message")
+ }
+
+ actual fun i(tag: String, message: String) {
+ println("INFO $tag: $message")
+ }
+
+ actual fun w(tag: String, message: String) {
+ println("WARNING $tag: $message")
+ }
+
+ actual fun e(tag: String, message: String) {
+ println("ERROR $tag: $message")
+ }
+}
\ No newline at end of file
diff --git a/settings.gradle.kts b/settings.gradle.kts
index 17070047..eabd9f0e 100644
--- a/settings.gradle.kts
+++ b/settings.gradle.kts
@@ -1,3 +1,4 @@
rootProject.name = "CloudStream"
-include(":app")
\ No newline at end of file
+include(":app")
+include(":library")
\ No newline at end of file
From 9a18ef641136cf9335c830145cf5b1bc4a62f8e3 Mon Sep 17 00:00:00 2001
From: int3debug <164035730+int3debug@users.noreply.github.com>
Date: Wed, 17 Apr 2024 23:48:33 +0200
Subject: [PATCH 2/5] bugfix: fixing regex special chars break it (#1047)
---
.../main/java/com/lagradost/cloudstream3/utils/JsUnpacker.kt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/app/src/main/java/com/lagradost/cloudstream3/utils/JsUnpacker.kt b/app/src/main/java/com/lagradost/cloudstream3/utils/JsUnpacker.kt
index 153dbd3e..d9f0b382 100644
--- a/app/src/main/java/com/lagradost/cloudstream3/utils/JsUnpacker.kt
+++ b/app/src/main/java/com/lagradost/cloudstream3/utils/JsUnpacker.kt
@@ -50,7 +50,7 @@ class JsUnpacker(packedJS: String?) {
throw Exception("Unknown p.a.c.k.e.r. encoding")
}
val unbase = Unbase(radix)
- p = Pattern.compile("\\b\\w+\\b")
+ p = Pattern.compile("""\b[a-zA-Z0-9_]+\b""")
m = p.matcher(payload)
val decoded = StringBuilder(payload)
var replaceOffset = 0
From 6cef9f7ea257f4af8ed3f739f79c1d01b1b3b36e Mon Sep 17 00:00:00 2001
From: KingLucius
Date: Sat, 20 Apr 2024 22:18:49 +0200
Subject: [PATCH 3/5] Filtering first unwatched episode respects watched state
(#1049)
---
.../com/lagradost/cloudstream3/ui/result/ResultFragmentTv.kt | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/result/ResultFragmentTv.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/result/ResultFragmentTv.kt
index 6a83f396..13621cda 100644
--- a/app/src/main/java/com/lagradost/cloudstream3/ui/result/ResultFragmentTv.kt
+++ b/app/src/main/java/com/lagradost/cloudstream3/ui/result/ResultFragmentTv.kt
@@ -783,7 +783,10 @@ class ResultFragmentTv : Fragment() {
// resultEpisodeLoading.isVisible = episodes is Resource.Loading
if (episodes is Resource.Success) {
- val lastWatchedIndex = episodes.value.indexOfLast { ep -> ep.getWatchProgress() >= NEXT_WATCH_EPISODE_PERCENTAGE.toFloat() / 100.0f }
+ val lastWatchedIndex = episodes.value.indexOfLast { ep ->
+ ep.getWatchProgress() >= NEXT_WATCH_EPISODE_PERCENTAGE.toFloat() / 100.0f || ep.videoWatchState == VideoWatchState.Watched
+ }
+
val firstUnwatched = episodes.value.getOrElse(lastWatchedIndex + 1) { episodes.value.firstOrNull() }
if (firstUnwatched != null) {
From e01ff4d843810467660add2a8464973a673daa08 Mon Sep 17 00:00:00 2001
From: KingLucius
Date: Mon, 22 Apr 2024 01:13:55 +0200
Subject: [PATCH 4/5] Fix NewPipeExtractor lib path (#1050)
---
app/build.gradle.kts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index e07162d7..f854865d 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -202,7 +202,7 @@ dependencies {
// PlayBack
implementation("com.jaredrummler:colorpicker:1.1.0") // Subtitle Color Picker
implementation("com.github.recloudstream:media-ffmpeg:1.1.0") // Custom FF-MPEG Lib for Audio Codecs
- implementation("com.github.teamnewpipe:NewPipeExtractor:6dc25f7") /* For Trailers
+ implementation("com.github.TeamNewPipe.NewPipeExtractor:NewPipeExtractor:6dc25f7b97") /* For Trailers
^ Update to Latest Commits if Trailers Misbehave, github.com/TeamNewPipe/NewPipeExtractor/commits/dev */
implementation("com.github.albfernandez:juniversalchardet:2.4.0") // Subtitle Decoding
From 4399a612dfa0672acefc7de17c37884ee64331c5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C3=96mer=20Faruk=20Sancak?=
Date: Mon, 22 Apr 2024 02:14:36 +0300
Subject: [PATCH 5/5] Update Vidmoly.kt (#1051)
---
.../java/com/lagradost/cloudstream3/extractors/Vidmoly.kt | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/app/src/main/java/com/lagradost/cloudstream3/extractors/Vidmoly.kt b/app/src/main/java/com/lagradost/cloudstream3/extractors/Vidmoly.kt
index 615cfd74..979fd8c5 100644
--- a/app/src/main/java/com/lagradost/cloudstream3/extractors/Vidmoly.kt
+++ b/app/src/main/java/com/lagradost/cloudstream3/extractors/Vidmoly.kt
@@ -25,9 +25,13 @@ open class Vidmoly : ExtractorApi() {
subtitleCallback: (SubtitleFile) -> Unit,
callback: (ExtractorLink) -> Unit
) {
-
+ val headers = mapOf(
+ "User-Agent" to "Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Mobile Safari/537.36",
+ "Sec-Fetch-Dest" to "iframe"
+ )
val script = app.get(
url,
+ headers = headers,
referer = referer,
).document.select("script")
.find { it.data().contains("sources:") }?.data()
@@ -66,4 +70,4 @@ open class Vidmoly : ExtractorApi() {
@JsonProperty("kind") val kind: String? = null,
)
-}
\ No newline at end of file
+}