diff --git a/multisrc/overrides/po2scans/apairof2/res/mipmap-hdpi/ic_launcher.png b/multisrc/overrides/po2scans/apairof2/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 000000000..228282d2f Binary files /dev/null and b/multisrc/overrides/po2scans/apairof2/res/mipmap-hdpi/ic_launcher.png differ diff --git a/multisrc/overrides/po2scans/apairof2/res/mipmap-mdpi/ic_launcher.png b/multisrc/overrides/po2scans/apairof2/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 000000000..c7b5f56ec Binary files /dev/null and b/multisrc/overrides/po2scans/apairof2/res/mipmap-mdpi/ic_launcher.png differ diff --git a/multisrc/overrides/po2scans/apairof2/res/mipmap-xhdpi/ic_launcher.png b/multisrc/overrides/po2scans/apairof2/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 000000000..e80a721cf Binary files /dev/null and b/multisrc/overrides/po2scans/apairof2/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/multisrc/overrides/po2scans/apairof2/res/mipmap-xxhdpi/ic_launcher.png b/multisrc/overrides/po2scans/apairof2/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 000000000..4384c19a4 Binary files /dev/null and b/multisrc/overrides/po2scans/apairof2/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/multisrc/overrides/po2scans/apairof2/res/mipmap-xxxhdpi/ic_launcher.png b/multisrc/overrides/po2scans/apairof2/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 000000000..367670860 Binary files /dev/null and b/multisrc/overrides/po2scans/apairof2/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/multisrc/overrides/po2scans/apairof2/src/APairOf2.kt b/multisrc/overrides/po2scans/apairof2/src/APairOf2.kt new file mode 100644 index 000000000..a7fc0e2eb --- /dev/null +++ b/multisrc/overrides/po2scans/apairof2/src/APairOf2.kt @@ -0,0 +1,12 @@ +package eu.kanade.tachiyomi.extension.en.apairof2 + +import eu.kanade.tachiyomi.multisrc.po2scans.PO2Scans +import eu.kanade.tachiyomi.network.interceptor.rateLimit + +class APairOf2 : PO2Scans("A Pair Of 2+", "https://po2scans.com", "en") { + override val versionId = 2 + + override val client = super.client.newBuilder() + .rateLimit(4) + .build() +} diff --git a/src/en/apairof2/AndroidManifest.xml b/multisrc/overrides/po2scans/default/AndroidManifest.xml similarity index 78% rename from src/en/apairof2/AndroidManifest.xml rename to multisrc/overrides/po2scans/default/AndroidManifest.xml index fa0c911c9..4a90e33e8 100644 --- a/src/en/apairof2/AndroidManifest.xml +++ b/multisrc/overrides/po2scans/default/AndroidManifest.xml @@ -3,7 +3,7 @@ @@ -14,9 +14,9 @@ + android:scheme="${SOURCESCHEME}" /> diff --git a/multisrc/overrides/po2scans/default/additional.gradle b/multisrc/overrides/po2scans/default/additional.gradle new file mode 100644 index 000000000..081900adc --- /dev/null +++ b/multisrc/overrides/po2scans/default/additional.gradle @@ -0,0 +1,3 @@ +dependencies { + implementation(project(":lib:dataimage")) +} diff --git a/multisrc/overrides/po2scans/sadscans/res/mipmap-hdpi/ic_launcher.png b/multisrc/overrides/po2scans/sadscans/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 000000000..524d12588 Binary files /dev/null and b/multisrc/overrides/po2scans/sadscans/res/mipmap-hdpi/ic_launcher.png differ diff --git a/multisrc/overrides/po2scans/sadscans/res/mipmap-mdpi/ic_launcher.png b/multisrc/overrides/po2scans/sadscans/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 000000000..e33fac7ee Binary files /dev/null and b/multisrc/overrides/po2scans/sadscans/res/mipmap-mdpi/ic_launcher.png differ diff --git a/multisrc/overrides/po2scans/sadscans/res/mipmap-xhdpi/ic_launcher.png b/multisrc/overrides/po2scans/sadscans/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 000000000..1844eb757 Binary files /dev/null and b/multisrc/overrides/po2scans/sadscans/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/multisrc/overrides/po2scans/sadscans/res/mipmap-xxhdpi/ic_launcher.png b/multisrc/overrides/po2scans/sadscans/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 000000000..43a0ae8c6 Binary files /dev/null and b/multisrc/overrides/po2scans/sadscans/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/multisrc/overrides/po2scans/sadscans/res/mipmap-xxxhdpi/ic_launcher.png b/multisrc/overrides/po2scans/sadscans/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 000000000..ad7340db9 Binary files /dev/null and b/multisrc/overrides/po2scans/sadscans/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/src/en/apairof2/src/eu/kanade/tachiyomi/extension/en/apairof2/APairOf2.kt b/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/po2scans/PO2Scans.kt similarity index 51% rename from src/en/apairof2/src/eu/kanade/tachiyomi/extension/en/apairof2/APairOf2.kt rename to multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/po2scans/PO2Scans.kt index 9b8aa149e..aa8fb72ed 100644 --- a/src/en/apairof2/src/eu/kanade/tachiyomi/extension/en/apairof2/APairOf2.kt +++ b/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/po2scans/PO2Scans.kt @@ -1,80 +1,64 @@ -package eu.kanade.tachiyomi.extension.en.apairof2 +package eu.kanade.tachiyomi.multisrc.po2scans import eu.kanade.tachiyomi.lib.dataimage.DataImageInterceptor import eu.kanade.tachiyomi.lib.dataimage.dataImageAsUrl import eu.kanade.tachiyomi.network.GET -import eu.kanade.tachiyomi.network.interceptor.rateLimit 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.ParsedHttpSource -import okhttp3.Headers -import okhttp3.OkHttpClient -import okhttp3.Request import org.jsoup.nodes.Document import org.jsoup.nodes.Element import rx.Observable import java.text.SimpleDateFormat import java.util.Locale -class APairOf2 : ParsedHttpSource() { - - override val name = "A Pair of 2+" - - override val baseUrl = "https://po2scans.com" - - override val lang = "en" +abstract class PO2Scans( + override val name: String, + override val baseUrl: String, + override val lang: String, + private val dateFormat: SimpleDateFormat = SimpleDateFormat("dd MMMM, yy", Locale.ENGLISH), +) : ParsedHttpSource() { override val supportsLatest = true - override val versionId = 2 - - override val client: OkHttpClient = network.cloudflareClient.newBuilder() + override val client = network.cloudflareClient.newBuilder() .addInterceptor(DataImageInterceptor()) - .rateLimit(4) .build() - override fun headersBuilder(): Headers.Builder = super.headersBuilder() + override fun headersBuilder() = super.headersBuilder() .add("Referer", "$baseUrl/") // popular - override fun popularMangaRequest(page: Int): Request { - return GET("$baseUrl/series", headers) - } + override fun popularMangaRequest(page: Int) = GET("$baseUrl/series", headers) override fun popularMangaSelector() = "div.series-list" - override fun popularMangaFromElement(element: Element): SManga { - return SManga.create().apply { - title = element.select("div > h2").text() - url = element.select("div > a").attr("href").let { "/$it" } - thumbnail_url = element.select("img").attr("abs:data-src") - } + override fun popularMangaFromElement(element: Element) = SManga.create().apply { + setUrlWithoutDomain(element.selectFirst("div > a")!!.absUrl("href")) + title = element.selectFirst("div > h2")!!.text() + thumbnail_url = element.selectFirst("img")?.absUrl("data-src") } // TODO: add page selectors & url parameters when site have enough series for pagination override fun popularMangaNextPageSelector() = null // latest - override fun latestUpdatesRequest(page: Int): Request { - return GET(baseUrl, headers) - } + override fun latestUpdatesRequest(page: Int) = GET(baseUrl, headers) override fun latestUpdatesSelector() = "div.chap" - override fun latestUpdatesFromElement(element: Element): SManga { - return SManga.create().apply { - element.select("div.chap-title a").let { it -> - url = it.attr("href").let { "/$it" } - title = it.text() - } - thumbnail_url = element.select("img").attr("abs:data-src") + override fun latestUpdatesFromElement(element: Element) = SManga.create().apply { + element.selectFirst("div.chap-title a")!!.let { + setUrlWithoutDomain(it.absUrl("href")) + title = it.text() } + thumbnail_url = element.selectFirst("img")?.absUrl("data-src") } - override fun latestUpdatesNextPageSelector() = popularMangaSelector() + override fun latestUpdatesNextPageSelector() = popularMangaNextPageSelector() // search override fun fetchSearchManga(page: Int, query: String, filters: FilterList): Observable { @@ -83,15 +67,15 @@ class APairOf2 : ParsedHttpSource() { } val url = "/series/${query.substringAfter(SLUG_SEARCH_PREFIX)}" - return fetchMangaDetails(SManga.create().apply { this.url = url }).map { - it.url = url - MangasPage(listOf(it), false) - } + return fetchMangaDetails(SManga.create().apply { this.url = url }) + .map { + it.url = url + MangasPage(listOf(it), false) + } } - override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request { - return GET("$baseUrl/series?search=$query", headers) - } + override fun searchMangaRequest(page: Int, query: String, filters: FilterList) = + GET("$baseUrl/series?search=$query", headers) override fun searchMangaSelector() = popularMangaSelector() @@ -111,39 +95,33 @@ class APairOf2 : ParsedHttpSource() { } } - private fun String.parseStatus(): Int { - return when { - this.contains("ongoing", true) -> SManga.ONGOING - this.contains("complete", true) -> SManga.COMPLETED - else -> SManga.UNKNOWN - } - } - // chapter list override fun chapterListSelector() = "div.chap" - override fun chapterFromElement(element: Element): SChapter { - return SChapter.create().apply { - element.select("a").let { a -> - url = a.attr("href").let { "/$it" } - name = a.text() - } - date_upload = parseDate(element.select("div > div > span:nth-child(2)").text()) + override fun chapterFromElement(element: Element) = SChapter.create().apply { + element.selectFirst("a")!!.let { + setUrlWithoutDomain(it.absUrl("href")) + name = it.text() } - } - - private fun parseDate(dateStr: String): Long { - return runCatching { DATE_FORMATTER.parse(dateStr)?.time } - .getOrNull() ?: 0L + date_upload = parseDate(element.select("div > div > span:nth-child(2)").text()) } // page list - override fun pageListParse(document: Document): List { - return document.select(".swiper-slide img").mapIndexed { index, img -> - Page( - index = index, - imageUrl = img.imgAttr(), - ) + override fun pageListParse(document: Document) = + document.select(".swiper-slide img").mapIndexed { index, img -> + Page(index, imageUrl = img.imgAttr()) + } + + override fun imageUrlParse(document: Document) = throw UnsupportedOperationException() + + private val statusOngoing = listOf("ongoing", "devam ediyor") + private val statusCompleted = listOf("complete", "tamamlandı", "bitti") + + private fun String.parseStatus(): Int { + return when (this.lowercase()) { + in statusOngoing -> SManga.ONGOING + in statusCompleted -> SManga.COMPLETED + else -> SManga.UNKNOWN } } @@ -153,15 +131,11 @@ class APairOf2 : ParsedHttpSource() { else -> dataImageAsUrl("src") } - override fun imageUrlParse(document: Document): String { - throw UnsupportedOperationException() - } + private fun parseDate(dateStr: String) = + runCatching { dateFormat.parse(dateStr)!!.time } + .getOrDefault(0L) companion object { - private val DATE_FORMATTER by lazy { - SimpleDateFormat("dd MMMM, yy", Locale.ENGLISH) - } - const val SLUG_SEARCH_PREFIX = "slug:" } } diff --git a/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/po2scans/PO2ScansGenerator.kt b/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/po2scans/PO2ScansGenerator.kt new file mode 100644 index 000000000..769fc2ee8 --- /dev/null +++ b/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/po2scans/PO2ScansGenerator.kt @@ -0,0 +1,24 @@ +package eu.kanade.tachiyomi.multisrc.po2scans + +import generator.ThemeSourceData.SingleLang +import generator.ThemeSourceGenerator + +class PO2ScansGenerator : ThemeSourceGenerator { + override val themePkg = "po2scans" + + override val themeClass = "PO2Scans" + + override val baseVersionCode = 1 + + override val sources = listOf( + SingleLang("A Pair Of 2+", "https://po2scans.com", "en", className = "APairOf2", overrideVersionCode = 31), + SingleLang("Sadscans", "https://sadscans.com", "tr"), + ) + + companion object { + @JvmStatic + fun main(args: Array) { + PO2ScansGenerator().createAll() + } + } +} diff --git a/src/en/apairof2/src/eu/kanade/tachiyomi/extension/en/apairof2/APairOf2UrlActivity.kt b/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/po2scans/PO2ScansUrlActivity.kt similarity index 74% rename from src/en/apairof2/src/eu/kanade/tachiyomi/extension/en/apairof2/APairOf2UrlActivity.kt rename to multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/po2scans/PO2ScansUrlActivity.kt index 8ba124982..f260ea234 100644 --- a/src/en/apairof2/src/eu/kanade/tachiyomi/extension/en/apairof2/APairOf2UrlActivity.kt +++ b/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/po2scans/PO2ScansUrlActivity.kt @@ -1,4 +1,4 @@ -package eu.kanade.tachiyomi.extension.en.apairof2 +package eu.kanade.tachiyomi.multisrc.po2scans import android.app.Activity import android.content.ActivityNotFoundException @@ -7,7 +7,7 @@ import android.os.Bundle import android.util.Log import kotlin.system.exitProcess -class APairOf2UrlActivity : Activity() { +class PO2ScansUrlActivity : Activity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val pathSegments = intent?.data?.pathSegments @@ -15,17 +15,17 @@ class APairOf2UrlActivity : Activity() { val slug = pathSegments[1] val mainIntent = Intent().apply { action = "eu.kanade.tachiyomi.SEARCH" - putExtra("query", "${APairOf2.SLUG_SEARCH_PREFIX}$slug") + putExtra("query", "${PO2Scans.SLUG_SEARCH_PREFIX}$slug") putExtra("filter", packageName) } try { startActivity(mainIntent) } catch (e: ActivityNotFoundException) { - Log.e("APairOf2UrlActivity", e.toString()) + Log.e("PO2ScansUrlActivity", "Could not start activity", e) } } else { - Log.e("APairOf2UrlActivity", "could not parse uri from intent $intent") + Log.e("PO2ScansUrlActivity", "could not parse URI from intent $intent") } finish() diff --git a/src/en/apairof2/build.gradle b/src/en/apairof2/build.gradle deleted file mode 100644 index 3d3560c90..000000000 --- a/src/en/apairof2/build.gradle +++ /dev/null @@ -1,11 +0,0 @@ -ext { - extName = 'A Pair of 2+' - extClass = '.APairOf2' - extVersionCode = 31 -} - -apply from: "$rootDir/common.gradle" - -dependencies { - implementation project(':lib:dataimage') -} diff --git a/src/en/apairof2/res/mipmap-hdpi/ic_launcher.png b/src/en/apairof2/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index e967aa5a8..000000000 Binary files a/src/en/apairof2/res/mipmap-hdpi/ic_launcher.png and /dev/null differ diff --git a/src/en/apairof2/res/mipmap-mdpi/ic_launcher.png b/src/en/apairof2/res/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index 6124280fe..000000000 Binary files a/src/en/apairof2/res/mipmap-mdpi/ic_launcher.png and /dev/null differ diff --git a/src/en/apairof2/res/mipmap-xhdpi/ic_launcher.png b/src/en/apairof2/res/mipmap-xhdpi/ic_launcher.png deleted file mode 100644 index e1c7dfe5b..000000000 Binary files a/src/en/apairof2/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ diff --git a/src/en/apairof2/res/mipmap-xxhdpi/ic_launcher.png b/src/en/apairof2/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index a59222004..000000000 Binary files a/src/en/apairof2/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ diff --git a/src/en/apairof2/res/mipmap-xxxhdpi/ic_launcher.png b/src/en/apairof2/res/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index cd9c91db7..000000000 Binary files a/src/en/apairof2/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ