diff --git a/src/en/boredsociety/build.gradle b/src/en/boredsociety/build.gradle
deleted file mode 100644
index 78a1f8567..000000000
--- a/src/en/boredsociety/build.gradle
+++ /dev/null
@@ -1,18 +0,0 @@
-apply plugin: 'com.android.application'
-apply plugin: 'kotlin-android'
-
-ext {
- appName = 'Tachiyomi: Boredom Society'
- pkgNameSuffix = 'en.boredomsociety'
- extClass = '.BoredomSociety'
- extVersionCode = 4
- libVersion = '1.2'
-}
-
-dependencies {
- compileOnly 'com.google.code.gson:gson:2.8.2'
- compileOnly 'com.github.salomonbrys.kotson:kotson:2.5.0'
- compileOnly 'com.github.inorichi.injekt:injekt-core:65b0440'
-}
-
-apply from: "$rootDir/common.gradle"
diff --git a/src/en/boredsociety/res/mipmap-hdpi/ic_launcher.png b/src/en/boredsociety/res/mipmap-hdpi/ic_launcher.png
deleted file mode 100644
index 0de15f69d..000000000
Binary files a/src/en/boredsociety/res/mipmap-hdpi/ic_launcher.png and /dev/null differ
diff --git a/src/en/boredsociety/res/mipmap-mdpi/ic_launcher.png b/src/en/boredsociety/res/mipmap-mdpi/ic_launcher.png
deleted file mode 100644
index 13506eec7..000000000
Binary files a/src/en/boredsociety/res/mipmap-mdpi/ic_launcher.png and /dev/null differ
diff --git a/src/en/boredsociety/res/mipmap-xhdpi/ic_launcher.png b/src/en/boredsociety/res/mipmap-xhdpi/ic_launcher.png
deleted file mode 100644
index dd098b029..000000000
Binary files a/src/en/boredsociety/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ
diff --git a/src/en/boredsociety/res/mipmap-xxhdpi/ic_launcher.png b/src/en/boredsociety/res/mipmap-xxhdpi/ic_launcher.png
deleted file mode 100644
index 32651e371..000000000
Binary files a/src/en/boredsociety/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ
diff --git a/src/en/boredsociety/res/mipmap-xxxhdpi/ic_launcher.png b/src/en/boredsociety/res/mipmap-xxxhdpi/ic_launcher.png
deleted file mode 100644
index 0842b55cf..000000000
Binary files a/src/en/boredsociety/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ
diff --git a/src/en/boredsociety/res/web_hi_res_512.png b/src/en/boredsociety/res/web_hi_res_512.png
deleted file mode 100644
index 7832966dd..000000000
Binary files a/src/en/boredsociety/res/web_hi_res_512.png and /dev/null differ
diff --git a/src/en/boredsociety/src/eu/kanade/tachiyomi/extension/en/boredomsociety/BoredomSociety.kt b/src/en/boredsociety/src/eu/kanade/tachiyomi/extension/en/boredomsociety/BoredomSociety.kt
deleted file mode 100644
index dd06a6edd..000000000
--- a/src/en/boredsociety/src/eu/kanade/tachiyomi/extension/en/boredomsociety/BoredomSociety.kt
+++ /dev/null
@@ -1,213 +0,0 @@
-package eu.kanade.tachiyomi.extension.en.boredomsociety
-
-import com.github.salomonbrys.kotson.get
-import com.github.salomonbrys.kotson.long
-import com.github.salomonbrys.kotson.string
-import com.google.gson.JsonArray
-import com.google.gson.JsonElement
-import com.google.gson.JsonObject
-import com.google.gson.JsonParser
-import eu.kanade.tachiyomi.network.GET
-import eu.kanade.tachiyomi.network.asObservableSuccess
-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.ParsedHttpSource
-import okhttp3.HttpUrl
-import okhttp3.OkHttpClient
-import okhttp3.Request
-import okhttp3.Response
-import org.jsoup.Jsoup
-import org.jsoup.nodes.Document
-import org.jsoup.nodes.Element
-import rx.Observable
-
-class BoredomSociety : ParsedHttpSource() {
-
- override val name = "Boredom Society"
-
- override val baseUrl = "https://boredomsociety.xyz"
-
- override val lang = "en"
-
- override val supportsLatest = true
-
- override val client: OkHttpClient = network.cloudflareClient
-
- override fun popularMangaRequest(page: Int): Request {
- return GET(baseUrl + ALL_URL, headers)
- }
-
- override fun latestUpdatesRequest(page: Int): Request = popularMangaRequest(page)
-
- override fun fetchPopularManga(page: Int): Observable {
- return client.newCall(popularMangaRequest(page))
- .asObservableSuccess()
- .map { response ->
- popularMangaParse(response)
- }
- }
-
- override fun popularMangaParse(response: Response): MangasPage {
- val jsonArray = getJsonArray(response)
- val list = parseData(jsonArray.toList())
- return MangasPage(list, false)
- }
-
- override fun fetchLatestUpdates(page: Int): Observable {
- return client.newCall(latestUpdatesRequest(page))
- .asObservableSuccess()
- .map { response ->
- latestUpdatesParse(response)
- }
- }
-
- override fun latestUpdatesParse(response: Response): MangasPage {
- val jsonArray = getJsonArray(response)
- val sortedJson = jsonArray.sortedBy { it["last_updated"].long }.asReversed()
- val list = parseData(sortedJson)
- return MangasPage(list, false)
- }
-
- private fun getJsonArray(response: Response): JsonArray {
- val jsonData = response.body()!!.string()
- return JsonParser().parse(jsonData).asJsonArray
- }
-
- private fun parseData(jsonArray: List): List {
- val mutableList = mutableListOf()
- jsonArray.forEach { json ->
- val manga = SManga.create()
- manga.url = MANGA_URL + json["id"].string
- json["title_name"].string
- manga.title = json["title_name"].string
- manga.description = cleanString(json["title_desc"].string)
- manga.status = getStatus(json["status"].string)
- manga.thumbnail_url = "https://" + json["cover_url"].string
-
- mutableList.add(manga)
- }
- return mutableList
- }
-
- private fun parseChapter(jsonElement: JsonElement): SChapter {
- val sChapter = SChapter.create()
- sChapter.url = CHAPTER_URL + jsonElement["id"].string
- val chapterName = mutableListOf()
-
- if (!jsonElement["chapter_name"].string.startsWith("Chapter", true)) {
- if (jsonElement["chapter_volume"].string.isNotBlank()) {
- chapterName.add("Vol. " + jsonElement["chapter_volume"].string)
- }
- if (jsonElement["chapter_number"].string.isNotBlank()) {
- chapterName.add("Ch. " + jsonElement["chapter_number"].string + " - ")
- }
- }
- chapterName.add(jsonElement["chapter_name"].string)
- sChapter.name = cleanString(chapterName.joinToString(" "))
- sChapter.date_upload = jsonElement["creation_timestamp"].long * 1000
- return sChapter
- }
-
- private fun getStatus(status: String): Int {
- return when (status) {
- "Ongoing" -> SManga.ONGOING
- "Finished" -> SManga.COMPLETED
- else -> SManga.UNKNOWN
- }
- }
-
- override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
- val url = HttpUrl.parse("$baseUrl$ALL_URL$query")!!.newBuilder()
- return GET(url.toString(), headers)
- }
-
- override fun fetchSearchManga(page: Int, query: String, filters: FilterList): Observable {
- return client.newCall(searchMangaRequest(page, query, filters))
- .asObservableSuccess()
- .map { response ->
- searchMangaParse(response)
- }
- }
-
- override fun searchMangaParse(response: Response): MangasPage = popularMangaParse(response)
-
- private fun getJsonObject(response: Response): JsonObject {
- val jsonData = response.body()!!.string()
- return JsonParser().parse(jsonData).asJsonObject
- }
-
- override fun mangaDetailsParse(response: Response): SManga {
- val jsonObject = getJsonObject(response)
- val list = parseData(listOf(jsonObject))
- return list[0]
- }
-
- override fun chapterListParse(response: Response): List {
- val json = getJsonObject(response)
- var mutableChapters = mutableListOf()
- json["chapters"].asJsonArray.forEach { it ->
- mutableChapters.add(parseChapter(it))
- }
- mutableChapters.reverse()
- return mutableChapters
- }
-
- override fun pageListParse(document: Document) = throw Exception("Not used")
-
- override fun pageListParse(response: Response): List {
- val json = getJsonObject(response)
-
- val pages = mutableListOf()
- val array = json["page_url"].asJsonArray
-
- array.forEach {
- val url = "https://${it.asString}"
- pages.add(Page(pages.size, "", url))
- }
-
- return pages
- }
-
- private fun cleanString(description: String): String {
- return Jsoup.parseBodyFragment(description
- .replace("[list]", "")
- .replace("[/list]", "")
- .replace("[*]", "")
- .replace("""\[(\w+)[^\]]*](.*?)\[/\1]""".toRegex(), "$2")).text()
- }
-
- override fun imageUrlParse(document: Document): String = ""
-
- override fun chapterFromElement(element: Element): SChapter = throw Exception("Not used")
-
- override fun chapterListSelector(): String = throw Exception("Not used")
-
- override fun latestUpdatesFromElement(element: Element): SManga = throw Exception("Not used")
-
- override fun latestUpdatesNextPageSelector(): String? = throw Exception("Not used")
-
- override fun latestUpdatesSelector(): String = throw Exception("Not used")
-
- override fun mangaDetailsParse(document: Document): SManga = throw Exception("Not used")
-
- override fun popularMangaFromElement(element: Element): SManga = throw Exception("Not used")
-
- override fun popularMangaNextPageSelector(): String? = throw Exception("Not used")
-
- override fun popularMangaSelector(): String = throw Exception("Not used")
-
- override fun searchMangaFromElement(element: Element): SManga = throw Exception("Not used")
-
- override fun searchMangaNextPageSelector(): String? = throw Exception("Not used")
-
- override fun searchMangaSelector(): String = throw Exception("Not used")
-
- companion object {
- private const val MANGA_URL = "/api/title/"
- private const val ALL_URL = "/api/titles/"
- private const val CHAPTER_URL = "/api/chapter/"
- }
-}
diff --git a/src/id/pecintakomik/build.gradle b/src/id/pecintakomik/build.gradle
deleted file mode 100644
index 5f752a23f..000000000
--- a/src/id/pecintakomik/build.gradle
+++ /dev/null
@@ -1,12 +0,0 @@
-apply plugin: 'com.android.application'
-apply plugin: 'kotlin-android'
-
-ext {
- appName = 'Tachiyomi: Pecinta Komik'
- pkgNameSuffix = 'id.pecintakomik'
- extClass = '.PecintaKomik'
- extVersionCode = 3
- libVersion = '1.2'
-}
-
-apply from: "$rootDir/common.gradle"
diff --git a/src/id/pecintakomik/res/mipmap-hdpi/ic_launcher.png b/src/id/pecintakomik/res/mipmap-hdpi/ic_launcher.png
deleted file mode 100644
index 05c4e8c2f..000000000
Binary files a/src/id/pecintakomik/res/mipmap-hdpi/ic_launcher.png and /dev/null differ
diff --git a/src/id/pecintakomik/res/mipmap-mdpi/ic_launcher.png b/src/id/pecintakomik/res/mipmap-mdpi/ic_launcher.png
deleted file mode 100644
index 8b443115f..000000000
Binary files a/src/id/pecintakomik/res/mipmap-mdpi/ic_launcher.png and /dev/null differ
diff --git a/src/id/pecintakomik/res/mipmap-xhdpi/ic_launcher.png b/src/id/pecintakomik/res/mipmap-xhdpi/ic_launcher.png
deleted file mode 100644
index 4bac62f9b..000000000
Binary files a/src/id/pecintakomik/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ
diff --git a/src/id/pecintakomik/res/mipmap-xxhdpi/ic_launcher.png b/src/id/pecintakomik/res/mipmap-xxhdpi/ic_launcher.png
deleted file mode 100644
index ed0fdf319..000000000
Binary files a/src/id/pecintakomik/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ
diff --git a/src/id/pecintakomik/res/mipmap-xxxhdpi/ic_launcher.png b/src/id/pecintakomik/res/mipmap-xxxhdpi/ic_launcher.png
deleted file mode 100644
index c108c772f..000000000
Binary files a/src/id/pecintakomik/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ
diff --git a/src/id/pecintakomik/res/web_hi_res_512.png b/src/id/pecintakomik/res/web_hi_res_512.png
deleted file mode 100644
index 0e042805b..000000000
Binary files a/src/id/pecintakomik/res/web_hi_res_512.png and /dev/null differ
diff --git a/src/id/pecintakomik/src/eu/kanade/tachiyomi/extension/id/pecintakomik/PecintaKomik.kt b/src/id/pecintakomik/src/eu/kanade/tachiyomi/extension/id/pecintakomik/PecintaKomik.kt
deleted file mode 100644
index 4f19a9ebd..000000000
--- a/src/id/pecintakomik/src/eu/kanade/tachiyomi/extension/id/pecintakomik/PecintaKomik.kt
+++ /dev/null
@@ -1,323 +0,0 @@
-package eu.kanade.tachiyomi.extension.id.pecintakomik
-
-import eu.kanade.tachiyomi.network.GET
-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.source.online.ParsedHttpSource
-import java.text.SimpleDateFormat
-import java.util.Locale
-import okhttp3.HttpUrl
-import okhttp3.OkHttpClient
-import okhttp3.Request
-import org.jsoup.Jsoup
-import org.jsoup.nodes.Document
-import org.jsoup.nodes.Element
-
-class PecintaKomik : ParsedHttpSource() {
-
- override val name = "Pecinta Komik"
-
- override val baseUrl = "https://www.pecintakomik.net"
-
- override val lang = "id"
-
- override val supportsLatest = true
-
- override val client: OkHttpClient = network.cloudflareClient
-
- override fun latestUpdatesRequest(page: Int): Request {
- // The site redirects page 1 -> url-without-page so we do this redirect early for optimization
- val builtUrl = if (page == 1) baseUrl else "$baseUrl/page/$page/"
- return GET(builtUrl)
- }
-
- override fun latestUpdatesSelector() = ".releases:contains(update) + .listthumbx li"
-
- override fun latestUpdatesFromElement(element: Element): SManga {
- val manga = SManga.create()
- val item = element.select("div.lx a.series")
- val imgurl = element.select("div.thumbx img").attr("src")
- manga.url = item.attr("href")
- manga.title = item.text()
- manga.thumbnail_url = imgurl
- return manga
- }
-
- override fun latestUpdatesNextPageSelector() = "a.next"
-
- override fun popularMangaRequest(page: Int): Request {
- val builtUrl = if (page == 1) "$baseUrl/advanced-search/?order=popular" else "$baseUrl/advanced-search/page/$page/?order=popular"
- return GET(builtUrl)
- }
-
- override fun popularMangaSelector() = "div.listupd div.utao"
-
- override fun popularMangaFromElement(element: Element): SManga {
- val manga = SManga.create()
- val imgurl = element.select("div.imgu img").attr("src")
- manga.url = element.select("div.imgu a").attr("href")
- manga.title = element.select("div.imgu a").attr("title")
- manga.thumbnail_url = imgurl
- return manga
- }
-
- override fun popularMangaNextPageSelector() = latestUpdatesNextPageSelector()
-
- override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
- val builtUrl = if (page == 1) "$baseUrl/advanced-search/" else "$baseUrl/advanced-search/page/$page/"
- var types: String? = null
- fun requireNoType() = require(types == null) {
- "You cannot combine type with other filters!"
- }
- val url = HttpUrl.parse(builtUrl)!!.newBuilder()
- url.addQueryParameter("title", query)
- url.addQueryParameter("page", page.toString())
- filters.forEach { filter ->
- when (filter) {
- is AuthorFilter -> {
- if (filter.state.isNotBlank()) {
- requireNoType()
- url.addQueryParameter("author", filter.state)
- }
- }
- is YearFilter -> {
- if (filter.state.isNotBlank()) {
- requireNoType()
- url.addQueryParameter("yearx", filter.state)
- }
- }
- is StatusFilter -> {
- val status = when (filter.state) {
- Filter.TriState.STATE_INCLUDE -> "completed"
- Filter.TriState.STATE_EXCLUDE -> "ongoing"
- else -> ""
- }
- if (status.isNotEmpty()) {
- requireNoType()
- url.addQueryParameter("status", status)
- }
- }
- is TypeFilter -> {
- if (filter.state != 0) {
- types = if (page == 1) "$baseUrl/types/${filter.toUriPart()}/" else "$baseUrl/types/${filter.toUriPart()}/page/$page/"
- }
- }
- is OrderByFilter -> {
- if (filter.state != 0) {
- requireNoType()
- url.addQueryParameter("order", filter.toUriPart())
- }
- }
- is GenreList -> {
- filter.state.forEach {
- if (it.state) {
- requireNoType()
- url.addQueryParameter("genre[]", it.id)
- }
- }
- }
- }
- }
- return if (types != null) {
- GET("$types")
- } else {
- GET(url.build().toString(), headers)
- }
- }
-
- override fun searchMangaSelector() = popularMangaSelector()
-
- override fun searchMangaFromElement(element: Element) = popularMangaFromElement(element)
-
- override fun searchMangaNextPageSelector() = latestUpdatesNextPageSelector()
-
- override fun mangaDetailsRequest(manga: SManga): Request {
- if (manga.url.startsWith("http")) {
- return GET(manga.url, headers)
- }
- return super.mangaDetailsRequest(manga)
- }
-
- override fun mangaDetailsParse(document: Document): SManga {
- val infoElement = document.select("div.infomanga")
- val author = infoElement.select("th:contains(Penulis) + td").text()
- val manga = SManga.create()
- val genres = mutableListOf()
- val status = infoElement.select("th:contains(Status) + td").text()
- infoElement.select("th:contains(genre) + td a").forEach { element ->
- val genre = element.text()
- genres.add(genre)
- }
- manga.title = infoElement.select("h1 strong").text()
- manga.author = author
- manga.artist = author
- manga.status = parseStatus(status)
- manga.genre = genres.joinToString(", ")
- manga.description = Jsoup.parse(document.select("span.desc").html().substringAfter("
").substringBefore("
")).text()
- manga.thumbnail_url = document.select("div.imgprop img").attr("src")
- return manga
- }
-
- private fun parseStatus(status: String?) = when {
- status == null -> SManga.UNKNOWN
- status.contains("Ongoing") -> SManga.ONGOING
- status.contains("Completed") -> SManga.COMPLETED
- else -> SManga.UNKNOWN
- }
-
- override fun chapterListRequest(manga: SManga): Request {
- if (manga.url.startsWith("http")) {
- return GET(manga.url, headers)
- }
- return super.chapterListRequest(manga)
- }
-
- override fun chapterListSelector() = "h3:contains(Chapter) + ul li"
-
- override fun chapterFromElement(element: Element): SChapter {
- val urlElement = element.select("span.lchx a")
- val chapter = SChapter.create()
- chapter.url = urlElement.attr("href")
- chapter.name = urlElement.text()
- chapter.date_upload = element.select("span.dt").text()?.let {
- chapterParseDate(it)
- } ?: 0
- return chapter
- }
-
- private fun chapterParseDate(date: String): Long {
- return SimpleDateFormat("MMM dd, yyyy", Locale.ENGLISH).parse(date
- .replace("Mei", "May")
- .replace("Agu", "Aug")
- .replace("Okt", "Oct")
- .replace("Nop", "Nov")
- .replace("Des", "Dec")
- ).time
- }
-
- override fun pageListRequest(chapter: SChapter): Request {
- if (chapter.url.startsWith("http")) {
- return GET(chapter.url, headers)
- }
- return super.pageListRequest(chapter)
- }
-
- override fun pageListParse(document: Document): List {
- val pages = mutableListOf()
- document.select("div#readerarea img").forEach {
- val url = it.attr("data-src")
- if (url != "") {
- pages.add(Page(pages.size, "", url))
- }
- }
- return pages
- }
-
- override fun imageUrlParse(document: Document): String = throw UnsupportedOperationException("Not used")
-
- override fun getFilterList() = FilterList(
- Filter.Header("Type filter cannot be combined."),
- TypeFilter(),
- Filter.Separator(),
- Filter.Header("Below you can combine filter."),
- AuthorFilter(),
- YearFilter(),
- StatusFilter(),
- OrderByFilter(),
- GenreList(getGenreList())
- )
-
- private class AuthorFilter : Filter.Text("Author")
-
- private class YearFilter : Filter.Text("Year")
-
- private class StatusFilter : Filter.TriState("Completed")
-
- private class TypeFilter : UriPartFilter("Type", arrayOf(
- Pair("