diff --git a/lib-multisrc/po2scans/build.gradle.kts b/lib-multisrc/po2scans/build.gradle.kts deleted file mode 100644 index cc2397918..000000000 --- a/lib-multisrc/po2scans/build.gradle.kts +++ /dev/null @@ -1,9 +0,0 @@ -plugins { - id("lib-multisrc") -} - -baseVersionCode = 1 - -dependencies { - api(project(":lib:dataimage")) -} diff --git a/lib-multisrc/po2scans/src/eu/kanade/tachiyomi/multisrc/po2scans/PO2Scans.kt b/lib-multisrc/po2scans/src/eu/kanade/tachiyomi/multisrc/po2scans/PO2Scans.kt deleted file mode 100644 index aa8fb72ed..000000000 --- a/lib-multisrc/po2scans/src/eu/kanade/tachiyomi/multisrc/po2scans/PO2Scans.kt +++ /dev/null @@ -1,141 +0,0 @@ -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.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 org.jsoup.nodes.Document -import org.jsoup.nodes.Element -import rx.Observable -import java.text.SimpleDateFormat -import java.util.Locale - -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 client = network.cloudflareClient.newBuilder() - .addInterceptor(DataImageInterceptor()) - .build() - - override fun headersBuilder() = super.headersBuilder() - .add("Referer", "$baseUrl/") - - // popular - override fun popularMangaRequest(page: Int) = GET("$baseUrl/series", headers) - - override fun popularMangaSelector() = "div.series-list" - - 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) = GET(baseUrl, headers) - - override fun latestUpdatesSelector() = "div.chap" - - 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() = popularMangaNextPageSelector() - - // search - override fun fetchSearchManga(page: Int, query: String, filters: FilterList): Observable { - if (!query.startsWith(SLUG_SEARCH_PREFIX)) { - return super.fetchSearchManga(page, query, filters) - } - - val url = "/series/${query.substringAfter(SLUG_SEARCH_PREFIX)}" - 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) = - GET("$baseUrl/series?search=$query", headers) - - override fun searchMangaSelector() = popularMangaSelector() - - override fun searchMangaFromElement(element: Element) = popularMangaFromElement(element) - - override fun searchMangaNextPageSelector() = popularMangaNextPageSelector() - - // manga details - override fun mangaDetailsParse(document: Document): SManga { - return SManga.create().apply { - title = document.selectFirst(".title")!!.text() - author = document.select(".author > span:nth-child(2)").text() - artist = author - status = document.select(".status > span:nth-child(2)").text().parseStatus() - description = document.select(".summary p").text() - thumbnail_url = document.select("div.series-image img").attr("abs:src") - } - } - - // chapter list - override fun chapterListSelector() = "div.chap" - - override fun chapterFromElement(element: Element) = SChapter.create().apply { - element.selectFirst("a")!!.let { - setUrlWithoutDomain(it.absUrl("href")) - name = it.text() - } - date_upload = parseDate(element.select("div > div > span:nth-child(2)").text()) - } - - // page list - 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 - } - } - - private fun Element.imgAttr(): String = when { - hasAttr("data-pagespeed-high-res-src") -> dataImageAsUrl("data-pagespeed-high-res-src") - hasAttr("data-pagespeed-lazy-src") -> dataImageAsUrl("data-pagespeed-lazy-src") - else -> dataImageAsUrl("src") - } - - private fun parseDate(dateStr: String) = - runCatching { dateFormat.parse(dateStr)!!.time } - .getOrDefault(0L) - - companion object { - const val SLUG_SEARCH_PREFIX = "slug:" - } -} diff --git a/src/en/apairof2/build.gradle b/src/en/apairof2/build.gradle deleted file mode 100644 index caae4a711..000000000 --- a/src/en/apairof2/build.gradle +++ /dev/null @@ -1,9 +0,0 @@ -ext { - extName = 'A Pair Of 2+' - extClass = '.APairOf2' - themePkg = 'po2scans' - baseUrl = 'https://po2scans.com' - overrideVersionCode = 31 -} - -apply from: "$rootDir/common.gradle" 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 228282d2f..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 c7b5f56ec..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 e80a721cf..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 4384c19a4..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 367670860..000000000 Binary files a/src/en/apairof2/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ diff --git a/src/en/apairof2/src/eu/kanade/tachiyomi/extension/en/apairof2/APairOf2.kt b/src/en/apairof2/src/eu/kanade/tachiyomi/extension/en/apairof2/APairOf2.kt deleted file mode 100644 index a7fc0e2eb..000000000 --- a/src/en/apairof2/src/eu/kanade/tachiyomi/extension/en/apairof2/APairOf2.kt +++ /dev/null @@ -1,12 +0,0 @@ -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/lib-multisrc/po2scans/AndroidManifest.xml b/src/tr/sadscans/AndroidManifest.xml similarity index 78% rename from lib-multisrc/po2scans/AndroidManifest.xml rename to src/tr/sadscans/AndroidManifest.xml index 4a90e33e8..731f3c27e 100644 --- a/lib-multisrc/po2scans/AndroidManifest.xml +++ b/src/tr/sadscans/AndroidManifest.xml @@ -3,7 +3,7 @@ @@ -14,9 +14,9 @@ + android:scheme="https" /> diff --git a/src/tr/sadscans/build.gradle b/src/tr/sadscans/build.gradle index 941a3e02d..b3b5363a6 100644 --- a/src/tr/sadscans/build.gradle +++ b/src/tr/sadscans/build.gradle @@ -1,9 +1,11 @@ ext { extName = 'Sadscans' extClass = '.Sadscans' - themePkg = 'po2scans' - baseUrl = 'https://sadscans.com' - overrideVersionCode = 0 + extVersionCode = 2 } apply from: "$rootDir/common.gradle" + +dependencies { + api(project(":lib:dataimage")) +} diff --git a/src/tr/sadscans/src/eu/kanade/tachiyomi/extension/tr/sadscans/Sadscans.kt b/src/tr/sadscans/src/eu/kanade/tachiyomi/extension/tr/sadscans/Sadscans.kt index 773e94b8b..2627416fe 100644 --- a/src/tr/sadscans/src/eu/kanade/tachiyomi/extension/tr/sadscans/Sadscans.kt +++ b/src/tr/sadscans/src/eu/kanade/tachiyomi/extension/tr/sadscans/Sadscans.kt @@ -1,5 +1,144 @@ package eu.kanade.tachiyomi.extension.tr.sadscans -import eu.kanade.tachiyomi.multisrc.po2scans.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.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 org.jsoup.nodes.Document +import org.jsoup.nodes.Element +import rx.Observable +import java.text.SimpleDateFormat +import java.util.Locale -class Sadscans : PO2Scans("Sadscans", "https://sadscans.com", "tr") +class Sadscans : ParsedHttpSource() { + + override val name = "Sadscans" + + override val baseUrl = "https://sadscans.com" + + override val lang = "tr" + + private val dateFormat = SimpleDateFormat("dd MMMM, yy", Locale.ENGLISH) + + override val supportsLatest = true + + override val client = network.cloudflareClient.newBuilder() + .addInterceptor(DataImageInterceptor()) + .build() + + override fun headersBuilder() = super.headersBuilder() + .add("Referer", "$baseUrl/") + + // popular + override fun popularMangaRequest(page: Int) = GET("$baseUrl/series", headers) + + override fun popularMangaSelector() = "div.series-list" + + 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) = GET(baseUrl, headers) + + override fun latestUpdatesSelector() = "div.chap" + + 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() = popularMangaNextPageSelector() + + // search + override fun fetchSearchManga(page: Int, query: String, filters: FilterList): Observable { + if (!query.startsWith(SLUG_SEARCH_PREFIX)) { + return super.fetchSearchManga(page, query, filters) + } + + val url = "/series/${query.substringAfter(SLUG_SEARCH_PREFIX)}" + 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) = + GET("$baseUrl/series?search=$query", headers) + + override fun searchMangaSelector() = popularMangaSelector() + + override fun searchMangaFromElement(element: Element) = popularMangaFromElement(element) + + override fun searchMangaNextPageSelector() = popularMangaNextPageSelector() + + // manga details + override fun mangaDetailsParse(document: Document): SManga { + return SManga.create().apply { + title = document.selectFirst(".title")!!.text() + author = document.select(".author > span:nth-child(2)").text() + artist = author + status = document.select(".status > span:nth-child(2)").text().parseStatus() + description = document.select(".summary p").text() + thumbnail_url = document.select("div.series-image img").attr("abs:src") + } + } + + // chapter list + override fun chapterListSelector() = "div.chap" + + override fun chapterFromElement(element: Element) = SChapter.create().apply { + element.selectFirst("a")!!.let { + setUrlWithoutDomain(it.absUrl("href")) + name = it.text() + } + date_upload = parseDate(element.select("div > div > span:nth-child(2)").text()) + } + + // page list + 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 + } + } + + private fun Element.imgAttr(): String = when { + hasAttr("data-pagespeed-high-res-src") -> dataImageAsUrl("data-pagespeed-high-res-src") + hasAttr("data-pagespeed-lazy-src") -> dataImageAsUrl("data-pagespeed-lazy-src") + else -> dataImageAsUrl("src") + } + + private fun parseDate(dateStr: String) = + runCatching { dateFormat.parse(dateStr)!!.time } + .getOrDefault(0L) + + companion object { + const val SLUG_SEARCH_PREFIX = "slug:" + } +} diff --git a/lib-multisrc/po2scans/src/eu/kanade/tachiyomi/multisrc/po2scans/PO2ScansUrlActivity.kt b/src/tr/sadscans/src/eu/kanade/tachiyomi/extension/tr/sadscans/SadscansUrlActivity.kt similarity index 75% rename from lib-multisrc/po2scans/src/eu/kanade/tachiyomi/multisrc/po2scans/PO2ScansUrlActivity.kt rename to src/tr/sadscans/src/eu/kanade/tachiyomi/extension/tr/sadscans/SadscansUrlActivity.kt index f260ea234..beddb6052 100644 --- a/lib-multisrc/po2scans/src/eu/kanade/tachiyomi/multisrc/po2scans/PO2ScansUrlActivity.kt +++ b/src/tr/sadscans/src/eu/kanade/tachiyomi/extension/tr/sadscans/SadscansUrlActivity.kt @@ -1,4 +1,4 @@ -package eu.kanade.tachiyomi.multisrc.po2scans +package eu.kanade.tachiyomi.extension.tr.sadscans 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 PO2ScansUrlActivity : Activity() { +class SadscansUrlActivity : Activity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val pathSegments = intent?.data?.pathSegments @@ -15,17 +15,17 @@ class PO2ScansUrlActivity : Activity() { val slug = pathSegments[1] val mainIntent = Intent().apply { action = "eu.kanade.tachiyomi.SEARCH" - putExtra("query", "${PO2Scans.SLUG_SEARCH_PREFIX}$slug") + putExtra("query", "${Sadscans.SLUG_SEARCH_PREFIX}$slug") putExtra("filter", packageName) } try { startActivity(mainIntent) } catch (e: ActivityNotFoundException) { - Log.e("PO2ScansUrlActivity", "Could not start activity", e) + Log.e("SadscansUrlActivity", "Could not start activity", e) } } else { - Log.e("PO2ScansUrlActivity", "could not parse URI from intent $intent") + Log.e("SadscansUrlActivity", "could not parse URI from intent $intent") } finish()