diff --git a/multisrc/overrides/foolslide/phoenixscans/res/mipmap-hdpi/ic_launcher.png b/multisrc/overrides/foolslide/phoenixscans/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index 11bcdec79..000000000 Binary files a/multisrc/overrides/foolslide/phoenixscans/res/mipmap-hdpi/ic_launcher.png and /dev/null differ diff --git a/multisrc/overrides/foolslide/phoenixscans/res/mipmap-mdpi/ic_launcher.png b/multisrc/overrides/foolslide/phoenixscans/res/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index 2ec1ffe89..000000000 Binary files a/multisrc/overrides/foolslide/phoenixscans/res/mipmap-mdpi/ic_launcher.png and /dev/null differ diff --git a/multisrc/overrides/foolslide/phoenixscans/res/mipmap-xhdpi/ic_launcher.png b/multisrc/overrides/foolslide/phoenixscans/res/mipmap-xhdpi/ic_launcher.png deleted file mode 100644 index 6c0af60bd..000000000 Binary files a/multisrc/overrides/foolslide/phoenixscans/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ diff --git a/multisrc/overrides/foolslide/phoenixscans/res/mipmap-xxhdpi/ic_launcher.png b/multisrc/overrides/foolslide/phoenixscans/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index 1043cf5c8..000000000 Binary files a/multisrc/overrides/foolslide/phoenixscans/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ diff --git a/multisrc/overrides/foolslide/phoenixscans/res/mipmap-xxxhdpi/ic_launcher.png b/multisrc/overrides/foolslide/phoenixscans/res/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index ce097eca8..000000000 Binary files a/multisrc/overrides/foolslide/phoenixscans/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ diff --git a/multisrc/overrides/foolslide/phoenixscans/res/web_hi_res_512.png b/multisrc/overrides/foolslide/phoenixscans/res/web_hi_res_512.png deleted file mode 100644 index b8409ca6d..000000000 Binary files a/multisrc/overrides/foolslide/phoenixscans/res/web_hi_res_512.png and /dev/null differ diff --git a/multisrc/overrides/foolslide/phoenixscans/src/PhoenixScans.kt b/multisrc/overrides/foolslide/phoenixscans/src/PhoenixScans.kt deleted file mode 100644 index 8d8dfb693..000000000 --- a/multisrc/overrides/foolslide/phoenixscans/src/PhoenixScans.kt +++ /dev/null @@ -1,5 +0,0 @@ -package eu.kanade.tachiyomi.extension.it.phoenixscans - -import eu.kanade.tachiyomi.multisrc.foolslide.FoolSlide - -class PhoenixScans : FoolSlide("The Phoenix Scans", "https://www.phoenixscans.com", "it", "/reader") diff --git a/multisrc/overrides/pizzareader/default/res/mipmap-hdpi/ic_launcher.png b/multisrc/overrides/pizzareader/default/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 000000000..9f18fceed Binary files /dev/null and b/multisrc/overrides/pizzareader/default/res/mipmap-hdpi/ic_launcher.png differ diff --git a/multisrc/overrides/pizzareader/default/res/mipmap-mdpi/ic_launcher.png b/multisrc/overrides/pizzareader/default/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 000000000..d3ed60e90 Binary files /dev/null and b/multisrc/overrides/pizzareader/default/res/mipmap-mdpi/ic_launcher.png differ diff --git a/multisrc/overrides/pizzareader/default/res/mipmap-xhdpi/ic_launcher.png b/multisrc/overrides/pizzareader/default/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 000000000..32b37d32f Binary files /dev/null and b/multisrc/overrides/pizzareader/default/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/multisrc/overrides/pizzareader/default/res/mipmap-xxhdpi/ic_launcher.png b/multisrc/overrides/pizzareader/default/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 000000000..3bc94d763 Binary files /dev/null and b/multisrc/overrides/pizzareader/default/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/multisrc/overrides/pizzareader/default/res/mipmap-xxxhdpi/ic_launcher.png b/multisrc/overrides/pizzareader/default/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 000000000..a476fb1d1 Binary files /dev/null and b/multisrc/overrides/pizzareader/default/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/multisrc/overrides/pizzareader/default/res/web_hi_res_512.png b/multisrc/overrides/pizzareader/default/res/web_hi_res_512.png new file mode 100644 index 000000000..0c7454f00 Binary files /dev/null and b/multisrc/overrides/pizzareader/default/res/web_hi_res_512.png differ diff --git a/multisrc/overrides/pizzareader/phoenixscans/src/PhoenixScans.kt b/multisrc/overrides/pizzareader/phoenixscans/src/PhoenixScans.kt new file mode 100644 index 000000000..260fb51fa --- /dev/null +++ b/multisrc/overrides/pizzareader/phoenixscans/src/PhoenixScans.kt @@ -0,0 +1,7 @@ +package eu.kanade.tachiyomi.extension.it.phoenixscans + +import eu.kanade.tachiyomi.multisrc.pizzareader.PizzaReader + +class PhoenixScans : PizzaReader("Phoenix Scans", "https://www.phoenixscans.com", "it") { + override val versionId = 2 +} diff --git a/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/foolslide/FoolSlideGenerator.kt b/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/foolslide/FoolSlideGenerator.kt index 6f75ee656..0495a12ac 100644 --- a/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/foolslide/FoolSlideGenerator.kt +++ b/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/foolslide/FoolSlideGenerator.kt @@ -35,7 +35,6 @@ class FoolSlideGenerator : ThemeSourceGenerator { SingleLang("Baixar Hentai", "https://leitura.baixarhentai.net", "pt-BR", isNsfw = true, overrideVersionCode = 3), MultiLang("HNI-Scantrad", "https://hni-scantrad.com", listOf("fr", "en"), className = "HNIScantradFactory", pkgName = "hniscantrad", overrideVersionCode = 1), SingleLang("QuegnaReader", "http://pignaquegna.altervista.org", "it"), - SingleLang("The Phoenix Scans", "https://www.phoenixscans.com", "it", className = "PhoenixScans"), SingleLang("GTO The Great Site", "https://www.gtothegreatsite.net", "it", className = "GTO"), SingleLang("NIFTeam", "http://read-nifteam.info", "it"), SingleLang("TuttoAnimeManga", "https://tuttoanimemanga.net", "it"), @@ -44,7 +43,7 @@ class FoolSlideGenerator : ThemeSourceGenerator { SingleLang("Mabushimajo", "http://mabushimajo.com", "tr"), SingleLang("Hyakuro", "https://hyakuro.com", "en"), SingleLang("Le Cercle du Scan", "https://lel.lecercleduscan.com", "fr", className = "LeCercleDuScan", overrideVersionCode = 1), - SingleLang("LetItGo Scans", "https://reader.letitgo.scans.today", "en", overrideVersionCode = 1) + SingleLang("LetItGo Scans", "https://reader.letitgo.scans.today", "en", overrideVersionCode = 1), ) companion object { diff --git a/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/pizzareader/PizzaReader.kt b/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/pizzareader/PizzaReader.kt new file mode 100644 index 000000000..035fc4016 --- /dev/null +++ b/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/pizzareader/PizzaReader.kt @@ -0,0 +1,103 @@ +package eu.kanade.tachiyomi.multisrc.pizzareader + +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 okhttp3.Headers +import okhttp3.Request +import okhttp3.Response +import org.json.JSONObject +import rx.Observable + +abstract class PizzaReader( + override val name: String, + override val baseUrl: String, + override val lang: String, + private val apiPath: String = "/api" +) : HttpSource() { + + override val supportsLatest = true + + open val apiUrl by lazy { "$baseUrl$apiPath" } + + override fun headersBuilder() = Headers.Builder().apply { + add("Referer", baseUrl) + } + + override fun popularMangaRequest(page: Int) = + GET("$apiUrl/comics", headers) + + override fun popularMangaParse(response: Response) = + MangasPage( + JSONObject(response.asString()).run { + val arr = getJSONArray("comics") + (0 until arr.length()).map { + SManga.create().fromJSON(arr.getJSONObject(it)) + } + }, + false + ) + + override fun searchMangaRequest(page: Int, query: String, filters: FilterList) = + GET("$apiUrl/search/$query", headers) + + override fun searchMangaParse(response: Response) = + MangasPage( + JSONObject(response.asString()).run { + val arr = getJSONArray("comics") + (0 until arr.length()).map { + SManga.create().fromJSON(arr.getJSONObject(it)) + } + }, + false + ) + + // TODO + override fun latestUpdatesRequest(page: Int): Request = + throw UnsupportedOperationException("Not used") + + override fun latestUpdatesParse(response: Response): MangasPage = + throw UnsupportedOperationException("Not used") + + // Workaround to allow "Open in browser" to use the real URL + override fun fetchMangaDetails(manga: SManga): Observable<SManga> = + client.newCall(chapterListRequest(manga)).asObservableSuccess() + .map { mangaDetailsParse(it).apply { initialized = true } } + + // Return the real URL for "Open in browser" + override fun mangaDetailsRequest(manga: SManga) = + GET("$baseUrl${manga.url}", headers) + + override fun mangaDetailsParse(response: Response): SManga = + SManga.create().fromJSON(JSONObject(response.asString()).getJSONObject("comic")) + + override fun chapterListRequest(manga: SManga) = GET("$apiUrl${manga.url}", headers) + + override fun chapterListParse(response: Response) = + JSONObject(response.asString()).getJSONObject("comic").run { + val arr = getJSONArray("chapters") + (0 until arr.length()).map { + SChapter.create().fromJSON(arr.getJSONObject(it)) + } + } + + override fun pageListRequest(chapter: SChapter) = + GET("$apiUrl${chapter.url}", headers) + + override fun pageListParse(response: Response) = + JSONObject(response.asString()).getJSONObject("chapter").run { + val arr = getJSONArray("pages") + (0 until arr.length()).map { + Page(it, "", arr.getString(it)) + } + } + + override fun imageUrlParse(response: Response): String = + throw UnsupportedOperationException("Not used") + +} diff --git a/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/pizzareader/PizzaReaderExtensions.kt b/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/pizzareader/PizzaReaderExtensions.kt new file mode 100644 index 000000000..ff5fd54cc --- /dev/null +++ b/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/pizzareader/PizzaReaderExtensions.kt @@ -0,0 +1,94 @@ +package eu.kanade.tachiyomi.multisrc.pizzareader + +import eu.kanade.tachiyomi.source.model.SChapter +import eu.kanade.tachiyomi.source.model.SManga +import okhttp3.Response +import org.json.JSONArray +import org.json.JSONObject +import java.text.DecimalFormat +// import java.time.OffsetDateTime +import java.text.SimpleDateFormat +import java.util.Locale + +/** Returns the body of a response as a `String`. */ +fun Response.asString(): String = body!!.string() + +/** + * Formats the number according to [fmt]. + * + * @param fmt A [DecimalFormat] string. + * @return A string representation of the number. + */ +fun Number.format(fmt: String): String = DecimalFormat(fmt).format(this) + +/** + * Joins each value of a given [field] of the array using [sep]. + * + * @param field The index of a [JSONArray]. + * When its type is [String], it is treated as the key of a [JSONObject]. + * @param sep The separator used to join the array. + * @return The joined string, or `null` if the array is empty. + */ +fun JSONArray.joinField(field: Int, sep: String = ", ") = + length().takeIf { it != 0 }?.run { + (0 until this).mapNotNull { + val obj = get(it) + if (obj != null && obj.toString() != "null") getJSONArray(it).getString(field) + else null + }.joinToString(sep) + } + +/** + * Joins each value of a given [field] of the array using [sep]. + * + * @param field The key of a [JSONObject]. + * @param sep The separator used to join the array. + * @return The joined string, or `null` if the array is empty. + */ +fun JSONArray.joinField(field: String, sep: String = ", ") = + length().takeIf { it != 0 }?.run { + (0 until this).mapNotNull { + val obj = get(it) + if (obj != null && obj.toString() != "null") getJSONObject(it).getString(field) + else null + }.joinToString(sep) + } + +/** + * Creates a [SManga] by parsing a [JSONObject]. + * + * @param obj The object containing the manga info. + */ +fun SManga.fromJSON(obj: JSONObject) = apply { + url = obj.getString("url") + title = obj.getString("title") + description = obj.getString("description") + thumbnail_url = obj.getString("thumbnail") + author = obj.getString("author") + artist = obj.getString("artist") + genre = obj.getJSONArray("genres").joinField("slug") + status = when (obj.getString("status").substring(0, 7)) { + "In cors" -> SManga.ONGOING + "On goin" -> SManga.ONGOING + "Complet" -> SManga.COMPLETED + "Conclus" -> SManga.COMPLETED + "Conclud" -> SManga.COMPLETED + "Licenzi" -> SManga.LICENSED + "License" -> SManga.LICENSED + else -> SManga.UNKNOWN + } +} + +/** + * Creates a [SChapter] by parsing a [JSONObject]. + * + * @param obj The object containing the chapter info. + */ +fun SChapter.fromJSON(obj: JSONObject) = apply { + url = obj.getString("url") + chapter_number = obj.optString("chapter", "-1").toFloat() + "0.${obj.optInt("subchapter", 0)}".toFloat() + // date_upload = OffsetDateTime.parse(obj.getString("published_on")).toEpochSecond() // API 26 + date_upload = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSSSS", Locale.ITALY).parse(obj.getString("published_on"))?.time ?: 0L + scanlator = obj.getJSONArray("teams").joinField("name", " & ") + name = obj.getString("full_title") +} diff --git a/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/pizzareader/PizzaReaderGenerator.kt b/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/pizzareader/PizzaReaderGenerator.kt new file mode 100644 index 000000000..718f4f3ce --- /dev/null +++ b/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/pizzareader/PizzaReaderGenerator.kt @@ -0,0 +1,27 @@ +package eu.kanade.tachiyomi.multisrc.pizzareader + +// import generator.ThemeSourceData.MultiLang +import generator.ThemeSourceData.SingleLang +import generator.ThemeSourceGenerator + +class PizzaReaderGenerator : ThemeSourceGenerator { + + override val themePkg = "pizzareader" + + override val themeClass = "PizzaReader" + + override val baseVersionCode: Int = 0 + + override val sources = listOf( + SingleLang("Phoenix Scans", "https://www.phoenixscans.com", "it", className = "PhoenixScans", overrideVersionCode = 4), + // Current migrating to this CMS: + // SingleLang("GTO The Great Site", "https://reader.gtothegreatsite.net", "it", className = "GTO", overrideVersionCode = 4), + ) + + companion object { + @JvmStatic + fun main(args: Array<String>) { + PizzaReaderGenerator().createAll() + } + } +}