PsychoPlay update (#1242)

PsychoPlay update
This commit is contained in:
Mike 2019-06-29 10:55:15 -04:00 committed by Eugene
parent ab3e1cfc9d
commit 30cb878aa0
2 changed files with 90 additions and 35 deletions

View File

@ -5,7 +5,7 @@ ext {
appName = 'Tachiyomi: PsychoPlay' appName = 'Tachiyomi: PsychoPlay'
pkgNameSuffix = 'en.psychoplay' pkgNameSuffix = 'en.psychoplay'
extClass = '.PsychoPlay' extClass = '.PsychoPlay'
extVersionCode = 2 extVersionCode = 3
libVersion = '1.2' libVersion = '1.2'
} }

View File

@ -3,10 +3,13 @@ package eu.kanade.tachiyomi.extension.en.psychoplay
import eu.kanade.tachiyomi.network.GET import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.source.model.* import eu.kanade.tachiyomi.source.model.*
import eu.kanade.tachiyomi.source.online.ParsedHttpSource import eu.kanade.tachiyomi.source.online.ParsedHttpSource
import eu.kanade.tachiyomi.util.asJsoup
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import okhttp3.Request import okhttp3.Request
import okhttp3.Response
import org.jsoup.nodes.Document import org.jsoup.nodes.Document
import org.jsoup.nodes.Element import org.jsoup.nodes.Element
import org.jsoup.select.Elements
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.* import java.util.*
@ -22,10 +25,11 @@ class PsychoPlay : ParsedHttpSource() {
override val client: OkHttpClient = network.cloudflareClient override val client: OkHttpClient = network.cloudflareClient
override fun popularMangaSelector() = "div.thumbnail" override fun popularMangaSelector() = "div.list-item"
private val popularMangaUrl = "$baseUrl/comics?page="
override fun popularMangaRequest(page: Int): Request { override fun popularMangaRequest(page: Int): Request {
return GET("$baseUrl/series?page=$page") return GET("$popularMangaUrl$page")
} }
override fun latestUpdatesSelector() = popularMangaSelector() override fun latestUpdatesSelector() = popularMangaSelector()
@ -36,51 +40,101 @@ class PsychoPlay : ParsedHttpSource() {
override fun popularMangaFromElement(element: Element): SManga { override fun popularMangaFromElement(element: Element): SManga {
val manga = SManga.create() val manga = SManga.create()
element.select("h6 a").first().let { element.select("a.list-title").first().let {
manga.setUrlWithoutDomain(it.attr("href")) manga.setUrlWithoutDomain(it.attr("href"))
manga.title = it.text() manga.title = it.text()
} }
manga.thumbnail_url = baseUrl + element.select("img").first().attr("src") manga.thumbnail_url = element.select("a.media-content").first().attr("style").substringAfter("(").substringBefore(")")
return manga return manga
} }
override fun latestUpdatesFromElement(element: Element): SManga = popularMangaFromElement(element) override fun latestUpdatesFromElement(element: Element): SManga = popularMangaFromElement(element)
override fun popularMangaNextPageSelector() = ":containsOwn(next):not([href=\"\"])" override fun popularMangaNextPageSelector() = "[rel=next]"
override fun latestUpdatesNextPageSelector() = popularMangaNextPageSelector() override fun latestUpdatesNextPageSelector() = popularMangaNextPageSelector()
// Didn't see a search function on PsychoPlay's website when I updated this extension; so searching locally
private var searchQuery = ""
private var searchPage = 1
private var nextPageSelectorElement = Elements()
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request { override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
val url = "$baseUrl/series?q=$query" if (page == 1) searchPage = 1
return GET(url, headers) searchQuery = query.toLowerCase()
return GET("$popularMangaUrl$page")
} }
override fun searchMangaSelector() = "div.thumbnail" override fun searchMangaParse(response: Response): MangasPage {
val searchMatches = mutableListOf<SManga>()
val document = response.asJsoup()
searchMatches.addAll(getMatchesFrom(document))
/* call another function if there's more pages to search
not doing it this way can lead to a false "no results found"
if no matches are found on the first page but there are matches
on subsequent pages */
nextPageSelectorElement = document.select(searchMangaNextPageSelector())
while (nextPageSelectorElement.hasText()) {
searchMatches.addAll(searchMorePages())
}
return MangasPage(searchMatches, false)
}
// search the given document for matches
private fun getMatchesFrom(document: Document): MutableList<SManga> {
val searchMatches = mutableListOf<SManga>()
document.select(searchMangaSelector()).forEach {
if (it.text().toLowerCase().contains(searchQuery)) {
searchMatches.add(searchMangaFromElement(it))
}
}
return searchMatches
}
// search additional pages if called
private fun searchMorePages(): MutableList<SManga> {
searchPage++
val nextPage = client.newCall(GET("$popularMangaUrl$searchPage", headers)).execute().asJsoup()
val searchMatches = mutableListOf<SManga>()
searchMatches.addAll(getMatchesFrom(nextPage))
nextPageSelectorElement = nextPage.select(searchMangaNextPageSelector())
return searchMatches
}
override fun searchMangaSelector() = popularMangaSelector()
override fun searchMangaFromElement(element: Element) = popularMangaFromElement(element) override fun searchMangaFromElement(element: Element) = popularMangaFromElement(element)
override fun searchMangaNextPageSelector() = popularMangaNextPageSelector() override fun searchMangaNextPageSelector() = popularMangaNextPageSelector()
override fun mangaDetailsParse(document: Document): SManga { override fun mangaDetailsParse(document: Document): SManga {
val infoElement = document.select("div.row").first() val infoElement = document.select("div#content").first()
val manga = SManga.create() val manga = SManga.create()
manga.title = infoElement.select("h2").first().text() manga.title = infoElement.select("h5").first().text()
manga.description = document.select("div.panel-body").text().substringAfter("Synopsis ") manga.description = document.select("div.col-lg-9").text().substringAfter("Description ").substringBefore(" Volume")
manga.thumbnail_url = baseUrl + document.select("div.media-left a").first().select("img").first().attr("src") manga.thumbnail_url = document.select("div.media a").first().attr("style").substringAfter("(").substringBefore(")")
return manga return manga
} }
override fun chapterListSelector() = "li.media" override fun chapterListSelector() = "div.col-lg-9 div.flex"
override fun chapterFromElement(element: Element): SChapter { override fun chapterFromElement(element: Element): SChapter {
val urlElement = element.select("a").first() val urlElement = element.select("a.item-author")
val chapNum = urlElement.attr("href").split("/").last()
val chapter = SChapter.create() val chapter = SChapter.create()
chapter.setUrlWithoutDomain(urlElement.attr("href")) chapter.setUrlWithoutDomain(urlElement.attr("href"))
chapter.name = urlElement.text().substringBefore("Added") if (urlElement.text().contains("Chapter $chapNum")) {
chapter.date_upload = parseChapterDate(urlElement.text().substringAfter("Added ")) ?: 0 chapter.name = urlElement.text()
} else {
chapter.name = "Ch. " + chapNum + ": " + urlElement.text()
}
chapter.date_upload = parseChapterDate(element.select("a.item-company").first().text()) ?: 0
return chapter return chapter
} }
@ -90,32 +144,28 @@ class PsychoPlay : ParsedHttpSource() {
} }
} }
// If the date string contains the word "on" simply dateformat it, otherwise send it off to parse relatively // If the date string contains the word "ago" send it off for relative date parsing otherwise use dateFormat
private fun parseChapterDate(string: String): Long? { private fun parseChapterDate(string: String): Long? {
if ("on " in string) { if ("ago" in string) {
return dateFormat.parse(string.substringAfter("on ")).time
} else {
return parseRelativeDate(string) ?: 0 return parseRelativeDate(string) ?: 0
} else {
return dateFormat.parse(string).time
} }
} }
// Subtract relative date (e.g. posted 3 days ago) // Subtract relative date (e.g. posted 3 days ago)
private fun parseRelativeDate(date: String): Long? { private fun parseRelativeDate(date: String): Long? {
var trimmedDate = date.substringBefore(" ago").replace(",", " ").split(" ") val trimmedDate = date.substringBefore(" ago").split(" ")
val calendar = Calendar.getInstance() val calendar = Calendar.getInstance()
var numIndex = -1 when (trimmedDate[1]){
trimmedDate.forEach { "month", "months" -> calendar.apply{add(Calendar.MONTH, -trimmedDate[0].toInt())}
when (it){ "week", "weeks" -> calendar.apply{add(Calendar.WEEK_OF_MONTH, -trimmedDate[0].toInt())}
"month", "months" -> calendar.apply{add(Calendar.MONTH, -trimmedDate.get(numIndex).toInt())} "day", "days" -> calendar.apply{add(Calendar.DAY_OF_MONTH, -trimmedDate[0].toInt())}
"week", "weeks" -> calendar.apply{add(Calendar.WEEK_OF_MONTH, -trimmedDate.get(numIndex).toInt())} "hour", "hours" -> calendar.apply{add(Calendar.HOUR_OF_DAY, -trimmedDate[0].toInt())}
"day", "days" -> calendar.apply{add(Calendar.DAY_OF_MONTH, -trimmedDate.get(numIndex).toInt())} "minute", "minutes" -> calendar.apply{add(Calendar.MONTH, -trimmedDate[0].toInt())}
"hour", "hours" -> calendar.apply{add(Calendar.HOUR_OF_DAY, -trimmedDate.get(numIndex).toInt())}
"minute", "minutes" -> calendar.apply{add(Calendar.MONTH, -trimmedDate.get(numIndex).toInt())}
"second", "seconds" -> calendar.apply{add(Calendar.SECOND, 0)} "second", "seconds" -> calendar.apply{add(Calendar.SECOND, 0)}
} }
numIndex++
}
return calendar.timeInMillis return calendar.timeInMillis
} }
@ -123,14 +173,19 @@ class PsychoPlay : ParsedHttpSource() {
override fun pageListParse(document: Document): List<Page> { override fun pageListParse(document: Document): List<Page> {
val pages = mutableListOf<Page>() val pages = mutableListOf<Page>()
document.select("div.row img")?.forEach { val allImages = document.select("script").first().data()
pages.add(Page(pages.size, "", it.attr("src"))) .substringAfter("[").substringBefore("];")
.replace(Regex("""["\\]"""), "")
.split(",")
for (i in 0 until allImages.size) {
pages.add(Page(i, "", allImages[i]))
} }
return pages return pages
} }
override fun imageUrlParse(document: Document): String = throw UnsupportedOperationException("No used") override fun imageUrlParse(document: Document): String = throw UnsupportedOperationException("Not used")
override fun getFilterList() = FilterList() override fun getFilterList() = FilterList()