diff --git a/src/en/warforrayuba/AndroidManifest.xml b/src/en/warforrayuba/AndroidManifest.xml new file mode 100644 index 000000000..30deb7f79 --- /dev/null +++ b/src/en/warforrayuba/AndroidManifest.xml @@ -0,0 +1,2 @@ + + diff --git a/src/en/warforrayuba/build.gradle b/src/en/warforrayuba/build.gradle new file mode 100644 index 000000000..e3df25371 --- /dev/null +++ b/src/en/warforrayuba/build.gradle @@ -0,0 +1,16 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlinx-serialization' + +ext { + extName = 'War For Rayuba' + pkgNameSuffix = 'en.warforrayuba' + extClass = '.WarForRayuba' + extVersionCode = 1 +} + +dependencies { + implementation project(':lib-ratelimit') +} + +apply from: "$rootDir/common.gradle" diff --git a/src/en/warforrayuba/res/mipmap-hdpi/ic_launcher.png b/src/en/warforrayuba/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 000000000..93ca7ab25 Binary files /dev/null and b/src/en/warforrayuba/res/mipmap-hdpi/ic_launcher.png differ diff --git a/src/en/warforrayuba/res/mipmap-mdpi/ic_launcher.png b/src/en/warforrayuba/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 000000000..b541e1fdb Binary files /dev/null and b/src/en/warforrayuba/res/mipmap-mdpi/ic_launcher.png differ diff --git a/src/en/warforrayuba/res/mipmap-xhdpi/ic_launcher.png b/src/en/warforrayuba/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 000000000..541244928 Binary files /dev/null and b/src/en/warforrayuba/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/src/en/warforrayuba/res/mipmap-xxhdpi/ic_launcher.png b/src/en/warforrayuba/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 000000000..fa6dff8b1 Binary files /dev/null and b/src/en/warforrayuba/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/src/en/warforrayuba/res/mipmap-xxxhdpi/ic_launcher.png b/src/en/warforrayuba/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 000000000..d70951f95 Binary files /dev/null and b/src/en/warforrayuba/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/src/en/warforrayuba/res/web_hi_res_512.png b/src/en/warforrayuba/res/web_hi_res_512.png new file mode 100644 index 000000000..959452e89 Binary files /dev/null and b/src/en/warforrayuba/res/web_hi_res_512.png differ diff --git a/src/en/warforrayuba/src/eu/kanade/tachiyomi/extension/en/warforrayuba/WarForRayuba.kt b/src/en/warforrayuba/src/eu/kanade/tachiyomi/extension/en/warforrayuba/WarForRayuba.kt new file mode 100644 index 000000000..9db8d8765 --- /dev/null +++ b/src/en/warforrayuba/src/eu/kanade/tachiyomi/extension/en/warforrayuba/WarForRayuba.kt @@ -0,0 +1,157 @@ +package eu.kanade.tachiyomi.extension.en.warforrayuba + +import android.os.Build +import eu.kanade.tachiyomi.BuildConfig +import eu.kanade.tachiyomi.extension.en.warforrayuba.dto.PageDto +import eu.kanade.tachiyomi.extension.en.warforrayuba.dto.RoundDto +import eu.kanade.tachiyomi.lib.ratelimit.RateLimitInterceptor +import eu.kanade.tachiyomi.network.GET +import eu.kanade.tachiyomi.network.asObservableSuccess +import eu.kanade.tachiyomi.source.model.FilterList +import eu.kanade.tachiyomi.source.model.MangasPage +import eu.kanade.tachiyomi.source.model.Page +import eu.kanade.tachiyomi.source.model.SChapter +import eu.kanade.tachiyomi.source.model.SManga +import eu.kanade.tachiyomi.source.online.HttpSource +import eu.kanade.tachiyomi.util.asJsoup +import kotlinx.serialization.decodeFromString +import kotlinx.serialization.json.Json +import okhttp3.Headers +import okhttp3.Request +import okhttp3.Response +import rx.Observable + +class WarForRayuba : HttpSource() { + + override val name = "War For Rayuba" + + override val baseUrl = "https://xrabohrok.github.io/WarMap/#/" + + override val lang = "en" + + override val supportsLatest = false + + override val client = network.cloudflareClient.newBuilder() + .addNetworkInterceptor(RateLimitInterceptor(4)).build() + + private val json = Json { + isLenient = true + ignoreUnknownKeys = true + allowSpecialFloatingPointValues = true + useArrayPolymorphism = true + prettyPrint = true + } + + private val cubariHeaders = Headers.Builder().apply { + add( + "User-Agent", + "(Android ${Build.VERSION.RELEASE}; " + + "${Build.MANUFACTURER} ${Build.MODEL}) " + + "Tachiyomi/${BuildConfig.VERSION_NAME} " + + Build.ID + ) + }.build() + + override fun headersBuilder() = Headers.Builder().apply { + add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:86.0) Gecko/20100101 Firefox/86.0 ") + add("Referer", baseUrl) + } + + override fun popularMangaRequest(page: Int) = GET("https://github.com/xrabohrok/WarMap/tree/main/tools", headers) + + override fun popularMangaParse(response: Response): MangasPage { + val document = response.asJsoup() + + val mangas = document.select("#repo-content-pjax-container .Details div[role=row] div[role=rowheader] a[href*='.json']").map { element -> + SManga.create().apply { + val githubRawUrl = "https://raw.githubusercontent.com/xrabohrok/WarMap/" + element.attr("abs:href").replace(".*(?=main)".toRegex(), "") + val githubData: RoundDto = json.decodeFromString( + client.newCall(GET(githubRawUrl, headers)).execute().body!!.string() + ) + + title = githubData.title + thumbnail_url = githubData.cover + url = githubRawUrl + } + } + + return MangasPage(mangas, false) + } + + override fun fetchMangaDetails(manga: SManga): Observable { + return client.newCall(apiMangaDetailsRequest(manga)) + .asObservableSuccess() + .map { response -> + mangaDetailsParse(response).apply { initialized = true } + } + } + + private fun apiMangaDetailsRequest(manga: SManga): Request { + return GET(manga.url, headers) + } + + override fun mangaDetailsRequest(manga: SManga): Request { + return GET(baseUrl, headers) + } + + override fun mangaDetailsParse(response: Response) = SManga.create().apply { + val githubData: RoundDto = json.decodeFromString(response.body!!.string()) + + thumbnail_url = githubData.cover + status = SManga.UNKNOWN + author = githubData.author + artist = githubData.artist + title = githubData.title + description = githubData.description + } + + override fun chapterListRequest(manga: SManga): Request { + return GET(manga.url, headers) + } + + override fun chapterListParse(response: Response): List { + val responseJson: RoundDto = json.decodeFromString(response.body!!.string()) + + val chapterList: MutableList = ArrayList() + responseJson.chapters.forEach { (number, chapter) -> + chapterList.add( + SChapter.create().apply { + url = "https://cubari.moe" + chapter.groups.primary + chapter_number = number.toFloat() + name = number.toString() + " " + chapter.title + date_upload = chapter.last_updated + } + ) + } + + return chapterList.reversed() + } + + override fun pageListRequest(chapter: SChapter): Request { + return GET(chapter.url, cubariHeaders) + } + + override fun pageListParse(response: Response): List { + val chapterData: List = json.decodeFromString(response.body!!.string()) + + val pageList = chapterData.mapIndexed { index, page -> + Page(index, page.src.slice(0..page.src.lastIndexOf(".")), page.src) + } + + return pageList + } + + override fun fetchSearchManga(page: Int, query: String, filters: FilterList): Observable { + return Observable.just(MangasPage(emptyList(), false)) + } + + override fun searchMangaRequest(page: Int, query: String, filters: FilterList) = throw UnsupportedOperationException("Not Used") + + override fun latestUpdatesRequest(page: Int) = throw UnsupportedOperationException("Not Used") + + override fun imageUrlParse(response: Response): String = throw UnsupportedOperationException("Not Used") + + override fun latestUpdatesParse(response: Response): MangasPage = throw UnsupportedOperationException("Not Used") + + override fun searchMangaParse(response: Response): MangasPage = throw UnsupportedOperationException("Not Used") +} diff --git a/src/en/warforrayuba/src/eu/kanade/tachiyomi/extension/en/warforrayuba/dto/ChapterDto.kt b/src/en/warforrayuba/src/eu/kanade/tachiyomi/extension/en/warforrayuba/dto/ChapterDto.kt new file mode 100644 index 000000000..02dae64d2 --- /dev/null +++ b/src/en/warforrayuba/src/eu/kanade/tachiyomi/extension/en/warforrayuba/dto/ChapterDto.kt @@ -0,0 +1,16 @@ +package eu.kanade.tachiyomi.extension.en.warforrayuba.dto + +import kotlinx.serialization.Serializable + +@Serializable +data class ChapterDto( + val title: String, + val volume: Int, + val groups: ChapterGroupDto, + val last_updated: Long, +) + +@Serializable +data class ChapterGroupDto( + val primary: String +) diff --git a/src/en/warforrayuba/src/eu/kanade/tachiyomi/extension/en/warforrayuba/dto/PageDto.kt b/src/en/warforrayuba/src/eu/kanade/tachiyomi/extension/en/warforrayuba/dto/PageDto.kt new file mode 100644 index 000000000..ee496c862 --- /dev/null +++ b/src/en/warforrayuba/src/eu/kanade/tachiyomi/extension/en/warforrayuba/dto/PageDto.kt @@ -0,0 +1,9 @@ +package eu.kanade.tachiyomi.extension.en.warforrayuba.dto + +import kotlinx.serialization.Serializable + +@Serializable +data class PageDto( + val description: String, + val src: String +) diff --git a/src/en/warforrayuba/src/eu/kanade/tachiyomi/extension/en/warforrayuba/dto/RoundDto.kt b/src/en/warforrayuba/src/eu/kanade/tachiyomi/extension/en/warforrayuba/dto/RoundDto.kt new file mode 100644 index 000000000..8256ba15c --- /dev/null +++ b/src/en/warforrayuba/src/eu/kanade/tachiyomi/extension/en/warforrayuba/dto/RoundDto.kt @@ -0,0 +1,13 @@ +package eu.kanade.tachiyomi.extension.en.warforrayuba.dto + +import kotlinx.serialization.Serializable + +@Serializable +data class RoundDto( + val title: String, + val description: String, + val artist: String, + val author: String, + val cover: String, + val chapters: Map +)