diff --git a/.github/ISSUE_TEMPLATE/01_report_issue.yml b/.github/ISSUE_TEMPLATE/01_report_issue.yml index acbe78bd..5c4de31f 100644 --- a/.github/ISSUE_TEMPLATE/01_report_issue.yml +++ b/.github/ISSUE_TEMPLATE/01_report_issue.yml @@ -1,5 +1,5 @@ -name: 🐞 Issue report -description: Report a source issue in Aniyomi +name: 🐞 Bug report +description: Report a bug labels: [Bug] body: @@ -57,11 +57,22 @@ body: required: true - type: input - id: aniyomi-version + id: which-app attributes: - label: Aniyomi version + label: Which app are you using? + placeholder: | + Example: Aniyomi, Kuukiyomi, Animiru, Animetail + description: | + Self explanatory + validations: + required: true + + - type: input + id: app-version + attributes: + label: App version description: | - You can find your Aniyomi version in **More → About**. + You can find your app version in **More → About**. placeholder: | Example: "0.15.2.4" or "Preview r7473" validations: @@ -95,13 +106,9 @@ body: required: true - label: I have written a short but informative title. required: true - - label: I have updated the app to version **[0.15.2.4](https://github.com/aniyomiorg/aniyomi/releases/latest)**. - required: true - label: I have updated all installed extensions. required: true - label: I have tried the [troubleshooting guide](https://aniyomi.org/docs/guides/troubleshooting/). required: true - - label: If this is an issue with the app itself, I should be opening an issue in the [app repository](https://github.com/aniyomiorg/aniyomi/issues/new/choose). - required: true - label: I will fill out all of the requested information in this form. required: true diff --git a/.github/ISSUE_TEMPLATE/02_request_source.yml b/.github/ISSUE_TEMPLATE/02_request_source.yml index 8445aa4b..4fd702eb 100644 --- a/.github/ISSUE_TEMPLATE/02_request_source.yml +++ b/.github/ISSUE_TEMPLATE/02_request_source.yml @@ -1,5 +1,5 @@ name: 🌐 Source request -description: Suggest a new source for Aniyomi +description: Suggest a new source labels: [Source request] body: diff --git a/.github/ISSUE_TEMPLATE/05_request_feature.yml b/.github/ISSUE_TEMPLATE/05_request_feature.yml index e47281fb..4a0ebee7 100644 --- a/.github/ISSUE_TEMPLATE/05_request_feature.yml +++ b/.github/ISSUE_TEMPLATE/05_request_feature.yml @@ -53,7 +53,5 @@ body: required: true - label: If this is an issue with the app itself, I should be opening an issue in the [app repository](https://github.com/aniyomiorg/aniyomi/issues/new/choose). required: true - - label: I have updated the app to version **[0.15.2.4](https://github.com/aniyomiorg/aniyomi/releases/latest)**. - required: true - label: I will fill out all of the requested information in this form. required: true diff --git a/.github/ISSUE_TEMPLATE/06_request_meta.yml b/.github/ISSUE_TEMPLATE/06_request_meta.yml deleted file mode 100644 index f6003b85..00000000 --- a/.github/ISSUE_TEMPLATE/06_request_meta.yml +++ /dev/null @@ -1,41 +0,0 @@ -name: 🧠 Meta request -description: Suggest improvements to the project -labels: [Meta request] -body: - - - type: textarea - id: feature-description - attributes: - label: Describe why this should be added - description: How can the project be improved? - placeholder: | - Example: - "It should work like this..." - validations: - required: true - - - type: textarea - id: other-details - attributes: - label: Other details - placeholder: | - Additional details and attachments. - - - type: checkboxes - id: acknowledgements - attributes: - label: Acknowledgements - description: Your issue will be closed if you haven't done these steps. - options: - - label: I have searched the existing issues and this is a new ticket, **NOT** a duplicate or related to another open (or closed) issue. - required: true - - label: I have written a short but informative title. - required: true - - label: If this is an issue with the app itself, I should be opening an issue in the [app repository](https://github.com/aniyomiorg/aniyomi/issues/new/choose). - required: true - - label: I have updated the app to version **[0.15.2.4](https://github.com/aniyomiorg/aniyomi/releases/latest)**. - required: true - - label: I have updated all installed extensions. - required: true - - label: I will fill out all of the requested information in this form. - required: true diff --git a/.github/ISSUE_TEMPLATE/07_request_removal.yml b/.github/ISSUE_TEMPLATE/06_request_removal.yml similarity index 90% rename from .github/ISSUE_TEMPLATE/07_request_removal.yml rename to .github/ISSUE_TEMPLATE/06_request_removal.yml index 7b3617bf..b957ff85 100644 --- a/.github/ISSUE_TEMPLATE/07_request_removal.yml +++ b/.github/ISSUE_TEMPLATE/06_request_removal.yml @@ -25,7 +25,7 @@ body: label: Requirements description: Your request will be denied if you don't meet these requirements. options: - - label: Proof of ownership/intent to remove sent to a Aniyomi Discord server mod via DM + - label: Proof of ownership/intent to remove sent to a Kohi den Discord server mod via DM required: true - label: Site only hosts content scanlated by the group and not stolen from other scanlators or official releases (i.e., not an aggregator site) required: true diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml deleted file mode 100644 index 9e1a6b4e..00000000 --- a/.github/ISSUE_TEMPLATE/config.yml +++ /dev/null @@ -1,14 +0,0 @@ -blank_issues_enabled: false -contact_links: - - name: ⚠️ Application issue - url: https://github.com/aniyomiorg/aniyomi/issues/new/choose - about: Issues and requests about the app itself should be opened in the tachiyomi repository instead - - name: 📦 Aniyomi extensions - url: https://aniyomi.org/extensions - about: List of all available extensions with download links - - name: 🖥️ Aniyomi website - url: https://aniyomi.org/help/ - about: Guides, troubleshooting, and answers to common questions - - name: Aniyomi app GitHub repository - url: https://github.com/aniyomiorg/aniyomi - about: Issues about the app itself should be opened here instead. diff --git a/lib/streamsilk-extractor/build.gradle.kts b/lib/streamsilk-extractor/build.gradle.kts new file mode 100644 index 00000000..d31dd9ff --- /dev/null +++ b/lib/streamsilk-extractor/build.gradle.kts @@ -0,0 +1,7 @@ +plugins { + id("lib-android") +} + +dependencies { + implementation(project(":lib:playlist-utils")) +} diff --git a/lib/streamsilk-extractor/src/main/java/eu/kanade/tachiyomi/lib/streamsilkextractor/JsHunter.kt b/lib/streamsilk-extractor/src/main/java/eu/kanade/tachiyomi/lib/streamsilkextractor/JsHunter.kt new file mode 100644 index 00000000..8fff8ef0 --- /dev/null +++ b/lib/streamsilk-extractor/src/main/java/eu/kanade/tachiyomi/lib/streamsilkextractor/JsHunter.kt @@ -0,0 +1,86 @@ +package eu.kanade.tachiyomi.lib.streamsilkextractor + +import java.util.regex.Matcher +import java.util.regex.Pattern +import kotlin.math.pow + +class JsHunter(private val hunterJS: String) { + + /** + * Detects whether the javascript is H.U.N.T.E.R coded. + * + * @return true if it's H.U.N.T.E.R coded. + */ + fun detect(): Boolean { + val p = Pattern.compile("eval\\(function\\(h,u,n,t,e,r\\)") + val searchResults = p.matcher(hunterJS) + return searchResults.find() + } + + /** + * Unpack the javascript + * + * @return the javascript unhunt or null. + */ + + fun dehunt(): String? { + try { + val p: Pattern = + Pattern.compile( + """\}\("([^"]+)",[^,]+,\s*"([^"]+)",\s*(\d+),\s*(\d+)""", + Pattern.DOTALL + ) + val searchResults: Matcher = p.matcher(hunterJS) + if (searchResults.find() && searchResults.groupCount() == 4) { + val h = searchResults.group(1)!!.toString() + val n = searchResults.group(2)!!.toString() + val t = searchResults.group(3)!!.toInt() + val e = searchResults.group(4)!!.toInt() + return hunter(h, n, t, e) + } + } catch (e: Exception) { + return null + } + return null + } + + private fun duf(d: String, e: Int, f: Int = 10): Int { + val str = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ+/" + val g = str.toList() + val h = g.take(e) + val i = g.take(f) + val dList = d.reversed().toList() + var j = 0.0 + for ((c, b) in dList.withIndex()) { + if (b in h) { + j += h.indexOf(b) * e.toDouble().pow(c) + } + } + var k = "" + while (j > 0) { + k = i[(j % f).toInt()] + k + j = (j - j % f) / f + } + return k.toIntOrNull() ?: 0 + } + + private fun hunter(h: String, n: String, t: Int, e: Int): String { + var result = "" + var i = 0 + while (i < h.length) { + var j = 0 + var s = "" + while (h[i] != n[e]) { + s += h[i] + i++ + } + while (j < n.length) { + s = s.replace(n[j], j.digitToChar()) + j++ + } + result += (duf(s, e) - t).toChar() + i++ + } + return result + } +} diff --git a/lib/streamsilk-extractor/src/main/java/eu/kanade/tachiyomi/lib/streamsilkextractor/StreamSilkExtractor.kt b/lib/streamsilk-extractor/src/main/java/eu/kanade/tachiyomi/lib/streamsilkextractor/StreamSilkExtractor.kt new file mode 100644 index 00000000..2c80ab48 --- /dev/null +++ b/lib/streamsilk-extractor/src/main/java/eu/kanade/tachiyomi/lib/streamsilkextractor/StreamSilkExtractor.kt @@ -0,0 +1,62 @@ +package eu.kanade.tachiyomi.lib.streamsilkextractor + +import eu.kanade.tachiyomi.animesource.model.Track +import eu.kanade.tachiyomi.animesource.model.Video +import eu.kanade.tachiyomi.lib.playlistutils.PlaylistUtils +import eu.kanade.tachiyomi.network.GET +import eu.kanade.tachiyomi.util.asJsoup +import kotlinx.serialization.Serializable +import kotlinx.serialization.json.Json +import okhttp3.Headers +import okhttp3.OkHttpClient +import okhttp3.internal.commonEmptyHeaders +import uy.kohesive.injekt.injectLazy + +class StreamSilkExtractor(private val client: OkHttpClient, private val headers: Headers = commonEmptyHeaders) { + + private val srcRegex = Regex("var urlPlay =\\s*\"(.*?m3u8.*?)\"") + + private val subsRegex = Regex("jsonUrl = `([^`]*)`") + + private val videoHeaders by lazy { + headers.newBuilder() + .set("Referer", "$STREAM_SILK_URL/") + .set("Origin", STREAM_SILK_URL) + .build() + } + + private val json: Json by injectLazy() + + private val playlistUtils by lazy { PlaylistUtils(client, videoHeaders) } + + fun videosFromUrl(url: String, prefix: String) = videosFromUrl(url) { "${prefix}StreamSilk:$it" } + + fun videosFromUrl(url: String, videoNameGen: (String) -> String = { quality -> "StreamSilk:$quality" }): List