Skip to content

Commit

Permalink
Merge pull request #5 from WebDitto/sync
Browse files Browse the repository at this point in the history
chore: Sync with latest commits
  • Loading branch information
almightyhak authored Jun 24, 2024
2 parents 286c655 + 56c945d commit 08da414
Show file tree
Hide file tree
Showing 115 changed files with 2,221 additions and 436 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@ package eu.kanade.tachiyomi.lib.vidbomextractor
import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.util.asJsoup
import okhttp3.Headers
import okhttp3.OkHttpClient

class VidBomExtractor(private val client: OkHttpClient) {
fun videosFromUrl(url: String): List<Video> {
val doc = client.newCall(GET(url)).execute().asJsoup()
fun videosFromUrl(url: String, headers: Headers? = null): List<Video> {
val request = if (headers != null) GET(url, headers) else GET(url)
val doc = client.newCall(request).execute().asJsoup()
val script = doc.selectFirst("script:containsData(sources)")!!
val data = script.data().substringAfter("sources: [").substringBefore("],")

Expand Down
3 changes: 2 additions & 1 deletion src/all/sudatchi/build.gradle
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
ext {
extName = 'Sudatchi'
extClass = '.Sudatchi'
extVersionCode = 1
extVersionCode = 3
isNsfw = true
}

apply from: "$rootDir/common.gradle"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,13 @@ import android.app.Application
import android.content.SharedPreferences
import androidx.preference.ListPreference
import androidx.preference.PreferenceScreen
import eu.kanade.tachiyomi.animeextension.all.sudatchi.dto.AnimeDto
import eu.kanade.tachiyomi.animeextension.all.sudatchi.dto.AnimePageDto
import eu.kanade.tachiyomi.animeextension.all.sudatchi.dto.DirectoryDto
import eu.kanade.tachiyomi.animeextension.all.sudatchi.dto.HomeListDto
import eu.kanade.tachiyomi.animeextension.all.sudatchi.dto.LongAnimeDto
import eu.kanade.tachiyomi.animeextension.all.sudatchi.dto.ShortAnimeDto
import eu.kanade.tachiyomi.animeextension.all.sudatchi.dto.EpisodePageDto
import eu.kanade.tachiyomi.animeextension.all.sudatchi.dto.HomePageDto
import eu.kanade.tachiyomi.animeextension.all.sudatchi.dto.PropsDto
import eu.kanade.tachiyomi.animeextension.all.sudatchi.dto.SubtitleDto
import eu.kanade.tachiyomi.animeextension.all.sudatchi.dto.WatchDto
import eu.kanade.tachiyomi.animesource.ConfigurableAnimeSource
import eu.kanade.tachiyomi.animesource.model.AnimeFilterList
import eu.kanade.tachiyomi.animesource.model.AnimesPage
Expand All @@ -27,6 +28,7 @@ import kotlinx.serialization.json.Json
import okhttp3.HttpUrl.Companion.toHttpUrl
import okhttp3.Request
import okhttp3.Response
import org.jsoup.nodes.Document
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import uy.kohesive.injekt.injectLazy
Expand All @@ -37,6 +39,8 @@ class Sudatchi : AnimeHttpSource(), ConfigurableAnimeSource {

override val baseUrl = "https://sudatchi.com"

private val ipfsUrl = "https://ipfs.animeui.com"

override val lang = "all"

override val supportsLatest = true
Expand All @@ -52,7 +56,7 @@ class Sudatchi : AnimeHttpSource(), ConfigurableAnimeSource {
}

// ============================== Popular ===============================
override fun popularAnimeRequest(page: Int) = GET("$baseUrl/api/home-list", headers)
override fun popularAnimeRequest(page: Int) = GET(baseUrl, headers)

private fun Int.parseStatus() = when (this) {
1 -> SAnime.UNKNOWN // Not Yet Released
Expand All @@ -61,7 +65,7 @@ class Sudatchi : AnimeHttpSource(), ConfigurableAnimeSource {
else -> SAnime.UNKNOWN
}

private fun ShortAnimeDto.toSAnime(titleLang: String) = SAnime.create().apply {
private fun AnimeDto.toSAnime(titleLang: String) = SAnime.create().apply {
url = "/anime/$slug"
title = when (titleLang) {
"romaji" -> titleRomanji
Expand All @@ -70,14 +74,19 @@ class Sudatchi : AnimeHttpSource(), ConfigurableAnimeSource {
} ?: arrayOf(titleEnglish, titleRomanji, titleJapanese, "").firstNotNullOf { it }
description = synopsis
status = statusId.parseStatus()
thumbnail_url = "$baseUrl$imgUrl"
thumbnail_url = when {
imgUrl.startsWith("/") -> "$baseUrl$imgUrl"
else -> "$ipfsUrl/ipfs/$imgUrl"
}
genre = animeGenres?.joinToString { it.genre.name }
}

override fun popularAnimeParse(response: Response): AnimesPage {
sudatchiFilters.fetchFilters()
val titleLang = preferences.title
return AnimesPage(response.parseAs<HomeListDto>().animeSpotlight.map { it.toSAnime(titleLang) }, false)
val document = response.asJsoup()
val data = document.parseAs<HomePageDto>().animeSpotlight
return AnimesPage(data.map { it.toSAnime(titleLang) }, false)
}

// =============================== Latest ===============================
Expand All @@ -97,15 +106,22 @@ class Sudatchi : AnimeHttpSource(), ConfigurableAnimeSource {
override suspend fun getSearchAnime(page: Int, query: String, filters: AnimeFilterList): AnimesPage {
return if (query.startsWith(PREFIX_SEARCH)) { // URL intent handler
val id = query.removePrefix(PREFIX_SEARCH)
client.newCall(GET("$baseUrl/api/anime/$id", headers))
client.newCall(GET("$baseUrl/anime/$id", headers))
.awaitSuccess()
.use(::searchAnimeByIdParse)
} else {
super.getSearchAnime(page, query, filters)
}
}

private fun searchAnimeByIdParse(response: Response) = AnimesPage(listOf(animeDetailsParse(response)), false)
private fun searchAnimeByIdParse(response: Response): AnimesPage {
val details = animeDetailsParse(response).apply {
setUrlWithoutDomain(response.request.url.toString())
initialized = true
}

return AnimesPage(listOf(details), false)
}

override fun searchAnimeRequest(page: Int, query: String, filters: AnimeFilterList): Request {
val url = "$baseUrl/api/directory".toHttpUrl().newBuilder()
Expand All @@ -123,15 +139,18 @@ class Sudatchi : AnimeHttpSource(), ConfigurableAnimeSource {
// =========================== Anime Details ============================
override fun getAnimeUrl(anime: SAnime) = "$baseUrl${anime.url}"

override fun animeDetailsRequest(anime: SAnime) = GET("$baseUrl/api${anime.url}", headers)

override fun animeDetailsParse(response: Response) = response.parseAs<ShortAnimeDto>().toSAnime(preferences.title)
override fun animeDetailsParse(response: Response): SAnime {
val document = response.asJsoup()
val data = document.parseAs<AnimePageDto>().animeData
return data.toSAnime(preferences.title)
}

// ============================== Episodes ==============================
override fun episodeListRequest(anime: SAnime) = animeDetailsRequest(anime)

override fun episodeListParse(response: Response): List<SEpisode> {
val anime = response.parseAs<LongAnimeDto>()
val document = response.asJsoup()
val anime = document.parseAs<AnimePageDto>().animeData
return anime.episodes.map {
SEpisode.create().apply {
name = it.title
Expand All @@ -148,8 +167,7 @@ class Sudatchi : AnimeHttpSource(), ConfigurableAnimeSource {

override fun videoListParse(response: Response): List<Video> {
val document = response.asJsoup()
val jsonString = document.selectFirst("script#__NEXT_DATA__")?.data() ?: return emptyList()
val data = json.decodeFromString<WatchDto>(jsonString).props.pageProps.episodeData
val data = document.parseAs<EpisodePageDto>().episodeData
val subtitles = json.decodeFromString<List<SubtitleDto>>(data.subtitlesJson)
// val videoUrl = client.newCall(GET("$baseUrl/api/streams?episodeId=${data.episode.id}", headers)).execute().parseAs<StreamsDto>().url
// keeping it in case the simpler solution breaks, can be hardcoded to this for now :
Expand All @@ -158,7 +176,7 @@ class Sudatchi : AnimeHttpSource(), ConfigurableAnimeSource {
videoUrl,
videoNameGen = { "Sudatchi (Private IPFS Gateway) - $it" },
subtitleList = subtitles.map {
Track("$baseUrl${it.url}", "${it.subtitlesName.name} (${it.subtitlesName.language})")
Track("$ipfsUrl${it.url}", "${it.subtitlesName.name} (${it.subtitlesName.language})")
}.sort(),
)
}
Expand Down Expand Up @@ -226,6 +244,11 @@ class Sudatchi : AnimeHttpSource(), ConfigurableAnimeSource {
}

// ============================= Utilities ==============================
private inline fun <reified T> Document.parseAs(): T {
val nextData = this.selectFirst("script#__NEXT_DATA__")!!.data()
return json.decodeFromString<PropsDto<T>>(nextData).props.pageProps
}

private val SharedPreferences.quality get() = getString(PREF_QUALITY_KEY, PREF_QUALITY_DEFAULT)!!
private val SharedPreferences.subtitles get() = getString(PREF_SUBTITLES_KEY, PREF_SUBTITLES_DEFAULT)!!
private val SharedPreferences.title get() = getString(PREF_TITLE_KEY, PREF_TITLE_DEFAULT)!!
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,23 @@ import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

@Serializable
data class Genre(val name: String)
data class GenreDto(val name: String)

@Serializable
data class AnimeGenreRelation(
data class AnimeGenreRelationDto(
@SerialName("Genre")
val genre: Genre,
val genre: GenreDto,
)

@Serializable
data class ShortAnimeDto(
data class EpisodeDto(
val title: String,
val id: Int,
val number: Int,
)

@Serializable
data class AnimeDto(
val titleRomanji: String?,
val titleEnglish: String?,
val titleJapanese: String?,
Expand All @@ -22,68 +29,57 @@ data class ShortAnimeDto(
val statusId: Int,
val imgUrl: String,
@SerialName("AnimeGenres")
val animeGenres: List<AnimeGenreRelation>?,
val animeGenres: List<AnimeGenreRelationDto>?,
@SerialName("Episodes")
val episodes: List<EpisodeDto> = emptyList(),
)

@Serializable
data class HomeListDto(
data class HomePageDto(
@SerialName("AnimeSpotlight")
val animeSpotlight: List<ShortAnimeDto>,
)

@Serializable
data class DirectoryDto(
val animes: List<ShortAnimeDto>,
val page: Int,
val pages: Int,
val animeSpotlight: List<AnimeDto>,
)

@Serializable
data class Episode(
val title: String,
val id: Int,
val number: Int,
data class AnimePageDto(
val animeData: AnimeDto,
)

@Serializable
data class LongAnimeDto(
val slug: String,
@SerialName("Episodes")
val episodes: List<Episode>,
data class EpisodeDataDto(
val episode: EpisodeDto,
val subtitlesJson: String,
)

@Serializable
data class SubtitleLangDto(
val name: String,
val language: String,
data class EpisodePageDto(
val episodeData: EpisodeDataDto,
)

@Serializable
data class SubtitleDto(
val url: String,
@SerialName("SubtitlesName")
val subtitlesName: SubtitleLangDto,
)
data class PagePropsDto<T>(val pageProps: T)

@Serializable
data class EpisodeDataDto(
val episode: Episode,
val subtitlesJson: String,
)
data class PropsDto<T>(val props: PagePropsDto<T>)

@Serializable
data class PagePropsDto(
val episodeData: EpisodeDataDto,
data class DirectoryDto(
val animes: List<AnimeDto>,
val page: Int,
val pages: Int,
)

@Serializable
data class DataWatchDto(
val pageProps: PagePropsDto,
data class SubtitleLangDto(
val name: String,
val language: String,
)

@Serializable
data class WatchDto(
val props: DataWatchDto,
data class SubtitleDto(
val url: String,
@SerialName("SubtitlesName")
val subtitlesName: SubtitleLangDto,
)

@Serializable
Expand Down
4 changes: 2 additions & 2 deletions src/all/supjav/build.gradle
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
ext {
extName = 'SupJav'
extClass = '.SupJavFactory'
extVersionCode = 8
extVersionCode = 9
isNsfw = true
}

Expand All @@ -12,4 +12,4 @@ dependencies {
implementation(project(":lib:streamwish-extractor"))
implementation(project(":lib:voe-extractor"))
implementation(project(":lib:playlist-utils"))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,11 @@ class SupJav(override val lang: String = "en") : ConfigurableAnimeSource, Parsed
}

private fun searchAnimeByIdParse(response: Response): AnimesPage {
val details = animeDetailsParse(response.asJsoup())
val details = animeDetailsParse(response.asJsoup()).apply {
setUrlWithoutDomain(response.request.url.toString())
initialized = true
}

return AnimesPage(listOf(details), false)
}

Expand Down
22 changes: 22 additions & 0 deletions src/all/torrentio/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application>
<activity
android:name=".all.torrentio.TorrentioUrlActivity"
android:excludeFromRecents="true"
android:exported="true"
android:theme="@android:style/Theme.NoDisplay">
<intent-filter>
<action android:name="android.intent.action.VIEW" />

<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />

<data
android:host="torrentio.strem.fun"
android:pathPattern="/anime/..*"
android:scheme="https" />
</intent-filter>
</activity>
</application>
</manifest>
8 changes: 8 additions & 0 deletions src/all/torrentio/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
ext {
extName = 'Torrentio (Torrent / Debrid)'
extClass = '.Torrentio'
extVersionCode = 1
containsNsfw = false
}

apply from: "$rootDir/common.gradle"
Binary file added src/all/torrentio/res/mipmap-hdpi/ic_launcher.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/all/torrentio/res/mipmap-mdpi/ic_launcher.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit 08da414

Please sign in to comment.