diff --git a/src/en/brewingscans/AndroidManifest.xml b/src/en/brewingscans/AndroidManifest.xml new file mode 100644 index 000000000..30deb7f79 --- /dev/null +++ b/src/en/brewingscans/AndroidManifest.xml @@ -0,0 +1,2 @@ + + diff --git a/src/en/brewingscans/build.gradle b/src/en/brewingscans/build.gradle new file mode 100644 index 000000000..c9fd1d7e6 --- /dev/null +++ b/src/en/brewingscans/build.gradle @@ -0,0 +1,14 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlinx-serialization' + +ext { + extName = 'Brewing Scans' + pkgNameSuffix = 'en.brewingscans' + extClass = '.BrewingScans' + extVersionCode = 1 + libVersion = '1.2' + containsNsfw = true +} + +apply from: "$rootDir/common.gradle" diff --git a/src/en/brewingscans/res/mipmap-hdpi/ic_launcher.png b/src/en/brewingscans/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 000000000..6f484fa6d Binary files /dev/null and b/src/en/brewingscans/res/mipmap-hdpi/ic_launcher.png differ diff --git a/src/en/brewingscans/res/mipmap-mdpi/ic_launcher.png b/src/en/brewingscans/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 000000000..8c921e48e Binary files /dev/null and b/src/en/brewingscans/res/mipmap-mdpi/ic_launcher.png differ diff --git a/src/en/brewingscans/res/mipmap-xhdpi/ic_launcher.png b/src/en/brewingscans/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 000000000..cd489c562 Binary files /dev/null and b/src/en/brewingscans/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/src/en/brewingscans/res/mipmap-xxhdpi/ic_launcher.png b/src/en/brewingscans/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 000000000..25e1bc7eb Binary files /dev/null and b/src/en/brewingscans/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/src/en/brewingscans/res/mipmap-xxxhdpi/ic_launcher.png b/src/en/brewingscans/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 000000000..623bc5994 Binary files /dev/null and b/src/en/brewingscans/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/src/en/brewingscans/res/web_hi_res_512.png b/src/en/brewingscans/res/web_hi_res_512.png new file mode 100644 index 000000000..d78b6769f Binary files /dev/null and b/src/en/brewingscans/res/web_hi_res_512.png differ diff --git a/src/en/brewingscans/src/eu/kanade/tachiyomi/extension/en/brewingscans/BrewingScans.kt b/src/en/brewingscans/src/eu/kanade/tachiyomi/extension/en/brewingscans/BrewingScans.kt new file mode 100644 index 000000000..30582e5e5 --- /dev/null +++ b/src/en/brewingscans/src/eu/kanade/tachiyomi/extension/en/brewingscans/BrewingScans.kt @@ -0,0 +1,107 @@ +package eu.kanade.tachiyomi.extension.en.brewingscans + +import eu.kanade.tachiyomi.annotations.Nsfw +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 kotlinx.serialization.decodeFromString +import kotlinx.serialization.json.Json +import okhttp3.Response +import uy.kohesive.injekt.injectLazy + +@Nsfw class BrewingScans : HttpSource() { + override val lang = "en" + + override val name = "Brewing Scans" + + override val baseUrl = "https://www.brewingscans.com" + + override val supportsLatest = false + + private val json by injectLazy() + + override fun popularMangaRequest(page: Int) = + GET("$baseUrl/api/series", headers) + + // Request the frontend URL for the webview + override fun mangaDetailsRequest(manga: SManga) = + GET("$baseUrl/menu/${manga.url}", headers) + + override fun chapterListRequest(manga: SManga) = + GET("$baseUrl/api/series/${manga.url}", headers) + + override fun pageListRequest(chapter: SChapter) = + GET("$baseUrl/api/series/${chapter.url}", headers) + + override fun popularMangaParse(response: Response) = + response.toMangasPage { sortedByDescending { it.view_count } } + + override fun pageListParse(response: Response) = + json.decodeFromString>(response.body!!.string()) + .mapIndexed { idx, url -> Page(idx, "", url) } + + override fun fetchSearchManga(page: Int, query: String, filters: FilterList) = + client.newCall(popularMangaRequest(page)).asObservableSuccess().map { res -> + res.toMangasPage { filter { it.title.contains(query, true) } } + }!! + + override fun fetchMangaDetails(manga: SManga) = + client.newCall(chapterListRequest(manga)).asObservableSuccess().map { res -> + val series = json.decodeFromString(res.body!!.string()) + manga.description = series.description + manga.author = series.author + manga.artist = series.artist + manga.genre = series.genres?.joinToString() + manga.status = SManga.UNKNOWN + manga.initialized = true + return@map manga + }!! + + override fun fetchChapterList(manga: SManga) = + client.newCall(chapterListRequest(manga)).asObservableSuccess().map { res -> + json.decodeFromString(res.body!!.string()).chapters.map { + SChapter.create().apply { + url = "${manga.url}/chapter/${it.key}" + chapter_number = it.key.toFloat() + name = it.value + } + } + }!! + + private inline fun Response.toMangasPage( + crossinline func: Collection.() -> List) = + json.decodeFromString>(body!!.string()) + .values.func().map { + SManga.create().apply { + url = it.id!! + thumbnail_url = it.cover + title = it.title + } + }.let { MangasPage(it, false) } + + override fun latestUpdatesRequest(page: Int) = + throw UnsupportedOperationException("Not used!") + + override fun searchMangaRequest(page: Int, query: String, filters: FilterList) = + throw UnsupportedOperationException("Not used!") + + override fun latestUpdatesParse(response: Response) = + throw UnsupportedOperationException("Not used!") + + override fun searchMangaParse(response: Response) = + throw UnsupportedOperationException("Not used!") + + override fun mangaDetailsParse(response: Response) = + throw UnsupportedOperationException("Not used!") + + override fun chapterListParse(response: Response) = + throw UnsupportedOperationException("Not used!") + + override fun imageUrlParse(response: Response) = + throw UnsupportedOperationException("Not used!") +} diff --git a/src/en/brewingscans/src/eu/kanade/tachiyomi/extension/en/brewingscans/BrewingSeries.kt b/src/en/brewingscans/src/eu/kanade/tachiyomi/extension/en/brewingscans/BrewingSeries.kt new file mode 100644 index 000000000..a98badf0a --- /dev/null +++ b/src/en/brewingscans/src/eu/kanade/tachiyomi/extension/en/brewingscans/BrewingSeries.kt @@ -0,0 +1,18 @@ +package eu.kanade.tachiyomi.extension.en.brewingscans + +@kotlinx.serialization.Serializable +data class BrewingSeries( + val id: String? = null, + val title: String, + val description: String, + val view_count: Int, + val age: String, + val chapters: Map, + val author: String? = null, + val artist: String? = null, + val genres: List? = null +) { + val cover by lazy { + if (id == null) null else "https://brewingscans.b-cdn.net/covers/${id}_cover.jpg" + } +}