Remove A Pair Of 2+, migrate Sadscans from old multisrc (#4955)
* Remove A Pair Of 2+ * move Sadscans from multisrc
This commit is contained in:
		
							parent
							
								
									f8ab0d3f2f
								
							
						
					
					
						commit
						90eb12294c
					
				| @ -1,9 +0,0 @@ | ||||
| plugins { | ||||
|     id("lib-multisrc") | ||||
| } | ||||
| 
 | ||||
| baseVersionCode = 1 | ||||
| 
 | ||||
| dependencies { | ||||
|     api(project(":lib:dataimage")) | ||||
| } | ||||
| @ -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<MangasPage> { | ||||
|         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:" | ||||
|     } | ||||
| } | ||||
| @ -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" | ||||
										
											Binary file not shown.
										
									
								
							| Before Width: | Height: | Size: 2.2 KiB | 
										
											Binary file not shown.
										
									
								
							| Before Width: | Height: | Size: 1.3 KiB | 
										
											Binary file not shown.
										
									
								
							| Before Width: | Height: | Size: 2.8 KiB | 
										
											Binary file not shown.
										
									
								
							| Before Width: | Height: | Size: 5.2 KiB | 
										
											Binary file not shown.
										
									
								
							| Before Width: | Height: | Size: 7.6 KiB | 
| @ -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() | ||||
| } | ||||
| @ -3,7 +3,7 @@ | ||||
| 
 | ||||
|     <application> | ||||
|         <activity | ||||
|             android:name="eu.kanade.tachiyomi.multisrc.po2scans.PO2ScansUrlActivity" | ||||
|             android:name="eu.kanade.tachiyomi.extension.tr.sadscans.SadscansUrlActivity" | ||||
|             android:excludeFromRecents="true" | ||||
|             android:exported="true" | ||||
|             android:theme="@android:style/Theme.NoDisplay"> | ||||
| @ -14,9 +14,9 @@ | ||||
|                 <category android:name="android.intent.category.BROWSABLE" /> | ||||
| 
 | ||||
|                 <data | ||||
|                     android:host="${SOURCEHOST}" | ||||
|                     android:host="sadscans.com" | ||||
|                     android:pathPattern="/series/..*" | ||||
|                     android:scheme="${SOURCESCHEME}" /> | ||||
|                     android:scheme="https" /> | ||||
|             </intent-filter> | ||||
|         </activity> | ||||
|     </application> | ||||
| @ -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")) | ||||
| } | ||||
|  | ||||
| @ -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<MangasPage> { | ||||
|         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:" | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -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() | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Vetle Ledaal
						Vetle Ledaal