From 26b48d07363c8a47f073619d7db5038a12b02a4b Mon Sep 17 00:00:00 2001
From: jopejoe1 <34899572+jopejoe1@users.noreply.github.com>
Date: Mon, 24 Jan 2022 23:22:15 +1300
Subject: [PATCH] Made Luscious into only one extension (#10563)

* Update Luscious.kt

* Delete multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/luscious directory

* Delete multisrc/overrides/luscious directory

* Made in to singel source

* Update CHANGELOG.md

* Update build.gradle
---
 .../luscious/luscious/src/LusciousFactory.kt  |  37 -----
 .../lusciousapi/src/LusciousAPIFactory.kt     |  37 -----
 .../src/LusciousMembersFactory.kt             |  37 -----
 .../multisrc/luscious/LusciousGenerator.kt    |  26 ----
 src/all/AndroidManifest.xml                   |   4 +
 src/all/CHANGELOG.md                          | 132 ++++++++++++++++++
 src/all/README.md                             |  23 +++
 src/all/build.gradle                          |  13 ++
 .../all}/res/mipmap-hdpi/ic_launcher.png      | Bin
 .../all}/res/mipmap-mdpi/ic_launcher.png      | Bin
 .../all}/res/mipmap-xhdpi/ic_launcher.png     | Bin
 .../all}/res/mipmap-xxhdpi/ic_launcher.png    | Bin
 .../all}/res/mipmap-xxxhdpi/ic_launcher.png   | Bin
 .../all}/res/web_hi_res_512.png               | Bin
 .../extension/all}/luscious/Luscious.kt       |  60 ++++++--
 .../extension/all/luscious/LusciousFactory.kt |  36 +++++
 16 files changed, 257 insertions(+), 148 deletions(-)
 delete mode 100644 multisrc/overrides/luscious/luscious/src/LusciousFactory.kt
 delete mode 100644 multisrc/overrides/luscious/lusciousapi/src/LusciousAPIFactory.kt
 delete mode 100644 multisrc/overrides/luscious/lusciousmembers/src/LusciousMembersFactory.kt
 delete mode 100644 multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/luscious/LusciousGenerator.kt
 create mode 100644 src/all/AndroidManifest.xml
 create mode 100644 src/all/CHANGELOG.md
 create mode 100644 src/all/README.md
 create mode 100644 src/all/build.gradle
 rename {multisrc/overrides/luscious/default => src/all}/res/mipmap-hdpi/ic_launcher.png (100%)
 rename {multisrc/overrides/luscious/default => src/all}/res/mipmap-mdpi/ic_launcher.png (100%)
 rename {multisrc/overrides/luscious/default => src/all}/res/mipmap-xhdpi/ic_launcher.png (100%)
 rename {multisrc/overrides/luscious/default => src/all}/res/mipmap-xxhdpi/ic_launcher.png (100%)
 rename {multisrc/overrides/luscious/default => src/all}/res/mipmap-xxxhdpi/ic_launcher.png (100%)
 rename {multisrc/overrides/luscious/default => src/all}/res/web_hi_res_512.png (100%)
 rename {multisrc/src/main/java/eu/kanade/tachiyomi/multisrc => src/all/src/eu/kanade/tachiyomi/extension/all}/luscious/Luscious.kt (94%)
 create mode 100644 src/all/src/eu/kanade/tachiyomi/extension/all/luscious/LusciousFactory.kt

diff --git a/multisrc/overrides/luscious/luscious/src/LusciousFactory.kt b/multisrc/overrides/luscious/luscious/src/LusciousFactory.kt
deleted file mode 100644
index 8355b47df..000000000
--- a/multisrc/overrides/luscious/luscious/src/LusciousFactory.kt
+++ /dev/null
@@ -1,37 +0,0 @@
-package eu.kanade.tachiyomi.extension.all.luscious
-
-import eu.kanade.tachiyomi.multisrc.luscious.Luscious
-import eu.kanade.tachiyomi.source.Source
-import eu.kanade.tachiyomi.source.SourceFactory
-
-class LusciousFactory : SourceFactory {
-    override fun createSources(): List<Source> = listOf(
-        LusciousEN(),
-        LusciousJA(),
-        LusciousES(),
-        LusciousIT(),
-        LusciousDE(),
-        LusciousFR(),
-        LusciousZH(),
-        LusciousKO(),
-        LusciousOTHER(),
-        LusciousPT(),
-        LusciousTH(),
-        LusciousALL(),
-    )
-}
-class LusciousEN : Luscious("Luscious", "https://www.luscious.net", "en")
-class LusciousJA : Luscious("Luscious", "https://www.luscious.net", "ja")
-class LusciousES : Luscious("Luscious", "https://www.luscious.net", "es")
-class LusciousIT : Luscious("Luscious", "https://www.luscious.net", "it")
-class LusciousDE : Luscious("Luscious", "https://www.luscious.net", "de")
-class LusciousFR : Luscious("Luscious", "https://www.luscious.net", "fr")
-class LusciousZH : Luscious("Luscious", "https://www.luscious.net", "zh")
-class LusciousKO : Luscious("Luscious", "https://www.luscious.net", "ko")
-class LusciousOTHER : Luscious("Luscious", "https://www.luscious.net", "other")
-class LusciousPT : Luscious("Luscious", "https://www.luscious.net", "pt-BR") {
-    // Hardcode the id because the language wasn't specific.
-    override val id: Long = 5826725746643311801
-}
-class LusciousTH : Luscious("Luscious", "https://www.luscious.net", "th")
-class LusciousALL : Luscious("Luscious", "https://www.luscious.net", "all")
diff --git a/multisrc/overrides/luscious/lusciousapi/src/LusciousAPIFactory.kt b/multisrc/overrides/luscious/lusciousapi/src/LusciousAPIFactory.kt
deleted file mode 100644
index d3d6b977f..000000000
--- a/multisrc/overrides/luscious/lusciousapi/src/LusciousAPIFactory.kt
+++ /dev/null
@@ -1,37 +0,0 @@
-package eu.kanade.tachiyomi.extension.all.lusciousapi
-
-import eu.kanade.tachiyomi.multisrc.luscious.Luscious
-import eu.kanade.tachiyomi.source.Source
-import eu.kanade.tachiyomi.source.SourceFactory
-
-class LusciousAPIFactory : SourceFactory {
-    override fun createSources(): List<Source> = listOf(
-        LusciousAPIEN(),
-        LusciousAPIJA(),
-        LusciousAPIES(),
-        LusciousAPIIT(),
-        LusciousAPIDE(),
-        LusciousAPIFR(),
-        LusciousAPIZH(),
-        LusciousAPIKO(),
-        LusciousAPIOTHER(),
-        LusciousAPIPT(),
-        LusciousAPITH(),
-        LusciousAPIALL(),
-    )
-}
-class LusciousAPIEN : Luscious("Luscious (API)", "https://api.luscious.net", "en")
-class LusciousAPIJA : Luscious("Luscious (API)", "https://api.luscious.net", "ja")
-class LusciousAPIES : Luscious("Luscious (API)", "https://api.luscious.net", "es")
-class LusciousAPIIT : Luscious("Luscious (API)", "https://api.luscious.net", "it")
-class LusciousAPIDE : Luscious("Luscious (API)", "https://api.luscious.net", "de")
-class LusciousAPIFR : Luscious("Luscious (API)", "https://api.luscious.net", "fr")
-class LusciousAPIZH : Luscious("Luscious (API)", "https://api.luscious.net", "zh")
-class LusciousAPIKO : Luscious("Luscious (API)", "https://api.luscious.net", "ko")
-class LusciousAPIOTHER : Luscious("Luscious (API)", "https://api.luscious.net", "other")
-class LusciousAPIPT : Luscious("Luscious (API)", "https://api.luscious.net", "pt-BR") {
-    // Hardcode the id because the language wasn't specific.
-    override val id: Long = 7982365826055835382
-}
-class LusciousAPITH : Luscious("Luscious (API)", "https://api.luscious.net", "th")
-class LusciousAPIALL : Luscious("Luscious (API)", "https://api.luscious.net", "all")
diff --git a/multisrc/overrides/luscious/lusciousmembers/src/LusciousMembersFactory.kt b/multisrc/overrides/luscious/lusciousmembers/src/LusciousMembersFactory.kt
deleted file mode 100644
index 69d3c459e..000000000
--- a/multisrc/overrides/luscious/lusciousmembers/src/LusciousMembersFactory.kt
+++ /dev/null
@@ -1,37 +0,0 @@
-package eu.kanade.tachiyomi.extension.all.lusciousmembers
-
-import eu.kanade.tachiyomi.multisrc.luscious.Luscious
-import eu.kanade.tachiyomi.source.Source
-import eu.kanade.tachiyomi.source.SourceFactory
-
-class LusciousMembersFactory : SourceFactory {
-    override fun createSources(): List<Source> = listOf(
-        LusciousMembersEN(),
-        LusciousMembersJA(),
-        LusciousMembersES(),
-        LusciousMembersIT(),
-        LusciousMembersDE(),
-        LusciousMembersFR(),
-        LusciousMembersZH(),
-        LusciousMembersKO(),
-        LusciousMembersOTHER(),
-        LusciousMembersPT(),
-        LusciousMembersTH(),
-        LusciousMembersALL(),
-    )
-}
-class LusciousMembersEN : Luscious("Luscious (Members)", "https://members.luscious.net", "en")
-class LusciousMembersJA : Luscious("Luscious (Members)", "https://members.luscious.net", "ja")
-class LusciousMembersES : Luscious("Luscious (Members)", "https://members.luscious.net", "es")
-class LusciousMembersIT : Luscious("Luscious (Members)", "https://members.luscious.net", "it")
-class LusciousMembersDE : Luscious("Luscious (Members)", "https://members.luscious.net", "de")
-class LusciousMembersFR : Luscious("Luscious (Members)", "https://members.luscious.net", "fr")
-class LusciousMembersZH : Luscious("Luscious (Members)", "https://members.luscious.net", "zh")
-class LusciousMembersKO : Luscious("Luscious (Members)", "https://members.luscious.net", "ko")
-class LusciousMembersOTHER : Luscious("Luscious (Members)", "https://members.luscious.net", "other")
-class LusciousMembersPT : Luscious("Luscious (Members)", "https://members.luscious.net", "pt-BR") {
-    // Hardcode the id because the language wasn't specific.
-    override val id: Long = 6917849530594229844
-}
-class LusciousMembersTH : Luscious("Luscious (Members)", "https://members.luscious.net", "th")
-class LusciousMembersALL : Luscious("Luscious (Members)", "https://members.luscious.net", "all")
diff --git a/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/luscious/LusciousGenerator.kt b/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/luscious/LusciousGenerator.kt
deleted file mode 100644
index d821b57c5..000000000
--- a/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/luscious/LusciousGenerator.kt
+++ /dev/null
@@ -1,26 +0,0 @@
-package eu.kanade.tachiyomi.multisrc.luscious
-
-import generator.ThemeSourceData.MultiLang
-import generator.ThemeSourceGenerator
-
-class LusciousGenerator : ThemeSourceGenerator {
-
-    override val themePkg = "luscious"
-
-    override val themeClass = "Luscious"
-
-    override val baseVersionCode: Int = 15
-
-    override val sources = listOf(
-        MultiLang("Luscious", "https://www.luscious.net", listOf("en", "ja", "es", "it", "de", "fr", "zh", "ko", "other", "pt-BR", "th", "all"), isNsfw = true, className = "LusciousFactory", overrideVersionCode = 2),
-        MultiLang("Luscious (Members)", "https://members.luscious.net", listOf("en", "ja", "es", "it", "de", "fr", "zh", "ko", "other", "pt-BR", "th", "all"), isNsfw = true, className = "LusciousMembersFactory", pkgName = "lusciousmembers"), // Requires Account
-        MultiLang("Luscious (API)", "https://api.luscious.net", listOf("en", "ja", "es", "it", "de", "fr", "zh", "ko", "other", "pt-BR", "th", "all"), isNsfw = true, className = "LusciousAPIFactory", pkgName = "lusciousapi")
-    )
-
-    companion object {
-        @JvmStatic
-        fun main(args: Array<String>) {
-            LusciousGenerator().createAll()
-        }
-    }
-}
diff --git a/src/all/AndroidManifest.xml b/src/all/AndroidManifest.xml
new file mode 100644
index 000000000..7f8a6d5d3
--- /dev/null
+++ b/src/all/AndroidManifest.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+package="eu.kanade.tachiyomi.extension">
+</manifest>
\ No newline at end of file
diff --git a/src/all/CHANGELOG.md b/src/all/CHANGELOG.md
new file mode 100644
index 000000000..5fccd58c1
--- /dev/null
+++ b/src/all/CHANGELOG.md
@@ -0,0 +1,132 @@
+## 1.2.18
+
+### Features
+
+* Merged Luscious extensions
+* added removed extensions as mirrors
+
+### Fix
+
+* webp images downloading as .bin files
+
+## 1.2.17
+
+### Refactor
+
+* replace Gson with kotlinx.serialization
+
+## 1.2.16
+
+### Fix
+
+* Gson conversion mistake
+
+## 1.2.15
+
+### Fix
+
+* Loading of image URLs that are missing `https` at the beginning
+
+## 1.2.14
+
+### Features
+
+* Chapter Number as prefix
+* Missing sort option `Search Score`
+
+## 1.2.13
+
+### Fix
+
+* Change pr to pt-BR
+
+## 1.2.12
+
+### Features
+
+* Chapter release date
+* Selection filter
+
+## 1.2.11
+
+### Features
+
+* Uploader Filter
+* Favourite filter
+
+### Fix
+
+* Api in webview
+
+## 1.2.10
+
+### Fix
+
+* Latest sort order
+
+## 1.2.9
+
+### Features
+
+* More genres as filter options
+
+## 1.2.8
+
+### Fix
+
+* Android 8 Support
+
+## 1.2.7
+
+### Features
+
+* Unfiltered Language option
+* Filter by year is now dynamic
+* Page sort preference
+* Tag filter is now text input
+
+
+## 1.2.6
+
+### Features
+
+* Merge Chapter preference
+* Resolution preference
+
+## 1.2.5
+
+### Features
+
+* Moved to API
+* Every page is now a Chapter
+* Album Size Filter
+* Restrict Genres Filter
+* More sort filter options
+
+### Fix
+
+* Details & tags in members mirror
+
+## 1.2.4
+
+### Fix
+
+* Changed image server
+
+## 1.2.3
+
+### Features
+
+* added api & members mirror
+
+## 1.2.2
+
+### Fix
+
+* Page order
+
+## 1.2.1
+
+### Features
+
+* first version
diff --git a/src/all/README.md b/src/all/README.md
new file mode 100644
index 000000000..db324677a
--- /dev/null
+++ b/src/all/README.md
@@ -0,0 +1,23 @@
+# Luscious
+
+Table of Content
+- [FAQ](#FAQ)
+
+[Uncomment this if needed; and replace &#40; and &#41; with ( and )]: <> (- [Guides]&#40;#Guides&#41;)
+
+Don't find the question you are look for go check out our general FAQs and Guides over at [Extension FAQ](https://tachiyomi.org/help/faq/#extensions) or [Getting Started](https://tachiyomi.org/help/guides/getting-started/#installation)
+
+## FAQ
+#### Why is each page a Chapter?
+New pages can always be added to a Luscious album by the creator of the album.
+
+#### Why do i get the errors like `Index: 2, Size: 2`?
+This happens when the manga is not supporting  your current resolution.
+
+#### Why do features that require login not work even when im logged in?
+Features that require login only work when the mirror is changed to the Members mirror.
+
+#### Where did the other Luscious extensions go?
+They are now mirror options in the Luscious extension.
+
+[Uncomment this if needed]: <> (## Guides)
\ No newline at end of file
diff --git a/src/all/build.gradle b/src/all/build.gradle
new file mode 100644
index 000000000..62c5c2957
--- /dev/null
+++ b/src/all/build.gradle
@@ -0,0 +1,13 @@
+apply plugin: 'com.android.application'
+apply plugin: 'kotlin-android'
+apply plugin: 'kotlinx-serialization'
+
+ext {
+    extName = 'Luscious'
+    pkgNameSuffix = 'all.luscious'
+    extClass = '.LusciousFactory'
+    extVersionCode = 18
+    isNsfw = true
+}
+
+apply from: "$rootDir/common.gradle"
diff --git a/multisrc/overrides/luscious/default/res/mipmap-hdpi/ic_launcher.png b/src/all/res/mipmap-hdpi/ic_launcher.png
similarity index 100%
rename from multisrc/overrides/luscious/default/res/mipmap-hdpi/ic_launcher.png
rename to src/all/res/mipmap-hdpi/ic_launcher.png
diff --git a/multisrc/overrides/luscious/default/res/mipmap-mdpi/ic_launcher.png b/src/all/res/mipmap-mdpi/ic_launcher.png
similarity index 100%
rename from multisrc/overrides/luscious/default/res/mipmap-mdpi/ic_launcher.png
rename to src/all/res/mipmap-mdpi/ic_launcher.png
diff --git a/multisrc/overrides/luscious/default/res/mipmap-xhdpi/ic_launcher.png b/src/all/res/mipmap-xhdpi/ic_launcher.png
similarity index 100%
rename from multisrc/overrides/luscious/default/res/mipmap-xhdpi/ic_launcher.png
rename to src/all/res/mipmap-xhdpi/ic_launcher.png
diff --git a/multisrc/overrides/luscious/default/res/mipmap-xxhdpi/ic_launcher.png b/src/all/res/mipmap-xxhdpi/ic_launcher.png
similarity index 100%
rename from multisrc/overrides/luscious/default/res/mipmap-xxhdpi/ic_launcher.png
rename to src/all/res/mipmap-xxhdpi/ic_launcher.png
diff --git a/multisrc/overrides/luscious/default/res/mipmap-xxxhdpi/ic_launcher.png b/src/all/res/mipmap-xxxhdpi/ic_launcher.png
similarity index 100%
rename from multisrc/overrides/luscious/default/res/mipmap-xxxhdpi/ic_launcher.png
rename to src/all/res/mipmap-xxxhdpi/ic_launcher.png
diff --git a/multisrc/overrides/luscious/default/res/web_hi_res_512.png b/src/all/res/web_hi_res_512.png
similarity index 100%
rename from multisrc/overrides/luscious/default/res/web_hi_res_512.png
rename to src/all/res/web_hi_res_512.png
diff --git a/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/luscious/Luscious.kt b/src/all/src/eu/kanade/tachiyomi/extension/all/luscious/Luscious.kt
similarity index 94%
rename from multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/luscious/Luscious.kt
rename to src/all/src/eu/kanade/tachiyomi/extension/all/luscious/Luscious.kt
index 7724408b3..e8db1c207 100644
--- a/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/luscious/Luscious.kt
+++ b/src/all/src/eu/kanade/tachiyomi/extension/all/luscious/Luscious.kt
@@ -1,4 +1,4 @@
-package eu.kanade.tachiyomi.multisrc.luscious
+package eu.kanade.tachiyomi.extension.all.luscious
 
 import android.app.Application
 import android.content.SharedPreferences
@@ -30,9 +30,12 @@ import kotlinx.serialization.json.put
 import kotlinx.serialization.json.putJsonArray
 import kotlinx.serialization.json.putJsonObject
 import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
+import okhttp3.Interceptor
+import okhttp3.MediaType.Companion.toMediaTypeOrNull
 import okhttp3.OkHttpClient
 import okhttp3.Request
 import okhttp3.Response
+import okhttp3.ResponseBody.Companion.toResponseBody
 import rx.Observable
 import uy.kohesive.injekt.Injekt
 import uy.kohesive.injekt.api.get
@@ -40,21 +43,37 @@ import uy.kohesive.injekt.injectLazy
 import java.util.Calendar
 
 abstract class Luscious(
-    override val name: String,
-    override val baseUrl: String,
     final override val lang: String
 ) : ConfigurableSource, HttpSource() {
 
-    // Based on Luscious single source extension form https://github.com/tachiyomiorg/tachiyomi-extensions/commit/aacf56d0c0ddb173372aac69d798ae998f178377
-    // with modification to make it support multisrc
-
     override val supportsLatest: Boolean = true
+    override val name: String = "Luscious"
+
+    private val preferences: SharedPreferences by lazy {
+        Injekt.get<Application>().getSharedPreferences("source_$id", 0x0000)
+    }
+
+    override val baseUrl: String = getMirrorPref()!!
 
     private val apiBaseUrl: String = "$baseUrl/graphql/nobatch/"
 
     private val json: Json by injectLazy()
 
-    override val client: OkHttpClient = network.cloudflareClient
+    override val client: OkHttpClient
+        get() = network.cloudflareClient.newBuilder()
+            .addNetworkInterceptor(rewriteOctetStream)
+            .build()
+
+    private val rewriteOctetStream: Interceptor = Interceptor { chain ->
+        val originalResponse: Response = chain.proceed(chain.request())
+        if (originalResponse.headers("Content-Type").contains("application/octet-stream") && originalResponse.request.url.toString().contains(".webp")) {
+            val orgBody = originalResponse.body!!.bytes()
+            val newBody = orgBody.toResponseBody("image/webp".toMediaTypeOrNull())
+            originalResponse.newBuilder()
+                .body(newBody)
+                .build()
+        } else originalResponse
+    }
 
     private val lusLang: String = toLusLang(lang)
 
@@ -75,10 +94,6 @@ abstract class Luscious(
         }
     }
 
-    private val preferences: SharedPreferences by lazy {
-        Injekt.get<Application>().getSharedPreferences("source_$id", 0x0000)
-    }
-
     // Common
 
     private fun buildAlbumListRequestInput(page: Int, filters: FilterList, query: String = ""): JsonObject {
@@ -820,6 +835,12 @@ abstract class Luscious(
         private val SORT_PREF_ENTRIES = arrayOf("Position", "Date", "Rating")
         private val SORT_PREF_ENTRY_VALUES = arrayOf("position", "date_newest", "rating_all_time")
         private val SORT_PREF_DEFAULT_VALUE = SORT_PREF_ENTRY_VALUES[0]
+
+        private const val MIRROR_PREF_KEY = "MIRROR"
+        private const val MIRROR_PREF_TITLE = "Mirror"
+        private val MIRROR_PREF_ENTRIES = arrayOf("Guest", "API", "Members")
+        private val MIRROR_PREF_ENTRY_VALUES = arrayOf("https://www.luscious.net", "https://api.luscious.net", "https://members.luscious.net")
+        private val MIRROR_PREF_DEFAULT_VALUE = MIRROR_PREF_ENTRY_VALUES[0]
     }
 
     override fun setupPreferenceScreen(screen: PreferenceScreen) {
@@ -864,12 +885,29 @@ abstract class Luscious(
                 preferences.edit().putBoolean("${MERGE_CHAPTER_PREF_KEY}_$lang", checkValue).commit()
             }
         }
+        val mirrorPref = ListPreference(screen.context).apply {
+            key = "${MIRROR_PREF_KEY}_$lang"
+            title = MIRROR_PREF_TITLE
+            entries = MIRROR_PREF_ENTRIES
+            entryValues = MIRROR_PREF_ENTRY_VALUES
+            setDefaultValue(MIRROR_PREF_DEFAULT_VALUE)
+            summary = "%s"
+
+            setOnPreferenceChangeListener { _, newValue ->
+                val selected = newValue as String
+                val index = findIndexOfValue(selected)
+                val entry = entryValues[index] as String
+                preferences.edit().putString("${MIRROR_PREF_KEY}_$lang", entry).commit()
+            }
+        }
         screen.addPreference(resolutionPref)
         screen.addPreference(sortPref)
         screen.addPreference(mergeChapterPref)
+        screen.addPreference(mirrorPref)
     }
 
     private fun getMergeChapterPref(): Boolean = preferences.getBoolean("${MERGE_CHAPTER_PREF_KEY}_$lang", MERGE_CHAPTER_PREF_DEFAULT_VALUE)
     private fun getResolutionPref(): String? = preferences.getString("${RESOLUTION_PREF_KEY}_$lang", RESOLUTION_PREF_DEFAULT_VALUE)
     private fun getSortPref(): String? = preferences.getString("${SORT_PREF_KEY}_$lang", SORT_PREF_DEFAULT_VALUE)
+    private fun getMirrorPref(): String? = preferences.getString("${MIRROR_PREF_KEY}_$lang", MIRROR_PREF_DEFAULT_VALUE)
 }
diff --git a/src/all/src/eu/kanade/tachiyomi/extension/all/luscious/LusciousFactory.kt b/src/all/src/eu/kanade/tachiyomi/extension/all/luscious/LusciousFactory.kt
new file mode 100644
index 000000000..302499157
--- /dev/null
+++ b/src/all/src/eu/kanade/tachiyomi/extension/all/luscious/LusciousFactory.kt
@@ -0,0 +1,36 @@
+package eu.kanade.tachiyomi.extension.all.luscious
+
+import eu.kanade.tachiyomi.source.Source
+import eu.kanade.tachiyomi.source.SourceFactory
+
+class LusciousFactory : SourceFactory {
+    override fun createSources(): List<Source> = listOf(
+        LusciousEN(),
+        LusciousJA(),
+        LusciousES(),
+        LusciousIT(),
+        LusciousDE(),
+        LusciousFR(),
+        LusciousZH(),
+        LusciousKO(),
+        LusciousOTHER(),
+        LusciousPT(),
+        LusciousTH(),
+        LusciousALL(),
+    )
+}
+class LusciousEN : Luscious("en")
+class LusciousJA : Luscious("ja")
+class LusciousES : Luscious("es")
+class LusciousIT : Luscious("it")
+class LusciousDE : Luscious("de")
+class LusciousFR : Luscious("fr")
+class LusciousZH : Luscious("zh")
+class LusciousKO : Luscious("ko")
+class LusciousOTHER : Luscious("other")
+class LusciousPT : Luscious("pt-BR") {
+    // Hardcode the id because the language wasn't specific.
+    override val id: Long = 5826725746643311801
+}
+class LusciousTH : Luscious("th")
+class LusciousALL : Luscious("all")