From 8c16b03bb9908d3b821d6d6b01dfb7b210eaeba3 Mon Sep 17 00:00:00 2001 From: ObserverOfTime Date: Fri, 12 Nov 2021 15:40:55 +0200 Subject: [PATCH] xkcd: add more translations (#9793) * Spanish * French * Russian * Korean --- src/all/xkcd/build.gradle | 2 +- .../tachiyomi/extension/all/xkcd/Xkcd.kt | 43 ++++++++-------- .../extension/all/xkcd/XkcdFactory.kt | 8 +++ .../extension/all/xkcd/translations/XkcdES.kt | 36 +++++++++++++ .../extension/all/xkcd/translations/XkcdFR.kt | 46 +++++++++++++++++ .../extension/all/xkcd/translations/XkcdKO.kt | 50 +++++++++++++++++++ .../extension/all/xkcd/translations/XkcdRU.kt | 48 ++++++++++++++++++ 7 files changed, 210 insertions(+), 23 deletions(-) create mode 100644 src/all/xkcd/src/eu/kanade/tachiyomi/extension/all/xkcd/translations/XkcdES.kt create mode 100644 src/all/xkcd/src/eu/kanade/tachiyomi/extension/all/xkcd/translations/XkcdFR.kt create mode 100644 src/all/xkcd/src/eu/kanade/tachiyomi/extension/all/xkcd/translations/XkcdKO.kt create mode 100644 src/all/xkcd/src/eu/kanade/tachiyomi/extension/all/xkcd/translations/XkcdRU.kt diff --git a/src/all/xkcd/build.gradle b/src/all/xkcd/build.gradle index c21f2a43f..026111fdf 100644 --- a/src/all/xkcd/build.gradle +++ b/src/all/xkcd/build.gradle @@ -6,7 +6,7 @@ ext { extName = 'xkcd' pkgNameSuffix = 'all.xkcd' extClass = '.XkcdFactory' - extVersionCode = 11 + extVersionCode = 12 } apply from: "$rootDir/common.gradle" diff --git a/src/all/xkcd/src/eu/kanade/tachiyomi/extension/all/xkcd/Xkcd.kt b/src/all/xkcd/src/eu/kanade/tachiyomi/extension/all/xkcd/Xkcd.kt index 2a8220526..d5fa48644 100644 --- a/src/all/xkcd/src/eu/kanade/tachiyomi/extension/all/xkcd/Xkcd.kt +++ b/src/all/xkcd/src/eu/kanade/tachiyomi/extension/all/xkcd/Xkcd.kt @@ -27,7 +27,7 @@ open class Xkcd( protected open val creator = "Randall Munroe" protected open val synopsis = - "A webcomic of romance, sarcasm, math and language" + "A webcomic of romance, sarcasm, math and language." protected open val interactiveText = "To experience the interactive version of this comic," + @@ -47,6 +47,25 @@ open class Xkcd( protected open fun String.numbered(number: Any) = "$number - $this" + // TODO: maybe use BreakIterator + protected fun wordWrap(title: String, altText: String) = buildString { + title.split(' ').forEachIndexed { i, w -> + if (i != 0 && i % 7 == 0) append("\n") + append(w).append(' ') + } + append("\n\n") + + var charCount = 0 + altText.replace("\r\n", " ").split(' ').forEach { w -> + if (charCount > 25) { + append("\n") + charCount = 0 + } + append(w).append(' ') + charCount += w.length + 1 + } + } + final override fun fetchPopularManga(page: Int) = SManga.create().apply { title = name @@ -88,27 +107,7 @@ open class Xkcd( } // create a text image for the alt text - val titleWords = img.attr("alt").split(' ') - val altTextWords = img.attr("title").split(' ') - - // TODO: maybe use BreakIterator - val text = buildString { - titleWords.forEachIndexed { i, w -> - if (i != 0 && i % 7 == 0) append("\n") - append(w).append(' ') - } - append("\n\n") - - var charCount = 0 - altTextWords.forEach { w -> - if (charCount > 25) { - append("\n") - charCount = 0 - } - append(w).append(' ') - charCount += w.length + 1 - } - } + val text = wordWrap(img.attr("alt"), img.attr("title")) return listOf(Page(0, "", image), Page(1, "", text.image())) } diff --git a/src/all/xkcd/src/eu/kanade/tachiyomi/extension/all/xkcd/XkcdFactory.kt b/src/all/xkcd/src/eu/kanade/tachiyomi/extension/all/xkcd/XkcdFactory.kt index 395d10cef..8dcfd4ade 100644 --- a/src/all/xkcd/src/eu/kanade/tachiyomi/extension/all/xkcd/XkcdFactory.kt +++ b/src/all/xkcd/src/eu/kanade/tachiyomi/extension/all/xkcd/XkcdFactory.kt @@ -1,11 +1,19 @@ package eu.kanade.tachiyomi.extension.all.xkcd +import eu.kanade.tachiyomi.extension.all.xkcd.translations.XkcdES +import eu.kanade.tachiyomi.extension.all.xkcd.translations.XkcdFR +import eu.kanade.tachiyomi.extension.all.xkcd.translations.XkcdKO +import eu.kanade.tachiyomi.extension.all.xkcd.translations.XkcdRU import eu.kanade.tachiyomi.extension.all.xkcd.translations.XkcdZH import eu.kanade.tachiyomi.source.SourceFactory class XkcdFactory : SourceFactory { override fun createSources() = listOf( Xkcd("https://xkcd.com", "en"), + XkcdES(), XkcdZH(), + XkcdFR(), + XkcdRU(), + XkcdKO(), ) } diff --git a/src/all/xkcd/src/eu/kanade/tachiyomi/extension/all/xkcd/translations/XkcdES.kt b/src/all/xkcd/src/eu/kanade/tachiyomi/extension/all/xkcd/translations/XkcdES.kt new file mode 100644 index 000000000..b5e473473 --- /dev/null +++ b/src/all/xkcd/src/eu/kanade/tachiyomi/extension/all/xkcd/translations/XkcdES.kt @@ -0,0 +1,36 @@ +package eu.kanade.tachiyomi.extension.all.xkcd.translations + +import eu.kanade.tachiyomi.extension.all.xkcd.Xkcd +import eu.kanade.tachiyomi.source.model.SChapter +import eu.kanade.tachiyomi.util.asJsoup +import okhttp3.Response + +class XkcdES : Xkcd("https://es.xkcd.com", "es") { + override val synopsis = + "Un webcómic sobre romance, sarcasmo, mates y lenguaje." + + // Google translated, sorry + override val interactiveText = + "Para experimentar la versión interactiva de este cómic," + + "\nábralo en WebView/navegador." + + override val chapterListSelector = "#archive-ul > ul > li > a" + + override val imageSelector = "#middleContent .strip" + + override fun chapterListParse(response: Response) = + response.asJsoup().select(chapterListSelector).mapIndexed { idx, el -> + SChapter.create().apply { + name = el.text() + // convert relative path to absolute + url = el.attr("href").substring(2) + // not accurate to the original ¯\_(ツ)_/¯ + chapter_number = idx + 1f + // no dates available + date_upload = 0L + } + } + + override fun String.numbered(number: Any) = + throw UnsupportedOperationException("Not used") +} diff --git a/src/all/xkcd/src/eu/kanade/tachiyomi/extension/all/xkcd/translations/XkcdFR.kt b/src/all/xkcd/src/eu/kanade/tachiyomi/extension/all/xkcd/translations/XkcdFR.kt new file mode 100644 index 000000000..9b9ee0f08 --- /dev/null +++ b/src/all/xkcd/src/eu/kanade/tachiyomi/extension/all/xkcd/translations/XkcdFR.kt @@ -0,0 +1,46 @@ +package eu.kanade.tachiyomi.extension.all.xkcd.translations + +import eu.kanade.tachiyomi.extension.all.xkcd.Xkcd +import eu.kanade.tachiyomi.source.model.Page +import eu.kanade.tachiyomi.source.model.SChapter +import eu.kanade.tachiyomi.util.asJsoup +import okhttp3.Response + +class XkcdFR : Xkcd("https://xkcd.lapin.org", "fr") { + override val archive = "/tous-episodes.php" + + override val synopsis = + "Un webcomic sarcastique qui parle de romance, de maths et de langage." + + override val chapterListSelector = "#content .s > a:not(:last-of-type)" + + override val imageSelector = "#content .s" + + override fun String.numbered(number: Any) = "$number. $this" + + override fun chapterListParse(response: Response) = + response.asJsoup().select(chapterListSelector).map { + SChapter.create().apply { + url = "/" + it.attr("href") + val number = url.substringAfter('=') + name = it.text().numbered(number) + chapter_number = number.toFloat() + // no dates available + date_upload = 0L + } + } + + override fun pageListParse(response: Response) = + response.asJsoup().selectFirst(imageSelector).let { + // no interactive comics here + val img = it.child(2).child(0).child(0) + + // create a text image for the alt text + val text = wordWrap(it.child(0).text(), img.attr("alt")) + + listOf(Page(0, "", img.attr("abs:src")), Page(1, "", text.image())) + } + + override val interactiveText: String + get() = throw UnsupportedOperationException("Not used") +} diff --git a/src/all/xkcd/src/eu/kanade/tachiyomi/extension/all/xkcd/translations/XkcdKO.kt b/src/all/xkcd/src/eu/kanade/tachiyomi/extension/all/xkcd/translations/XkcdKO.kt new file mode 100644 index 000000000..ae4bd2520 --- /dev/null +++ b/src/all/xkcd/src/eu/kanade/tachiyomi/extension/all/xkcd/translations/XkcdKO.kt @@ -0,0 +1,50 @@ +package eu.kanade.tachiyomi.extension.all.xkcd.translations + +import eu.kanade.tachiyomi.extension.all.xkcd.Xkcd +import eu.kanade.tachiyomi.source.model.Page +import eu.kanade.tachiyomi.source.model.SChapter +import eu.kanade.tachiyomi.util.asJsoup +import okhttp3.Response + +class XkcdKO : Xkcd("https://xkcdko.com", "ko") { + override val creator = "랜들 먼로" + + override val synopsis = "사랑, 풍자, 수학, 그리고 언어에 관한 웹 만화." + + // Google translated, sorry + override val interactiveText = + "이 만화의 대화형 버전을 경험하려면\nWebView/브라우저에서 엽니다." + + override val altTextUrl = CJK_ALT_TEXT_URL + + override val chapterListSelector = "#comicList > ol > li > a" + + override fun chapterListParse(response: Response) = + response.asJsoup().select(chapterListSelector).map { + SChapter.create().apply { + url = it.attr("href") + val number = it.attr("title") + name = it.text().numbered(number) + chapter_number = number.toFloat() + // no dates available + date_upload = 0L + } + } + + override fun pageListParse(response: Response): List { + // if the img tag is empty then it is an interactive comic + val img = response.asJsoup().selectFirst(imageSelector) + ?: return listOf(Page(0, "", interactiveText.image())) + + // if an HD image is available it'll be the srcset attribute + val image = when { + !img.hasAttr("srcset") -> img.attr("abs:src") + else -> img.attr("abs:srcset").substringBefore(' ') + } + + // create a text image for the alt text + val text = img.attr("alt") + "\n\n" + img.attr("title") + + return listOf(Page(0, "", image), Page(1, "", text.image())) + } +} diff --git a/src/all/xkcd/src/eu/kanade/tachiyomi/extension/all/xkcd/translations/XkcdRU.kt b/src/all/xkcd/src/eu/kanade/tachiyomi/extension/all/xkcd/translations/XkcdRU.kt new file mode 100644 index 000000000..95973e654 --- /dev/null +++ b/src/all/xkcd/src/eu/kanade/tachiyomi/extension/all/xkcd/translations/XkcdRU.kt @@ -0,0 +1,48 @@ +package eu.kanade.tachiyomi.extension.all.xkcd.translations + +import eu.kanade.tachiyomi.extension.all.xkcd.Xkcd +import eu.kanade.tachiyomi.source.model.Page +import eu.kanade.tachiyomi.source.model.SChapter +import eu.kanade.tachiyomi.util.asJsoup +import okhttp3.Response + +class XkcdRU : Xkcd("https://xkcd.ru", "ru") { + override val archive = "/img" + + override val creator = "Рэндел Манро" + + override val synopsis = "о романтике, сарказме, математике и языке" + + override val altTextUrl = super.altTextUrl.replace("museo", "noto") + + override val chapterListSelector = ".main > a" + + override val imageSelector = ".main" + + override fun String.numbered(number: Any) = "$number: $this" + + override fun chapterListParse(response: Response) = + response.asJsoup().select(chapterListSelector).map { + SChapter.create().apply { + url = it.attr("href") + name = it.child(0).attr("title") + chapter_number = url.removeSurrounding("/").toFloat() + // no dates available + date_upload = 0L + } + } + + override fun pageListParse(response: Response) = + response.asJsoup().selectFirst(imageSelector).let { + // no interactive comics here + val img = it.child(5).child(0) + + // create a text image for the alt text + val text = wordWrap(img.attr("alt"), it.child(7).text()) + + listOf(Page(0, "", img.attr("abs:src")), Page(1, "", text.image())) + } + + override val interactiveText: String + get() = throw UnsupportedOperationException("Not used") +}