diff --git a/src/en/mangamiso/AndroidManifest.xml b/src/en/mangamiso/AndroidManifest.xml deleted file mode 100644 index 6e274ca35..000000000 --- a/src/en/mangamiso/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/src/en/mangamiso/build.gradle b/src/en/mangamiso/build.gradle deleted file mode 100644 index 6b7e55f17..000000000 --- a/src/en/mangamiso/build.gradle +++ /dev/null @@ -1,8 +0,0 @@ -ext { - extName = 'MangaMiso' - extClass = '.MangaMiso' - extVersionCode = 4 - isNsfw = true -} - -apply from: "$rootDir/common.gradle" diff --git a/src/en/mangamiso/res/mipmap-hdpi/ic_launcher.png b/src/en/mangamiso/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index 9d8a57639..000000000 Binary files a/src/en/mangamiso/res/mipmap-hdpi/ic_launcher.png and /dev/null differ diff --git a/src/en/mangamiso/res/mipmap-mdpi/ic_launcher.png b/src/en/mangamiso/res/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index 17e0934ed..000000000 Binary files a/src/en/mangamiso/res/mipmap-mdpi/ic_launcher.png and /dev/null differ diff --git a/src/en/mangamiso/res/mipmap-xhdpi/ic_launcher.png b/src/en/mangamiso/res/mipmap-xhdpi/ic_launcher.png deleted file mode 100644 index 007abb7a0..000000000 Binary files a/src/en/mangamiso/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ diff --git a/src/en/mangamiso/res/mipmap-xxhdpi/ic_launcher.png b/src/en/mangamiso/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index 2e5a4b848..000000000 Binary files a/src/en/mangamiso/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ diff --git a/src/en/mangamiso/res/mipmap-xxxhdpi/ic_launcher.png b/src/en/mangamiso/res/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index a76a4deb5..000000000 Binary files a/src/en/mangamiso/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ diff --git a/src/en/mangamiso/src/eu/kanade/tachiyomi/extension/en/mangamiso/MangaMiso.kt b/src/en/mangamiso/src/eu/kanade/tachiyomi/extension/en/mangamiso/MangaMiso.kt deleted file mode 100644 index 278f80751..000000000 --- a/src/en/mangamiso/src/eu/kanade/tachiyomi/extension/en/mangamiso/MangaMiso.kt +++ /dev/null @@ -1,415 +0,0 @@ -package eu.kanade.tachiyomi.extension.en.mangamiso - -import eu.kanade.tachiyomi.network.GET -import eu.kanade.tachiyomi.network.asObservableSuccess -import eu.kanade.tachiyomi.source.model.Filter -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 kotlinx.serialization.decodeFromString -import kotlinx.serialization.json.Json -import kotlinx.serialization.json.decodeFromJsonElement -import kotlinx.serialization.json.jsonObject -import okhttp3.HttpUrl -import okhttp3.Request -import okhttp3.Response -import rx.Observable -import uy.kohesive.injekt.injectLazy -import java.lang.Exception -import java.text.SimpleDateFormat -import java.util.Locale - -class MangaMiso : HttpSource() { - - companion object { - const val MANGA_PER_PAGE = 20 - val DATE_FORMAT = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.US) - const val PREFIX_ID_SEARCH = "id:" - } - - override val name = "MangaMiso" - - override val baseUrl = "https://mangamiso.net" - - override val lang = "en" - - override val supportsLatest = true - - override val client = network.cloudflareClient - - private val json: Json by injectLazy() - - override fun popularMangaRequest(page: Int): Request { - val url = getBaseURLBuilder() - .addPathSegment("mangas-get") - .addPathSegment("get-new-mangas") - .addQueryParameter("perPage", MANGA_PER_PAGE.toString()) - .addQueryParameter("page", page.toString()) - .toString() - - return GET(url, headers) - } - - override fun popularMangaParse(response: Response): MangasPage { - val mangaList = json.decodeFromString(response.body.string()) - val page = response.request.url.queryParameter("page")!!.toInt() - val totalViewedManga = page * MANGA_PER_PAGE - return MangasPage(mangaList.newManga.map(::toSManga), mangaList.total > totalViewedManga) - } - - override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request { - val builder = getBaseURLBuilder() - .addQueryParameter("perPage", MANGA_PER_PAGE.toString()) - .addQueryParameter("page", page.toString()) - - return when { - query.startsWith(PREFIX_ID_SEARCH) -> { - val id = query.removePrefix(PREFIX_ID_SEARCH) - val url = "$baseUrl/mangas/$id" - return GET(url, headers) - } - query.isNotBlank() -> throw UnsupportedOperationException("Text search currently not supported") - else -> { - val url = builder.addPathSegment("genres") - - var tagCount = 0 - filters.forEach { filter -> - when (filter) { - is MangaStatusFilter -> { - val statusSlug = filter.toUriPart() - url.addQueryParameter("status", statusSlug) - } - is UriPartFilter -> { - if (filter.toUriPart() != "") { - val genreSlug = filter.toUriPart() - url.addPathSegment(genreSlug) - tagCount++ - if (tagCount > 1) { - throw UnsupportedOperationException("Too many categories selected") - } - } - } - else -> {} - } - } - - // If no filters selected, default to "all" - if (tagCount == 0) { url.addPathSegment("all") } - GET(url.build(), headers) - } - } - } - - override fun searchMangaParse(response: Response): MangasPage { - // This search was for a specific manga id - return if (response.request.url.pathSegments[0] == "mangas") { - val manga = mangaDetailsParse(response) - MangasPage(listOf(manga), false) - } else { - val mangaList = json.decodeFromString(response.body.string()) - val page = response.request.url.queryParameter("page")!!.toInt() - val totalViewedManga = page * MANGA_PER_PAGE - MangasPage(mangaList.foundList.map(::toSManga), mangaList.total > totalViewedManga) - } - } - - override fun latestUpdatesRequest(page: Int): Request { - val url = getBaseURLBuilder() - .addPathSegment("mangas-get") - .addPathSegment("get-latestUpdate-mangas") - .addQueryParameter("perPage", MANGA_PER_PAGE.toString()) - .addQueryParameter("page", page.toString()) - - return GET(url.build(), headers) - } - - override fun latestUpdatesParse(response: Response): MangasPage { - val mangaList = json.decodeFromString(response.body.string()) - val page = response.request.url.queryParameter("page")!!.toInt() - val totalViewedManga = page * MANGA_PER_PAGE - return MangasPage(mangaList.newManga.map(::toSManga), mangaList.total > totalViewedManga) - } - - // Since mangaDetailsRequest is what drives the webview, - // we are using this solely to provide that URL - override fun mangaDetailsRequest(manga: SManga): Request { - return GET(manga.url, headers) - } - - // This is what actually gets the manga details - override fun fetchMangaDetails(manga: SManga): Observable { - val jsonURL = manga.url.replace("/manga/", "/mangas/") - return client.newCall( - GET(jsonURL, headers), - ).asObservableSuccess() - .map { response -> - mangaDetailsParse(response) - } - } - - override fun mangaDetailsParse(response: Response): SManga { - val mangaRoot = json.parseToJsonElement(response.body.string()) - val mangaObj = mangaRoot.jsonObject["manga"]!! - - return toSManga(json.decodeFromJsonElement(mangaObj)) - } - - private fun cleanDescription(mangaDesc: String): String { - // Remove the link to the manga on other sites - var description = "

Link:.*

".toRegex(RegexOption.IGNORE_CASE).replace(mangaDesc, "") - - // Convert any breaks
to newlines - description = description.replace("
", "\n", true) - - // Convert any paragraphs to double newlines - description = description.replace("

", "\n\n", true) - - // Replace any other tags with nothing - description = "<.*?>".toRegex().replace(description, "") - - return description.trim() - } - - private fun mapStatus(status: String) = - when (status) { - "ongoing", "hiatus" -> SManga.ONGOING - "completed", "cancelled" -> SManga.COMPLETED - else -> SManga.UNKNOWN - } - - override fun chapterListRequest(manga: SManga): Request { - val url = "${manga.url.replace("/manga/", "/mangas/")}/get-manga-chapters-12345?page=1&perPage=9999&sort=-1" - return GET(url, headers) - } - - override fun chapterListParse(response: Response): List { - val chapterRoot = json.parseToJsonElement(response.body.string()) - - val chapterBase = chapterRoot.jsonObject["chapters"]!! - - val chapterList = json.decodeFromJsonElement(chapterBase) - - val path = response.request.url.pathSegments[1] // this is the pathName of the manga - - return chapterList.chapters.map { toSChapter(it, "$baseUrl/manga/$path") } - } - - override fun pageListRequest(chapter: SChapter): Request { - return GET(chapter.url.replace("/manga/", "/mangas/"), headers) - } - - override fun pageListParse(response: Response): List { - val chapterRoot = json.parseToJsonElement(response.body.string()) - - val chapterBase = chapterRoot.jsonObject["chapter"]!! - - val pageList = json.decodeFromJsonElement(chapterBase) - - return pageList.pages.mapIndexed { index, misoPage -> - val imgURL = "$baseUrl${misoPage.path}" - Page( - index, - imgURL, - imgURL, - ) - } - } - - override fun imageUrlParse(response: Response) = throw UnsupportedOperationException() - - //region Filter Classes - private open class UriPartFilter(displayName: String, val vals: Array>) : - Filter.Select(displayName, vals.map { it.first }.toTypedArray()) { - fun toUriPart() = vals[state].second - } - - private class MangaStatusFilter : UriPartFilter( - "Manga Status", - arrayOf( - Pair("All", "all"), - Pair("Ongoing", "ongoing"), - Pair("Completed", "completed"), - Pair("Cancelled", "cancelled"), - Pair("On Hiatus", "hiatus"), - ), - ) - - private class DemographicFilter : UriPartFilter( - "Demographic", - arrayOf( - Pair("", ""), - Pair("Action", "action"), - Pair("Adventure", "adventure"), - Pair("Comedy", "comedy"), - Pair("Crime", "crime"), - Pair("Drama", "drama"), - Pair("Fantasy", "fantasy"), - Pair("Historical", "historical"), - Pair("Horror", "horror"), - Pair("Isekai", "isekai"), - Pair("Magical Girls", "magical_girls"), - Pair("Mature", "mature"), - Pair("Mecha", "mecha"), - Pair("Medical", "medical"), - Pair("Mystery", "mystery"), - Pair("Philosopical", "philosopical"), - Pair("Psychological", "psychological"), - Pair("Romance", "romance"), - Pair("Sci-fi", "sci-fi"), - Pair("Shoujo Ai", "shoujo_ai"), - Pair("Shounen Ai", "shounen_ai"), - Pair("Slice of Life", "slice_of_life"), - Pair("Sports", "sports"), - Pair("Superhero", "superhero"), - Pair("Thriller", "thriller"), - Pair("Tragedy", "tragedy"), - Pair("Wuxia", "wuxia"), - Pair("Yaoi", "yaoi"), - Pair("Yuri", "yuri"), - ), - ) - - private class ThemeFilter : UriPartFilter( - "Themes", - arrayOf( - Pair("", ""), - Pair("4-Koma", "4-Koma"), - Pair("Anthology", "anthology"), - Pair("Doujinshi", "doujinshi"), - Pair("Fan Colored", "fan-colored"), - Pair("Full Colored", "full-colored"), - Pair("Long Strip", "long_strip"), - Pair("Manhwa", "manhwa"), - Pair("Officially Colored", "officially-colored"), - Pair("One Shot", "one_shot"), - Pair("Partly-Colored", "partly-colored"), - Pair("Web Comic", "web_comic"), - ), - ) - - private class ContentWarningFilter : UriPartFilter( - "Content Warning", - arrayOf( - Pair("", ""), - Pair("Adaptation", "adaptation"), - Pair("Adapted to Anime", "adapted_to_anime"), - Pair("Award Winning", "award_winning"), - ), - ) - - //endregion - - override fun getFilterList(): FilterList { - return FilterList( - MangaStatusFilter(), - Filter.Header("Max 1 selection from any of the below categories"), - DemographicFilter(), - GenreFilter(), - ThemeFilter(), - ContentTypeFilter(), - ContentWarningFilter(), - GloryFilter(), - ) - } - - private fun getBaseURLBuilder(): HttpUrl.Builder { - return HttpUrl.Builder() - .scheme("https") - .host("mangamiso.net") - } - - private fun toSManga(manga: MisoManga): SManga { - return SManga.create().apply { - title = manga.title.trim() - author = manga.author.joinToString(",", transform = ::humanizeID) - artist = manga.artist.joinToString(",", transform = ::humanizeID) - thumbnail_url = "$baseUrl${manga.coverImage}" - url = "$baseUrl/manga/${manga.pathName}" - - genre = manga.tags.joinToString(", ", transform = ::humanizeID) - - description = cleanDescription(manga.description) - - status = mapStatus(manga.status) - } - } - - private fun toSChapter(chapter: MisoChapter, mangaURL: String): SChapter { - return SChapter.create().apply { - name = chapter.title.trim() - date_upload = try { DATE_FORMAT.parse(chapter.createdAt)!!.time } catch (e: Exception) { System.currentTimeMillis() } - url = "$mangaURL/${chapter.pathName}" - chapter_number = chapter.chapterNum - } - } - - // Convert the id of authors / artists / tags to a better form. (Eg. school_life -> School Life) - private fun humanizeID(text: String) = text.split("_").joinToString(" ") { it.capitalize(Locale.US) } -} diff --git a/src/en/mangamiso/src/eu/kanade/tachiyomi/extension/en/mangamiso/MangaMisoObjects.kt b/src/en/mangamiso/src/eu/kanade/tachiyomi/extension/en/mangamiso/MangaMisoObjects.kt deleted file mode 100644 index 961d3ea1d..000000000 --- a/src/en/mangamiso/src/eu/kanade/tachiyomi/extension/en/mangamiso/MangaMisoObjects.kt +++ /dev/null @@ -1,83 +0,0 @@ -package eu.kanade.tachiyomi.extension.en.mangamiso - -import kotlinx.serialization.SerialName -import kotlinx.serialization.Serializable - -@Serializable -data class MisoNewMangaPage( - val newManga: List = emptyList(), - val total: Int = 0, -) - -@Serializable -data class MisoLatestUpdatesPage( - val newManga: List = emptyList(), - val total: Int = 0, -) - -@Serializable -data class MisoBrowseManga( - val foundList: List = emptyList(), - val total: Int = 0, -) - -@Serializable -data class MisoManga( - - val title: String = "", - - val description: String = "", - - val pathName: String = "", - - val status: String = "", - - val coverImage: String = "", - - val author: List = emptyList(), - val artist: List = emptyList(), - - val demographic: List = emptyList(), - - val genre: List = emptyList(), - - val themes: List = emptyList(), - - val contentType: List = emptyList(), - - val contentWarning: List = emptyList(), - - val glory: List = emptyList(), -) { - val tags: List get() { - return demographic + genre + themes + contentType + contentWarning + glory - } -} - -@Serializable -data class MisoChapterList( - val chapters: List, -) - -@Serializable -data class MisoChapter( - - @SerialName("chapterTitle") val title: String = "", - - val pathName: String = "", - - val chapterNum: Float = 1f, - - val createdAt: String = "", - -) - -@Serializable -data class MisoPageList( - val pages: List, -) - -@Serializable -data class MisoPage( - val path: String, -) diff --git a/src/en/mangamiso/src/eu/kanade/tachiyomi/extension/en/mangamiso/MangaMisoUrlActivity.kt b/src/en/mangamiso/src/eu/kanade/tachiyomi/extension/en/mangamiso/MangaMisoUrlActivity.kt deleted file mode 100644 index 8ec9399e2..000000000 --- a/src/en/mangamiso/src/eu/kanade/tachiyomi/extension/en/mangamiso/MangaMisoUrlActivity.kt +++ /dev/null @@ -1,35 +0,0 @@ -package eu.kanade.tachiyomi.extension.en.mangamiso - -import android.app.Activity -import android.content.ActivityNotFoundException -import android.content.Intent -import android.os.Bundle -import android.util.Log -import kotlin.system.exitProcess - -class MangaMisoUrlActivity : Activity() { - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - val pathSegments = intent?.data?.pathSegments - if (pathSegments != null && pathSegments.size > 1) { - val id = pathSegments[1] - val mainIntent = Intent().apply { - action = "eu.kanade.tachiyomi.SEARCH" - putExtra("query", "${MangaMiso.PREFIX_ID_SEARCH}$id") - putExtra("filter", packageName) - } - - try { - startActivity(mainIntent) - } catch (e: ActivityNotFoundException) { - Log.e("MangaMisoUrlActivity", e.toString()) - } - } else { - Log.e("MangaMisoUrlActivity", "could not parse uri from intent $intent") - } - - finish() - exitProcess(0) - } -}