From 3fb869e5e2ae61c8b6afd581b1e300f8a52ff859 Mon Sep 17 00:00:00 2001 From: Maxim Molochkov <48491463+klaseca@users.noreply.github.com> Date: Sat, 5 Apr 2025 09:19:39 +0400 Subject: [PATCH] Return Henchan source (#8280) --- src/ru/henchan/build.gradle | 10 + .../henchan/res/mipmap-hdpi/ic_launcher.png | Bin 0 -> 3008 bytes .../henchan/res/mipmap-mdpi/ic_launcher.png | Bin 0 -> 1748 bytes .../henchan/res/mipmap-xhdpi/ic_launcher.png | Bin 0 -> 3689 bytes .../henchan/res/mipmap-xxhdpi/ic_launcher.png | Bin 0 -> 5651 bytes .../res/mipmap-xxxhdpi/ic_launcher.png | Bin 0 -> 8006 bytes .../tachiyomi/extension/ru/henchan/HenChan.kt | 502 ++++++++++++++++++ 7 files changed, 512 insertions(+) create mode 100644 src/ru/henchan/build.gradle create mode 100644 src/ru/henchan/res/mipmap-hdpi/ic_launcher.png create mode 100644 src/ru/henchan/res/mipmap-mdpi/ic_launcher.png create mode 100644 src/ru/henchan/res/mipmap-xhdpi/ic_launcher.png create mode 100644 src/ru/henchan/res/mipmap-xxhdpi/ic_launcher.png create mode 100644 src/ru/henchan/res/mipmap-xxxhdpi/ic_launcher.png create mode 100644 src/ru/henchan/src/eu/kanade/tachiyomi/extension/ru/henchan/HenChan.kt diff --git a/src/ru/henchan/build.gradle b/src/ru/henchan/build.gradle new file mode 100644 index 000000000..facc8cdc6 --- /dev/null +++ b/src/ru/henchan/build.gradle @@ -0,0 +1,10 @@ +ext { + extName = 'HenChan' + extClass = '.HenChan' + themePkg = 'multichan' + baseUrl = 'https://xxl.hentaichan.live' + overrideVersionCode = 40 + isNsfw = true +} + +apply from: "$rootDir/common.gradle" diff --git a/src/ru/henchan/res/mipmap-hdpi/ic_launcher.png b/src/ru/henchan/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..eca8d1e500937f567e0ad4126b05ea1746deb7f0 GIT binary patch literal 3008 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 Hu0mjfasd=- literal 0 HcmV?d00001 diff --git a/src/ru/henchan/res/mipmap-xxhdpi/ic_launcher.png b/src/ru/henchan/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..7fcff819fba6d4e2ccf36ff1023eac4162fce758 GIT binary patch literal 5651 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 ZW>9G;NNt9TV2iyt>MwL4HAoy#Ifr?_-?^L^f* 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 OgEZ81RV$UPBmWPx232SP literal 0 HcmV?d00001 diff --git a/src/ru/henchan/src/eu/kanade/tachiyomi/extension/ru/henchan/HenChan.kt b/src/ru/henchan/src/eu/kanade/tachiyomi/extension/ru/henchan/HenChan.kt new file mode 100644 index 000000000..5a31c1ac1 --- /dev/null +++ b/src/ru/henchan/src/eu/kanade/tachiyomi/extension/ru/henchan/HenChan.kt @@ -0,0 +1,502 @@ +package eu.kanade.tachiyomi.extension.ru.henchan + +import android.annotation.SuppressLint +import android.content.SharedPreferences +import android.widget.Toast +import androidx.preference.EditTextPreference +import eu.kanade.tachiyomi.multisrc.multichan.MultiChan +import eu.kanade.tachiyomi.network.GET +import eu.kanade.tachiyomi.network.asObservable +import eu.kanade.tachiyomi.source.ConfigurableSource +import eu.kanade.tachiyomi.source.model.Filter +import eu.kanade.tachiyomi.source.model.FilterList +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.util.asJsoup +import keiyoushi.utils.getPreferencesLazy +import okhttp3.Headers +import okhttp3.Request +import okhttp3.Response +import org.jsoup.nodes.Document +import org.jsoup.nodes.Element +import rx.Observable +import java.net.URL +import java.text.SimpleDateFormat +import java.util.Date +import java.util.Locale + +class HenChan : MultiChan("HenChan", "https://xxl.hentaichan.live", "ru"), ConfigurableSource { + + override val id = 5504588601186153612 + + private val preferences: SharedPreferences by getPreferencesLazy() + + private val domain = preferences.getString(DOMAIN_TITLE, DOMAIN_DEFAULT)!! + + override val baseUrl = domain + + override fun latestUpdatesRequest(page: Int): Request = GET("$baseUrl/manga/newest?offset=${20 * (page - 1)}") + + override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request { + val url = if (query.isNotEmpty()) { + "$baseUrl/?do=search&subaction=search&story=$query&search_start=$page" + } else { + var genres = "" + var order = "" + filters.forEach { filter -> + when (filter) { + is GenreList -> { + filter.state + .filter { !it.isIgnored() } + .forEach { f -> + genres += (if (f.isExcluded()) "-" else "") + f.id + '+' + } + } + + else -> return@forEach + } + } + + if (genres.isNotEmpty()) { + filters.forEach { filter -> + when (filter) { + is OrderBy -> { + order = filter.toUriPartWithGenres() + } + + else -> return@forEach + } + } + "$baseUrl/tags/${genres.dropLast(1)}&sort=manga$order?offset=${20 * (page - 1)}" + } else { + filters.forEach { filter -> + when (filter) { + is OrderBy -> { + order = filter.toUriPartWithoutGenres() + } + + else -> return@forEach + } + } + "$baseUrl/$order?offset=${20 * (page - 1)}" + } + } + return GET(url, headers) + } + + override fun searchMangaSelector() = ".content_row:not(:has(div.item:containsOwn(Тип)))" + + private fun String.getHQThumbnail(): String { + val isExHenManga = this.contains("/manganew_thumbs_blur/") + val regex = "(?<=/)manganew_thumbs\\w*?(?=/)".toRegex(RegexOption.IGNORE_CASE) + return this.replace(regex, "showfull_retina/manga") + .replace( + "_".plus(URL(baseUrl).host), + "_hentaichan.ru", + ) // domain-related replacing for very old mangas + .plus( + if (isExHenManga) { + "#" + } else { + "" + }, + ) // # for later so we know what type manga is it + } + + override fun popularMangaFromElement(element: Element): SManga { + val manga = super.popularMangaFromElement(element) + manga.thumbnail_url = element.select("img").first()!!.attr("src").getHQThumbnail() + return manga + } + + override fun mangaDetailsParse(document: Document): SManga { + val manga = super.mangaDetailsParse(document) + manga.thumbnail_url = document.select("img#cover").attr("abs:src").getHQThumbnail() + return manga + } + + override fun fetchChapterList(manga: SManga): Observable> { + return client.newCall(chapterListRequest(manga)) + .asObservable().doOnNext { response -> + if (!response.isSuccessful) { + response.close() + // Error message for exceeding last page + if (response.code == 404) { + Observable.just( + listOf( + SChapter.create().apply { + url = manga.url + name = "Chapter" + chapter_number = 1f + }, + ), + ) + } else { + throw Exception("HTTP error ${response.code}") + } + } + } + .map { response -> + chapterListParse(response) + } + } + + override fun chapterListRequest(manga: SManga): Request { + val url = baseUrl + if (manga.thumbnail_url?.endsWith("#") == true) { + manga.url + } else { + manga.url.replace("/manga/", "/related/") + } + return (GET(url, headers)) + } + + override fun chapterListSelector() = ".related" + + override fun chapterListParse(response: Response): List { + val responseUrl = response.request.url.toString() + val document = response.asJsoup() + + // exhentai chapter + if (responseUrl.contains("/manga/")) { + val chap = SChapter.create() + chap.setUrlWithoutDomain(responseUrl) + chap.name = document.select("a.title_top_a").text() + chap.chapter_number = 1F + + val date = document.select("div.row4_right b")?.text()?.let { + SimpleDateFormat("dd MMMM yyyy", Locale("ru")).parse(it)?.time ?: 0 + } ?: 0 + chap.date_upload = date + return listOf(chap) + } + + // one chapter, nothing related + if (document.select("#right > div:nth-child(4)").text().contains(" похожий на ")) { + val chap = SChapter.create() + chap.setUrlWithoutDomain(document.select("#left > div > a").attr("href")) + chap.name = document.select("#right > div:nth-child(4)").text() + .split(" похожий на ")[1] + .replace("\\\"", "\"") + .replace("\\'", "'") + chap.chapter_number = 1F + chap.date_upload = + Date().time // setting to current date because of a sorting in the "Recent updates" section + return listOf(chap) + } + + // has related chapters + val result = mutableListOf() + result.addAll( + document.select(chapterListSelector()).map { + chapterFromElement(it) + }, + ) + + var url = document.select("div#pagination_related a:contains(Вперед)").attr("href") + while (url.isNotBlank()) { + val get = GET( + "${response.request.url}/$url", + headers = headers, + ) + val nextPage = client.newCall(get).execute().asJsoup() + result.addAll( + nextPage.select(chapterListSelector()).map { + chapterFromElement(it) + }, + ) + + url = nextPage.select("div#pagination_related a:contains(Вперед)").attr("href") + } + + return result.reversed() + } + + override fun chapterFromElement(element: Element): SChapter { + val chapter = SChapter.create() + chapter.setUrlWithoutDomain(element.select("h2 a").attr("href")) + val chapterName = element.select("h2 a").attr("title") + chapter.name = chapterName + chapter.chapter_number = + "(глава\\s|часть\\s)([0-9]+\\.?[0-9]*)".toRegex(RegexOption.IGNORE_CASE) + .find(chapterName)?.groupValues?.get(2)?.toFloat() ?: -1F + chapter.date_upload = + Date().time // setting to current date because of a sorting in the "Recent updates" section + return chapter + } + + override fun pageListRequest(chapter: SChapter): Request { + val url = if (chapter.url.contains("/manga/")) { + baseUrl + chapter.url.replace("/manga/", "/online/") + } else { + baseUrl + chapter.url + } + return GET(url, Headers.Builder().add("Accept", "image/webp,image/apng").build()) + } + + override fun pageListParse(response: Response): List { + val html = response.body.string() + val prefix = "fullimg\": [" + val beginIndex = html.indexOf(prefix) + prefix.length + val endIndex = html.indexOf("]", beginIndex) + val trimmedHtml = html.substring(beginIndex, endIndex) + .replace("\"", "") + .replace("\'", "") + + val pageUrls = trimmedHtml.split(", ") + return pageUrls.mapIndexed { i, url -> Page(i, "", url) } + } + + private class Genre( + val id: String, + @SuppressLint("DefaultLocale") name: String = id.replace('_', ' ').capitalize(), + ) : Filter.TriState(name) + + private class GenreList(genres: List) : Filter.Group("Тэги", genres) + private class OrderBy : UriPartFilter( + "Сортировка", + arrayOf("Дата", "Популярность", "Алфавит"), + arrayOf("&n=dateasc" to "", "&n=favasc" to "&n=favdesc", "&n=abcdesc" to "&n=abcasc"), + arrayOf( + "manga/new&n=dateasc" to "manga/new", + "manga/new&n=favasc" to "mostfavorites&sort=manga", + "manga/new&n=abcdesc" to "manga/new&n=abcasc", + ), + ) + + private open class UriPartFilter( + displayName: String, + sortNames: Array, + val withGenres: Array>, + val withoutGenres: Array>, + ) : + Filter.Sort(displayName, sortNames, Selection(1, false)) { + fun toUriPartWithGenres() = + if (state!!.ascending) withGenres[state!!.index].first else withGenres[state!!.index].second + + fun toUriPartWithoutGenres() = + if (state!!.ascending) withoutGenres[state!!.index].first else withoutGenres[state!!.index].second + } + + override fun getFilterList() = FilterList( + OrderBy(), + GenreList(getGenreList()), + ) + + private fun getGenreList() = listOf( + Genre("3D"), + Genre("action"), + Genre("ahegao"), + Genre("bdsm"), + Genre("corruption"), + Genre("foot_fetish"), + Genre("footfuck"), + Genre("gender_bender"), + Genre("live"), + Genre("lolcon"), + Genre("megane"), + Genre("mind_break"), + Genre("monstergirl"), + Genre("netorare"), + Genre("netori"), + Genre("nipple_penetration"), + Genre("oyakodon"), + Genre("paizuri_(titsfuck)"), + Genre("rpg"), + Genre("scat"), + Genre("shemale"), + Genre("shimaidon"), + Genre("shooter"), + Genre("simulation"), + Genre("skinsuit"), + Genre("tomboy"), + Genre("tomgirl"), + Genre("x-ray"), + Genre("алкоголь"), + Genre("анал"), + Genre("андроид"), + Genre("анилингус"), + Genre("анимация"), + Genre("аркада"), + Genre("арт"), + Genre("бабушка"), + Genre("без_текста"), + Genre("без_трусиков"), + Genre("без_цензуры"), + Genre("беременность"), + Genre("бикини"), + Genre("близнецы"), + Genre("боди-арт"), + Genre("больница"), + Genre("большая_грудь"), + Genre("большие_попки"), + Genre("бондаж"), + Genre("буккаке"), + Genre("в_ванной"), + Genre("в_общественном_месте"), + Genre("в_первый_раз"), + Genre("в_цвете"), + Genre("в_школе"), + Genre("вампиры"), + Genre("веб"), + Genre("вебкам"), + Genre("вибратор"), + Genre("визуальная_новелла"), + Genre("внучка"), + Genre("волосатые_женщины"), + Genre("гаремник"), + Genre("гг_девушка"), + Genre("гг_парень"), + Genre("гипноз"), + Genre("глубокий_минет"), + Genre("горячий_источник"), + Genre("грудастая_лоли"), + Genre("групповой_секс"), + Genre("гяру_и_гангуро"), + Genre("двойное_проникновение"), + Genre("девочки_волшебницы"), + Genre("девушка_туалет"), + Genre("демоны"), + Genre("дилдо"), + Genre("дочь"), + Genre("драма"), + Genre("дыра_в_стене"), + Genre("жестокость"), + Genre("за_деньги"), + Genre("зомби"), + Genre("зрелые_женщины"), + Genre("измена"), + Genre("изнасилование"), + Genre("инопланетяне"), + Genre("инцест"), + Genre("исполнение_желаний"), + Genre("камера"), + Genre("квест"), + Genre("кимоно"), + Genre("колготки"), + Genre("комиксы"), + Genre("косплей"), + Genre("кремпай"), + Genre("кудере"), + Genre("кузина"), + Genre("куннилингус"), + Genre("купальники"), + Genre("латекс_и_кожа"), + Genre("магия"), + Genre("маленькая_грудь"), + Genre("мастурбация"), + Genre("мать"), + Genre("мейдочки"), + Genre("мерзкий_дядька"), + Genre("минет"), + Genre("много_девушек"), + Genre("молоко"), + Genre("монашки"), + Genre("монстры"), + Genre("мочеиспускание"), + Genre("мужская_озвучка"), + Genre("мужчина_крепкого_телосложения"), + Genre("мускулистые_женщины"), + Genre("на_природе"), + Genre("наблюдение"), + Genre("непрямой_инцест"), + Genre("новелла"), + Genre("обмен_партнерами"), + Genre("обмен_телами"), + Genre("обычный_секс"), + Genre("огромная_грудь"), + Genre("огромный_член"), + Genre("оплодотворение"), + Genre("остановка_времени"), + Genre("парень_пассив"), + Genre("переодевание"), + Genre("песочница"), + Genre("племянница"), + Genre("пляж"), + Genre("подглядывание"), + Genre("подчинение"), + Genre("похищение"), + Genre("презерватив"), + Genre("принуждение"), + Genre("прозрачная_одежда"), + Genre("проникновение_в_матку"), + Genre("психические_отклонения"), + Genre("публично"), + Genre("рабыни"), + Genre("романтика"), + Genre("сверхъестественное"), + Genre("секс_игрушки"), + Genre("сестра"), + Genre("сетакон"), + Genre("скрытный_секс"), + Genre("спортивная_форма"), + Genre("спящие"), + Genre("страпон"), + Genre("суккубы"), + Genre("темнокожие"), + Genre("тентакли"), + Genre("толстушки"), + Genre("трап"), + Genre("тётя"), + Genre("умеренная_жестокость"), + Genre("учитель_и_ученик"), + Genre("ушастые"), + Genre("фантазии"), + Genre("фантастика"), + Genre("фемдом"), + Genre("фестиваль"), + Genre("фетиш"), + Genre("фистинг"), + Genre("фурри"), + Genre("футанари"), + Genre("футанари_имеет_парня"), + Genre("фэнтези"), + Genre("хоррор"), + Genre("цундере"), + Genre("чикан"), + Genre("чирлидеры"), + Genre("чулки"), + Genre("школьная_форма"), + Genre("школьники"), + Genre("школьницы"), + Genre("школьный_купальник"), + Genre("щекотка"), + Genre("эксгибиционизм"), + Genre("эльфы"), + Genre("эччи"), + Genre("юмор"), + Genre("юри"), + Genre("яндере"), + Genre("яой"), + ) + + override fun setupPreferenceScreen(screen: androidx.preference.PreferenceScreen) { + EditTextPreference(screen.context).apply { + key = DOMAIN_TITLE + this.title = DOMAIN_TITLE + summary = domain + this.setDefaultValue(DOMAIN_DEFAULT) + dialogTitle = DOMAIN_TITLE + setOnPreferenceChangeListener { _, newValue -> + try { + val res = + preferences.edit().putString(DOMAIN_TITLE, newValue as String).commit() + Toast.makeText( + screen.context, + "Для смены домена необходимо перезапустить приложение с полной остановкой.", + Toast.LENGTH_LONG, + ).show() + res + } catch (e: Exception) { + e.printStackTrace() + false + } + } + }.let(screen::addPreference) + } + + companion object { + private const val DOMAIN_TITLE = "Домен" + private const val DOMAIN_DEFAULT = "https://xxl.hentaichan.live" + } +}