* added source: Aurora to fulfill #9985 * Update src/en/aurora/src/eu/kanade/tachiyomi/extension/en/aurora/Aurora.kt added headers to the get request Co-authored-by: ObserverOfTime <chronobserver@disroot.org> * Update src/en/aurora/src/eu/kanade/tachiyomi/extension/en/aurora/Aurora.kt removed a filter Co-authored-by: ObserverOfTime <chronobserver@disroot.org> * Update src/en/aurora/src/eu/kanade/tachiyomi/extension/en/aurora/Aurora.kt removed filter Co-authored-by: ObserverOfTime <chronobserver@disroot.org> * used client.newCall instead of Jsoup to fullfill code review of #9986 * chapters to mangas and pages to chapters to fix automatic updates. #9985 * added automatic status fetching when a chapter (in form of a manga) is updated * added the name of the manga/comic in front of the chapter name so it can be more easily differenciated from other manga * Update src/en/aurora/src/eu/kanade/tachiyomi/extension/en/aurora/Aurora.kt removed some regex stuff Co-authored-by: ObserverOfTime <chronobserver@disroot.org> * Update src/en/aurora/src/eu/kanade/tachiyomi/extension/en/aurora/Aurora.kt removed some logging that isn't needed anymore Co-authored-by: ObserverOfTime <chronobserver@disroot.org> * Apply suggestions from code review accepted some code review changes Co-authored-by: ObserverOfTime <chronobserver@disroot.org> * implemented some more code review suggestions * Apply suggestions from code review Co-authored-by: ObserverOfTime <chronobserver@disroot.org> Co-authored-by: ObserverOfTime <chronobserver@disroot.org>
This commit is contained in:
parent
5c5e997c04
commit
fc4d99e1e8
2
src/en/aurora/AndroidManifest.xml
Normal file
2
src/en/aurora/AndroidManifest.xml
Normal file
@ -0,0 +1,2 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest package="eu.kanade.tachiyomi.extension" />
|
11
src/en/aurora/build.gradle
Normal file
11
src/en/aurora/build.gradle
Normal file
@ -0,0 +1,11 @@
|
||||
apply plugin: 'com.android.application'
|
||||
apply plugin: 'kotlin-android'
|
||||
|
||||
ext {
|
||||
extName = 'aurora'
|
||||
pkgNameSuffix = 'en.aurora'
|
||||
extClass = '.Aurora'
|
||||
extVersionCode = 1
|
||||
}
|
||||
|
||||
apply from: "$rootDir/common.gradle"
|
BIN
src/en/aurora/res/mipmap-hdpi/ic_launcher.png
Normal file
BIN
src/en/aurora/res/mipmap-hdpi/ic_launcher.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 12 KiB |
BIN
src/en/aurora/res/mipmap-mdpi/ic_launcher.png
Normal file
BIN
src/en/aurora/res/mipmap-mdpi/ic_launcher.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.8 KiB |
BIN
src/en/aurora/res/mipmap-xhdpi/ic_launcher.png
Normal file
BIN
src/en/aurora/res/mipmap-xhdpi/ic_launcher.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 19 KiB |
BIN
src/en/aurora/res/mipmap-xxhdpi/ic_launcher.png
Normal file
BIN
src/en/aurora/res/mipmap-xxhdpi/ic_launcher.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 38 KiB |
BIN
src/en/aurora/res/mipmap-xxxhdpi/ic_launcher.png
Normal file
BIN
src/en/aurora/res/mipmap-xxxhdpi/ic_launcher.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 59 KiB |
BIN
src/en/aurora/res/web_hi_res_512.png
Normal file
BIN
src/en/aurora/res/web_hi_res_512.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 354 KiB |
@ -0,0 +1,205 @@
|
||||
package eu.kanade.tachiyomi.extension.en.aurora
|
||||
|
||||
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.HttpSource
|
||||
import eu.kanade.tachiyomi.util.asJsoup
|
||||
import okhttp3.Request
|
||||
import okhttp3.Response
|
||||
import rx.Observable
|
||||
import java.lang.Exception
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
|
||||
/**
|
||||
* @author THE_ORONCO <the_oronco@posteo.net>
|
||||
*/
|
||||
|
||||
class Aurora : HttpSource() {
|
||||
|
||||
override val name = "Aurora"
|
||||
override val baseUrl = "https://comicaurora.com"
|
||||
override val lang = "en"
|
||||
override val supportsLatest = false
|
||||
private val authorName = "OSP-Red"
|
||||
private val auroraGenre = "fantasy"
|
||||
private val dateFormat = SimpleDateFormat("MMMM dd, yyyy", Locale.US)
|
||||
|
||||
override fun chapterListRequest(manga: SManga): Request = throw Exception("Not used")
|
||||
|
||||
override fun chapterListParse(response: Response): List<SChapter> = throw Exception("Not used")
|
||||
|
||||
override fun fetchChapterList(manga: SManga): Observable<List<SChapter>> {
|
||||
return Observable.just(fetchChapterListTR(baseUrl + manga.url, mutableListOf()))
|
||||
}
|
||||
|
||||
private tailrec fun fetchChapterListTR(
|
||||
currentUrl: String,
|
||||
foundChapters: MutableList<SChapter>
|
||||
): MutableList<SChapter> {
|
||||
val currentPage = client.newCall(GET(currentUrl, headers)).execute().asJsoup()
|
||||
|
||||
val pagesAsChapters = currentPage.select(".post-content")
|
||||
.map { postContent ->
|
||||
val chapterUrl = postContent.select("a.webcomic-link").attr("href")
|
||||
val title = postContent.select(".post-title a").text()
|
||||
val chapterNr = title.substringAfter('.').toFloat()
|
||||
val dateString = postContent.select(".post-date").text()
|
||||
val date = dateFormat.parse(dateString)?.time ?: 0L
|
||||
|
||||
SChapter.create().apply {
|
||||
setUrlWithoutDomain(chapterUrl)
|
||||
name = title
|
||||
chapter_number = chapterNr
|
||||
date_upload = date
|
||||
}
|
||||
}
|
||||
|
||||
foundChapters.addAll(pagesAsChapters)
|
||||
|
||||
// get a potential next page of the chapter overview
|
||||
val nextPageNavUrl = currentPage.selectFirst(".paginav-next a")?.attr("href")
|
||||
// check if a next page actually exits and if not exit
|
||||
return if (nextPageNavUrl == null) {
|
||||
foundChapters
|
||||
} else {
|
||||
fetchChapterListTR(nextPageNavUrl, foundChapters)
|
||||
}
|
||||
}
|
||||
|
||||
override fun fetchImageUrl(page: Page): Observable<String> {
|
||||
return Observable.just(page.imageUrl)
|
||||
}
|
||||
|
||||
override fun imageUrlParse(response: Response): String = throw Exception("Not used")
|
||||
|
||||
override fun latestUpdatesParse(response: Response): MangasPage = throw Exception("Not used")
|
||||
|
||||
override fun latestUpdatesRequest(page: Int): Request = throw Exception("Not used")
|
||||
|
||||
override fun fetchMangaDetails(manga: SManga): Observable<SManga> {
|
||||
val chapterNr = manga.title.substringAfter(' ').toFloatOrNull() ?: 0f
|
||||
|
||||
val updatedManga = SManga.create().apply {
|
||||
setUrlWithoutDomain(manga.url)
|
||||
title = manga.title
|
||||
artist = authorName
|
||||
author = authorName
|
||||
description = auroraDescription
|
||||
genre = auroraGenre
|
||||
status = getChapterStatusForChapter(chapterNr)
|
||||
thumbnail_url = manga.thumbnail_url
|
||||
}
|
||||
return Observable.just(updatedManga)
|
||||
}
|
||||
|
||||
/**
|
||||
* @param chapter chapter the status should be fetched for
|
||||
* @return the status of the chapter (as Enum value of SManga because chapters are mangas)
|
||||
*/
|
||||
private fun getChapterStatusForChapter(chapter: Float): Int {
|
||||
val newestPage = client.newCall(GET(baseUrl)).execute().asJsoup()
|
||||
val postTitle = newestPage.selectFirst(".post-title").text()
|
||||
// title is "<arc>.<chapter>.<page>"
|
||||
val chapterOfNewestPage = postTitle.split(".")[1].toFloat()
|
||||
return if (chapter >= chapterOfNewestPage) SManga.UNKNOWN else SManga.COMPLETED
|
||||
}
|
||||
|
||||
private val auroraDescription = """
|
||||
Aurora is a fantasy webcomic (updates M/W/F) written and illustrated by Red, better known for her work on the YouTube channel “Overly Sarcastic Productions.” It’s been in the works for over a decade, and she’s finally decided to stop putting it off.
|
||||
|
||||
If you’d like to discuss the comic, it now has a subreddit, as well as a dedicated twitter and a tumblr where you can ask questions. There’s also a dedicated room on the channel discord for conversations about it!
|
||||
|
||||
Find Red’s general ramblings on Twitter, alongside her cohost Blue, at OSPYouTube.
|
||||
""".trimIndent()
|
||||
|
||||
override fun mangaDetailsParse(response: Response): SManga = throw Exception("Not used")
|
||||
|
||||
override fun fetchPageList(chapter: SChapter): Observable<List<Page>> {
|
||||
val singlePageChapterDoc = client.newCall(
|
||||
GET(baseUrl + chapter.url, headers)
|
||||
).execute().asJsoup()
|
||||
val imageUrl = singlePageChapterDoc.selectFirst(
|
||||
".webcomic-media .webcomic-link .attachment-full"
|
||||
).attr("src")
|
||||
val singlePageChapter = Page(0, "", imageUrl)
|
||||
|
||||
return Observable.just(listOf(singlePageChapter))
|
||||
}
|
||||
|
||||
override fun pageListRequest(chapter: SChapter): Request = throw Exception("Not used")
|
||||
|
||||
override fun pageListParse(response: Response): List<Page> = throw Exception("Not used")
|
||||
|
||||
/**
|
||||
* Because the comic is updated 1 page at a time the chapters are turned into different mangas
|
||||
* so that the pages can be turned into different chapters which can be automatically updated by
|
||||
* Tachiyomi.
|
||||
*
|
||||
* @return List of all Chapters as separate mangas
|
||||
*/
|
||||
private fun fetchChaptersAsMangas(): List<SManga> {
|
||||
val descriptionText = auroraDescription
|
||||
|
||||
val chapterArchiveUrl = "$baseUrl/archive/"
|
||||
|
||||
val chapterOverviewDoc = client.newCall(GET(chapterArchiveUrl, headers)).execute().asJsoup()
|
||||
val chapterBlockElements = chapterOverviewDoc.select(".blocks-gallery-item")
|
||||
val mangasFromChapters = chapterBlockElements
|
||||
.mapIndexed { chapterIndex, chapter ->
|
||||
val chapterOverviewLink = chapter.selectFirst(".blocks-gallery-item__caption a")
|
||||
val chapterOverviewUrl = chapterOverviewLink.attr("href")
|
||||
val chapterTitle = "$name - ${chapterOverviewLink.text()}"
|
||||
val chapterThumbnail = chapter.selectFirst("figure img").attr("src")
|
||||
|
||||
SManga.create().apply {
|
||||
setUrlWithoutDomain(chapterOverviewUrl)
|
||||
title = chapterTitle
|
||||
author = authorName
|
||||
artist = authorName
|
||||
description = descriptionText
|
||||
genre = auroraGenre
|
||||
// this will mark every chapter except the last one as completed
|
||||
status =
|
||||
if (chapterIndex >= chapterBlockElements.size - 1) SManga.UNKNOWN
|
||||
else SManga.COMPLETED
|
||||
thumbnail_url = chapterThumbnail
|
||||
}
|
||||
}
|
||||
|
||||
return mangasFromChapters
|
||||
}
|
||||
|
||||
/**
|
||||
* Turn the list of chapters as mangas into the mangas page that can be returned for every
|
||||
* request.
|
||||
*/
|
||||
private fun generateAuroraMangasPage(): MangasPage {
|
||||
return MangasPage(fetchChaptersAsMangas(), false)
|
||||
}
|
||||
|
||||
override fun fetchPopularManga(page: Int): Observable<MangasPage> {
|
||||
return Observable.just(generateAuroraMangasPage())
|
||||
}
|
||||
|
||||
override fun popularMangaParse(response: Response): MangasPage = throw Exception("Not used")
|
||||
|
||||
override fun popularMangaRequest(page: Int): Request = throw Exception("Not used")
|
||||
|
||||
override fun fetchSearchManga(
|
||||
page: Int,
|
||||
query: String,
|
||||
filters: FilterList
|
||||
): Observable<MangasPage> {
|
||||
return Observable.just(generateAuroraMangasPage())
|
||||
}
|
||||
|
||||
override fun searchMangaParse(response: Response): MangasPage = throw Exception("Not used")
|
||||
|
||||
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request =
|
||||
throw Exception("Not used")
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user