diff --git a/src/en/kouhaiwork/AndroidManifest.xml b/src/en/kouhaiwork/AndroidManifest.xml
deleted file mode 100644
index 7335b11c4..000000000
--- a/src/en/kouhaiwork/AndroidManifest.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/en/kouhaiwork/build.gradle b/src/en/kouhaiwork/build.gradle
deleted file mode 100644
index 52ecaaf02..000000000
--- a/src/en/kouhaiwork/build.gradle
+++ /dev/null
@@ -1,7 +0,0 @@
-ext {
- extName = 'Kouhai Work'
- extClass = '.KouhaiWork'
- extVersionCode = 8
-}
-
-apply from: "$rootDir/common.gradle"
diff --git a/src/en/kouhaiwork/res/mipmap-hdpi/ic_launcher.png b/src/en/kouhaiwork/res/mipmap-hdpi/ic_launcher.png
deleted file mode 100644
index 90295216c..000000000
Binary files a/src/en/kouhaiwork/res/mipmap-hdpi/ic_launcher.png and /dev/null differ
diff --git a/src/en/kouhaiwork/res/mipmap-mdpi/ic_launcher.png b/src/en/kouhaiwork/res/mipmap-mdpi/ic_launcher.png
deleted file mode 100644
index 682fe5c69..000000000
Binary files a/src/en/kouhaiwork/res/mipmap-mdpi/ic_launcher.png and /dev/null differ
diff --git a/src/en/kouhaiwork/res/mipmap-xhdpi/ic_launcher.png b/src/en/kouhaiwork/res/mipmap-xhdpi/ic_launcher.png
deleted file mode 100644
index cedcf2010..000000000
Binary files a/src/en/kouhaiwork/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ
diff --git a/src/en/kouhaiwork/res/mipmap-xxhdpi/ic_launcher.png b/src/en/kouhaiwork/res/mipmap-xxhdpi/ic_launcher.png
deleted file mode 100644
index 72b5c4cc9..000000000
Binary files a/src/en/kouhaiwork/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ
diff --git a/src/en/kouhaiwork/res/mipmap-xxxhdpi/ic_launcher.png b/src/en/kouhaiwork/res/mipmap-xxxhdpi/ic_launcher.png
deleted file mode 100644
index ef1ca9f06..000000000
Binary files a/src/en/kouhaiwork/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ
diff --git a/src/en/kouhaiwork/src/eu/kanade/tachiyomi/extension/en/kouhaiwork/KouhaiAPI.kt b/src/en/kouhaiwork/src/eu/kanade/tachiyomi/extension/en/kouhaiwork/KouhaiAPI.kt
deleted file mode 100644
index ecfc50944..000000000
--- a/src/en/kouhaiwork/src/eu/kanade/tachiyomi/extension/en/kouhaiwork/KouhaiAPI.kt
+++ /dev/null
@@ -1,116 +0,0 @@
-package eu.kanade.tachiyomi.extension.en.kouhaiwork
-
-import kotlinx.serialization.Serializable
-import java.text.DecimalFormat
-import java.text.SimpleDateFormat
-import java.util.Locale
-
-const val ID_QUERY = "id:"
-
-const val API_URL = "https://api.kouhai.work/v3"
-
-const val STORAGE_URL = "https://api.kouhai.work/storage/"
-
-private const val ISO_DATE = "yyyy-MM-dd'T'HH:mm:ss.SSSSSS'Z'"
-
-private val dateFormat = SimpleDateFormat(ISO_DATE, Locale.ROOT)
-
-private val decimalFormat = DecimalFormat("#.##")
-
-@Serializable
-data class KouhaiSeries(
- val id: Int,
- val title: String,
- val cover: String,
-) {
- inline val url get() = id.toString()
-
- inline val thumbnail get() = STORAGE_URL + cover
-
- override fun toString() = title.trim()
-}
-
-@Serializable
-data class KouhaiSeriesDetails(
- val synopsis: String,
- val status: String,
- val alternative_titles: List? = null,
- val artists: List? = null,
- val authors: List? = null,
- val genres: List? = null,
- val themes: List? = null,
- val demographics: List? = null,
- val chapters: List,
-) {
- val tags by lazy {
- genres.orEmpty() + themes.orEmpty() + demographics.orEmpty()
- }
-
- override fun toString() = buildString {
- append(synopsis)
- alternative_titles?.joinTo(
- this,
- "\n",
- "\n\nAlternative Names:\n",
- )
- }
-}
-
-@Serializable
-data class KouhaiChapter(
- val id: Int,
- val volume: Int? = null,
- val number: Float,
- val name: String? = null,
- val groups: List,
- val updated_at: String,
-) {
- inline val url get() = id.toString()
-
- val timestamp by lazy {
- dateFormat.parse(updated_at)?.time ?: 0L
- }
-
- override fun toString() = buildString {
- volume?.let {
- append("[Vol. ").append(it).append("] ")
- }
- append("Chapter ")
- append(decimalFormat.format(number))
- name?.let { append(" - ").append(it) }
- }
-}
-
-@Serializable
-data class KouhaiTag(
- private val id: Int,
- private val name: String,
-) {
- override fun toString() = name
-}
-
-@Serializable
-data class KouhaiTagList(
- val genres: List,
- val themes: List,
- val demographics: List,
- val status: KouhaiTag?,
-)
-
-@Serializable
-data class KouhaiPages(
- private val pages: List,
-) : Iterable by pages
-
-@Serializable
-data class KouhaiMedia(private val media: String) {
- override fun toString() = STORAGE_URL + media
-}
-
-typealias KouhaiSearch = List
-
-inline val KouhaiSearch.url get() = this[0]
-
-inline val KouhaiSearch.title get() = this[1].trim()
-
-inline val KouhaiSearch.thumbnail get() = STORAGE_URL + last()
diff --git a/src/en/kouhaiwork/src/eu/kanade/tachiyomi/extension/en/kouhaiwork/KouhaiActivity.kt b/src/en/kouhaiwork/src/eu/kanade/tachiyomi/extension/en/kouhaiwork/KouhaiActivity.kt
deleted file mode 100644
index c03f47dbb..000000000
--- a/src/en/kouhaiwork/src/eu/kanade/tachiyomi/extension/en/kouhaiwork/KouhaiActivity.kt
+++ /dev/null
@@ -1,35 +0,0 @@
-package eu.kanade.tachiyomi.extension.en.kouhaiwork
-
-import android.app.Activity
-import android.content.ActivityNotFoundException
-import android.content.Intent
-import android.os.Bundle
-import android.util.Log
-import kotlin.system.exitProcess
-
-/**
- * Springboard that accepts `{baseUrl}/series/{id}`
- * intents and redirects them to the main Tachiyomi process.
- */
-class KouhaiActivity : Activity() {
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- val segments = intent?.data?.pathSegments
- if (segments != null && segments.size > 1) {
- val activity = Intent().apply {
- action = "eu.kanade.tachiyomi.SEARCH"
- putExtra("query", ID_QUERY + segments[1])
- putExtra("filter", packageName)
- }
- try {
- startActivity(activity)
- } catch (ex: ActivityNotFoundException) {
- Log.e("KouhaiActivity", ex.message, ex)
- }
- } else {
- Log.e("KouhaiActivity", "Failed to parse URI from intent: $intent")
- }
- finish()
- exitProcess(0)
- }
-}
diff --git a/src/en/kouhaiwork/src/eu/kanade/tachiyomi/extension/en/kouhaiwork/KouhaiFilters.kt b/src/en/kouhaiwork/src/eu/kanade/tachiyomi/extension/en/kouhaiwork/KouhaiFilters.kt
deleted file mode 100644
index f9b3e0988..000000000
--- a/src/en/kouhaiwork/src/eu/kanade/tachiyomi/extension/en/kouhaiwork/KouhaiFilters.kt
+++ /dev/null
@@ -1,58 +0,0 @@
-package eu.kanade.tachiyomi.extension.en.kouhaiwork
-
-import eu.kanade.tachiyomi.source.model.Filter
-
-class Genre(val id: Int, name: String) : Filter.CheckBox(name)
-
-private val genres: List
- get() = listOf(
- Genre(1, "Romance"),
- Genre(2, "Comedy"),
- Genre(3, "Slice of Life"),
- Genre(4, "Fantasy"),
- Genre(5, "Sci-Fi"),
- Genre(6, "Psychological"),
- Genre(7, "Horror"),
- Genre(8, "Mystery"),
- Genre(9, "Girls' Love"),
- Genre(10, "Drama"),
- Genre(11, "Action"),
- Genre(12, "Ecchi"),
- Genre(13, "Adventure"),
- )
-
-class GenresFilter(values: List = genres) :
- Filter.Group("Genres", values)
-
-class Theme(val id: Int, name: String) : Filter.CheckBox(name)
-
-private val themes: List
- get() = listOf(
- Theme(1, "Office Workers"),
- Theme(2, "Family"),
- Theme(3, "Supernatural"),
- Theme(4, "Demons"),
- Theme(5, "Magic"),
- Theme(6, "Aliens"),
- Theme(7, "Suggestive"),
- Theme(8, "Doujinshi"),
- Theme(9, "School Life"),
- Theme(10, "Police"),
- )
-
-class ThemesFilter(values: List = themes) :
- Filter.Group("Themes", values)
-
-private val demographics: Array
- get() = arrayOf("Any", "Shounen", "Shoujo", "Seinen")
-
-class DemographicsFilter(values: Array = demographics) :
- Filter.Select("Demographic", values)
-
-private val statuses: Array
- get() = arrayOf("Any", "Ongoing", "Finished", "Axed/Dropped")
-
-class StatusFilter(values: Array = statuses) :
- Filter.Select("Status", values)
-
-inline fun List>.find() = find { it is T } as? T
diff --git a/src/en/kouhaiwork/src/eu/kanade/tachiyomi/extension/en/kouhaiwork/KouhaiWork.kt b/src/en/kouhaiwork/src/eu/kanade/tachiyomi/extension/en/kouhaiwork/KouhaiWork.kt
deleted file mode 100644
index 7b132c66e..000000000
--- a/src/en/kouhaiwork/src/eu/kanade/tachiyomi/extension/en/kouhaiwork/KouhaiWork.kt
+++ /dev/null
@@ -1,157 +0,0 @@
-package eu.kanade.tachiyomi.extension.en.kouhaiwork
-
-import eu.kanade.tachiyomi.network.GET
-import eu.kanade.tachiyomi.network.POST
-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.HttpSource
-import kotlinx.serialization.json.Json
-import kotlinx.serialization.json.decodeFromJsonElement
-import kotlinx.serialization.json.encodeToJsonElement
-import kotlinx.serialization.json.jsonObject
-import okhttp3.FormBody
-import okhttp3.Response
-import uy.kohesive.injekt.Injekt
-import uy.kohesive.injekt.api.get
-
-class KouhaiWork : HttpSource() {
- override val name = "Kouhai Work"
-
- override val baseUrl = "https://kouhai.work"
-
- override val lang = "en"
-
- override val supportsLatest = true
-
- override val id = 1273675602267580928L
-
- private val json by lazy {
- Json(Injekt.get()) { isLenient = true }
- }
-
- override fun latestUpdatesRequest(page: Int) =
- GET("$API_URL/manga/recent", headers)
-
- override fun latestUpdatesParse(response: Response) =
- response.decode>().map {
- SManga.create().apply {
- url = it.url
- title = it.toString()
- thumbnail_url = it.thumbnail
- }
- }.let { MangasPage(it, false) }
-
- override fun popularMangaRequest(page: Int) =
- GET("$API_URL/manga/all", headers)
-
- override fun popularMangaParse(response: Response) =
- latestUpdatesParse(response)
-
- override fun searchMangaRequest(page: Int, query: String, filters: FilterList) =
- FormBody.Builder().add("search", query).add("tags", filters.json())
- .let { POST("$API_URL/search/manga", headers, it.build()) }
-
- override fun searchMangaParse(response: Response) =
- response.decode>().map {
- SManga.create().apply {
- url = it.url
- title = it.title
- thumbnail_url = it.thumbnail
- }
- }.let { MangasPage(it, false) }
-
- override fun fetchSearchManga(page: Int, query: String, filters: FilterList) =
- if (!query.startsWith(ID_QUERY)) {
- super.fetchSearchManga(page, query, filters)
- } else {
- val id = query.substringAfter(ID_QUERY)
- val req = GET("$API_URL/manga/get/$id", headers)
- client.newCall(req).asObservableSuccess().map {
- val series = it.decode()
- val manga = SManga.create().apply {
- url = series.url
- title = series.title
- thumbnail_url = series.thumbnail
- }
- MangasPage(listOf(manga), false)
- }!!
- }
-
- override fun mangaDetailsRequest(manga: SManga) =
- GET("$API_URL/manga/get/${manga.url}", headers)
-
- override fun mangaDetailsParse(response: Response) =
- SManga.create().apply {
- val series = response.decode()
- description = series.toString()
- author = series.authors?.joinToString()
- artist = series.artists?.joinToString()
- genre = series.tags.joinToString()
- status = when (series.status) {
- "ongoing" -> SManga.ONGOING
- "finished" -> SManga.COMPLETED
- else -> SManga.UNKNOWN
- }
- initialized = true
- }
-
- override fun chapterListRequest(manga: SManga) = mangaDetailsRequest(manga)
-
- override fun chapterListParse(response: Response) =
- response.decode().chapters.map {
- SChapter.create().apply {
- url = it.url
- name = it.toString()
- chapter_number = it.number
- date_upload = it.timestamp
- scanlator = it.groups.joinToString()
- }
- }.reversed()
-
- override fun pageListRequest(chapter: SChapter) =
- GET("$API_URL/chapters/get/${chapter.url}", headers)
-
- override fun pageListParse(response: Response) =
- response.decode("chapter")
- .mapIndexed { idx, img -> Page(idx, "", img.toString()) }
-
- override fun getMangaUrl(manga: SManga) = "$baseUrl/series/${manga.url}"
-
- override fun getChapterUrl(chapter: SChapter) = "$baseUrl/read/${chapter.url}"
-
- override fun getFilterList() = FilterList(
- GenresFilter(),
- ThemesFilter(),
- DemographicsFilter(),
- StatusFilter(),
- )
-
- override fun imageUrlParse(response: Response) =
- throw UnsupportedOperationException()
-
- private fun FilterList.json() = json.encodeToJsonElement(
- KouhaiTagList(
- find()?.state?.filter { it.state }?.map {
- KouhaiTag(it.id, it.name)
- } ?: emptyList(),
- find()?.state?.filter { it.state }?.map {
- KouhaiTag(it.id, it.name)
- } ?: emptyList(),
- find()?.takeIf { it.state != 0 }?.let {
- listOf(KouhaiTag(it.state, it.values[it.state]))
- } ?: emptyList(),
- find()?.takeIf { it.state != 0 }?.let {
- KouhaiTag(it.state - 1, it.values[it.state])
- },
- ),
- ).toString()
-
- private inline fun Response.decode(key: String = "data") =
- json.decodeFromJsonElement(
- json.parseToJsonElement(body.string()).jsonObject[key]!!,
- )
-}