new theme: Otaku Sanctuary (#14802)
* new theme: Otaku Sanctuary * linting i guess * i LOVE linting * add run configuration * rename and implement fixes from my other PR * make class open * otakusantheme -> otakusanctuary
							
								
								
									
										11
									
								
								.run/OtakuSanctuaryGenerator.run.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,11 @@
 | 
			
		||||
<component name="ProjectRunConfigurationManager">
 | 
			
		||||
  <configuration default="false" name="OtakuSanctuaryGenerator" type="JetRunConfigurationType" nameIsGenerated="true">
 | 
			
		||||
    <module name="tachiyomi-extensions.multisrc.main" />
 | 
			
		||||
    <option name="MAIN_CLASS_NAME" value="eu.kanade.tachiyomi.multisrc.otakusanctuary.OtakuSanctuaryGenerator" />
 | 
			
		||||
    <method v="2">
 | 
			
		||||
      <option name="Make" enabled="true" />
 | 
			
		||||
      <option name="Gradle.BeforeRunTask" enabled="true" tasks="ktFormat" externalProjectPath="$PROJECT_DIR$/multisrc" vmOptions="" scriptParameters="-Ptheme=otakusanctuary" />
 | 
			
		||||
      <option name="Gradle.BeforeRunTask" enabled="true" tasks="ktLint" externalProjectPath="$PROJECT_DIR$/multisrc" vmOptions="" scriptParameters="-Ptheme=otakusanctuary" />
 | 
			
		||||
    </method>
 | 
			
		||||
  </configuration>
 | 
			
		||||
</component>
 | 
			
		||||
| 
		 After Width: | Height: | Size: 5.7 KiB  | 
| 
		 After Width: | Height: | Size: 2.9 KiB  | 
| 
		 After Width: | Height: | Size: 9.0 KiB  | 
| 
		 After Width: | Height: | Size: 18 KiB  | 
| 
		 After Width: | Height: | Size: 30 KiB  | 
| 
		 After Width: | Height: | Size: 200 KiB  | 
| 
		 After Width: | Height: | Size: 5.2 KiB  | 
| 
		 After Width: | Height: | Size: 2.6 KiB  | 
| 
		 After Width: | Height: | Size: 8.4 KiB  | 
| 
		 After Width: | Height: | Size: 17 KiB  | 
| 
		 After Width: | Height: | Size: 28 KiB  | 
| 
		 After Width: | Height: | Size: 194 KiB  | 
@ -0,0 +1,214 @@
 | 
			
		||||
package eu.kanade.tachiyomi.multisrc.otakusanctuary
 | 
			
		||||
 | 
			
		||||
import eu.kanade.tachiyomi.network.GET
 | 
			
		||||
import eu.kanade.tachiyomi.network.POST
 | 
			
		||||
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 eu.kanade.tachiyomi.util.asJsoup
 | 
			
		||||
import kotlinx.serialization.decodeFromString
 | 
			
		||||
import kotlinx.serialization.json.Json
 | 
			
		||||
import kotlinx.serialization.json.jsonObject
 | 
			
		||||
import kotlinx.serialization.json.jsonPrimitive
 | 
			
		||||
import okhttp3.FormBody
 | 
			
		||||
import okhttp3.Headers
 | 
			
		||||
import okhttp3.HttpUrl.Companion.toHttpUrl
 | 
			
		||||
import okhttp3.Request
 | 
			
		||||
import okhttp3.Response
 | 
			
		||||
import org.jsoup.select.Elements
 | 
			
		||||
import org.jsoup.select.Evaluator
 | 
			
		||||
import uy.kohesive.injekt.injectLazy
 | 
			
		||||
import java.text.SimpleDateFormat
 | 
			
		||||
import java.util.Calendar
 | 
			
		||||
import java.util.Locale
 | 
			
		||||
import java.util.TimeZone
 | 
			
		||||
 | 
			
		||||
open class OtakuSanctuary(
 | 
			
		||||
    override val name: String,
 | 
			
		||||
    override val baseUrl: String,
 | 
			
		||||
    override val lang: String,
 | 
			
		||||
) : HttpSource() {
 | 
			
		||||
 | 
			
		||||
    override val supportsLatest = false
 | 
			
		||||
 | 
			
		||||
    override val client = network.cloudflareClient
 | 
			
		||||
 | 
			
		||||
    override fun headersBuilder(): Headers.Builder = super.headersBuilder().add("Referer", "$baseUrl/")
 | 
			
		||||
 | 
			
		||||
    private val helper = OtakuSanctuaryHelper(lang)
 | 
			
		||||
 | 
			
		||||
    private val json: Json by injectLazy()
 | 
			
		||||
 | 
			
		||||
    // There's no popular list, this will have to do
 | 
			
		||||
    override fun popularMangaRequest(page: Int) = POST(
 | 
			
		||||
        "$baseUrl/Manga/Newest",
 | 
			
		||||
        headers,
 | 
			
		||||
        FormBody.Builder().apply {
 | 
			
		||||
            add("Lang", helper.otakusanLang())
 | 
			
		||||
            add("PageSize", "24")
 | 
			
		||||
        }.build()
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    private fun parseMangaCollection(elements: Elements): List<SManga> {
 | 
			
		||||
        val page = emptyList<SManga>().toMutableList()
 | 
			
		||||
 | 
			
		||||
        for (element in elements) {
 | 
			
		||||
            val url = element.select("div.mdl-card__title a").first().attr("abs:href")
 | 
			
		||||
            // ignore external chapters
 | 
			
		||||
            if (url.toHttpUrl().host != baseUrl.toHttpUrl().host) {
 | 
			
		||||
                continue
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // ignore web novels/light novels
 | 
			
		||||
            val variant = element.select("div.mdl-card__supporting-text div.text-overflow-90 a").text()
 | 
			
		||||
            if (variant.contains("Novel")) {
 | 
			
		||||
                continue
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // ignore languages that dont match current ext
 | 
			
		||||
            val language = element.select("img.flag").attr("abs:src")
 | 
			
		||||
                .substringAfter("flags/")
 | 
			
		||||
                .substringBefore(".png")
 | 
			
		||||
            if (helper.otakusanLang() != "all" && language != helper.otakusanLang()) {
 | 
			
		||||
                continue
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            page += SManga.create().apply {
 | 
			
		||||
                setUrlWithoutDomain(url)
 | 
			
		||||
                title = element.select("div.mdl-card__supporting-text a[target=_blank]").text()
 | 
			
		||||
                    .replaceFirstChar { it.titlecase() }
 | 
			
		||||
                thumbnail_url = element.select("div.container-3-4.background-contain img").first().attr("abs:src")
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return page
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override fun popularMangaParse(response: Response): MangasPage {
 | 
			
		||||
        val document = response.asJsoup()
 | 
			
		||||
        val collection = document.select("div.mdl-card")
 | 
			
		||||
        return MangasPage(parseMangaCollection(collection), collection.size >= 24)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override fun latestUpdatesRequest(page: Int) = throw Exception("Unused")
 | 
			
		||||
 | 
			
		||||
    override fun latestUpdatesParse(response: Response) = throw Exception("Unused")
 | 
			
		||||
 | 
			
		||||
    override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request =
 | 
			
		||||
        GET(
 | 
			
		||||
            baseUrl.toHttpUrl().newBuilder().apply {
 | 
			
		||||
                addPathSegments("Home/Search")
 | 
			
		||||
                addQueryParameter("search", query)
 | 
			
		||||
            }.build().toString(),
 | 
			
		||||
            headers
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
    override fun searchMangaParse(response: Response): MangasPage {
 | 
			
		||||
        val document = response.asJsoup()
 | 
			
		||||
        val collection = document.select("div.collection:has(.group-header:contains(Manga)) div.mdl-card")
 | 
			
		||||
        return MangasPage(parseMangaCollection(collection), false)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override fun mangaDetailsParse(response: Response): SManga {
 | 
			
		||||
        val document = response.asJsoup()
 | 
			
		||||
 | 
			
		||||
        return SManga.create().apply {
 | 
			
		||||
            title = document.select("h1.title.text-lg-left.text-overflow-2-line")
 | 
			
		||||
                .text()
 | 
			
		||||
                .replaceFirstChar { it.titlecase() }
 | 
			
		||||
            author = document.select("tr:contains(Tác Giả) a.capitalize").first().text()
 | 
			
		||||
                .replaceFirstChar { it.titlecase() }
 | 
			
		||||
            description = document.select("div.summary p").joinToString("\n") {
 | 
			
		||||
                it.run {
 | 
			
		||||
                    select(Evaluator.Tag("br")).prepend("\\n")
 | 
			
		||||
                    this.text().replace("\\n", "\n").replace("\n ", "\n")
 | 
			
		||||
                }
 | 
			
		||||
            }.trim()
 | 
			
		||||
            genre = document.select("div.genres a").joinToString { it.text() }
 | 
			
		||||
            thumbnail_url = document.select("div.container-3-4.background-contain img").attr("abs:src")
 | 
			
		||||
 | 
			
		||||
            val statusString = document.select("tr:contains(Tình Trạng) td").first().text().trim()
 | 
			
		||||
            status = when (statusString) {
 | 
			
		||||
                "Ongoing" -> SManga.ONGOING
 | 
			
		||||
                "Done" -> SManga.COMPLETED
 | 
			
		||||
                else -> SManga.UNKNOWN
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private val dateFormat = SimpleDateFormat("dd/MM/yyyy", Locale.US).apply {
 | 
			
		||||
        timeZone = TimeZone.getTimeZone("Asia/Ho_Chi_Minh")
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun parseDate(date: String): Long {
 | 
			
		||||
        if (date.contains("cách đây")) {
 | 
			
		||||
            val number = Regex("""(\d+)""").find(date)?.value?.toIntOrNull() ?: return 0
 | 
			
		||||
            val cal = Calendar.getInstance()
 | 
			
		||||
 | 
			
		||||
            return when {
 | 
			
		||||
                date.contains("ngày") -> cal.apply { add(Calendar.DAY_OF_MONTH, -number) }.timeInMillis
 | 
			
		||||
                date.contains("tiếng") -> cal.apply { add(Calendar.HOUR, -number) }.timeInMillis
 | 
			
		||||
                date.contains("phút") -> cal.apply { add(Calendar.MINUTE, -number) }.timeInMillis
 | 
			
		||||
                date.contains("giây") -> cal.apply { add(Calendar.SECOND, -number) }.timeInMillis
 | 
			
		||||
                else -> 0L
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            return kotlin.runCatching { dateFormat.parse(date)?.time }.getOrNull() ?: 0L
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override fun chapterListParse(response: Response): List<SChapter> {
 | 
			
		||||
        val document = response.asJsoup()
 | 
			
		||||
 | 
			
		||||
        return document.select("tr.chapter").map {
 | 
			
		||||
            val cells = it.select("td")
 | 
			
		||||
            SChapter.create().apply {
 | 
			
		||||
                setUrlWithoutDomain(cells[1].select("a").attr("href"))
 | 
			
		||||
                name = cells[1].text()
 | 
			
		||||
                date_upload = parseDate(cells[3].text())
 | 
			
		||||
                chapter_number = cells[0].text().toFloatOrNull() ?: -1f
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override fun imageUrlParse(response: Response) = throw UnsupportedOperationException("Not used")
 | 
			
		||||
 | 
			
		||||
    override fun pageListParse(response: Response): List<Page> {
 | 
			
		||||
        val document = response.asJsoup()
 | 
			
		||||
 | 
			
		||||
        val vi = document.select("#dataip").attr("value")
 | 
			
		||||
        val numericId = document.select("#inpit-c").attr("data-chapter-id")
 | 
			
		||||
 | 
			
		||||
        val rawPagesArray = try {
 | 
			
		||||
            val data = json.parseToJsonElement(
 | 
			
		||||
                client.newCall(
 | 
			
		||||
                    POST(
 | 
			
		||||
                        "$baseUrl/Manga/CheckingAlternate",
 | 
			
		||||
                        headers,
 | 
			
		||||
                        FormBody.Builder().add("chapId", numericId).build()
 | 
			
		||||
                    )
 | 
			
		||||
                ).execute().body!!.string()
 | 
			
		||||
            )
 | 
			
		||||
 | 
			
		||||
            data.jsonObject["Content"]!!.jsonPrimitive.content
 | 
			
		||||
        } catch (_: Exception) {
 | 
			
		||||
            val data = json.parseToJsonElement(
 | 
			
		||||
                client.newCall(
 | 
			
		||||
                    POST(
 | 
			
		||||
                        "$baseUrl/Manga/UpdateView",
 | 
			
		||||
                        headers,
 | 
			
		||||
                        FormBody.Builder().add("chapId", numericId).build()
 | 
			
		||||
                    )
 | 
			
		||||
                ).execute().body!!.string()
 | 
			
		||||
            )
 | 
			
		||||
 | 
			
		||||
            data.jsonObject["view"]!!.jsonPrimitive.content
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return json.decodeFromString<List<String>>(rawPagesArray).mapIndexed { idx, it ->
 | 
			
		||||
            Page(idx, imageUrl = helper.processUrl(it, vi))
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,35 @@
 | 
			
		||||
package eu.kanade.tachiyomi.multisrc.otakusanctuary
 | 
			
		||||
 | 
			
		||||
import generator.ThemeSourceData.MultiLang
 | 
			
		||||
import generator.ThemeSourceGenerator
 | 
			
		||||
 | 
			
		||||
class OtakuSanctuaryGenerator : ThemeSourceGenerator {
 | 
			
		||||
 | 
			
		||||
    override val themePkg = "otakusanctuary"
 | 
			
		||||
 | 
			
		||||
    override val themeClass = "OtakuSanctuary"
 | 
			
		||||
 | 
			
		||||
    override val baseVersionCode: Int = 1
 | 
			
		||||
 | 
			
		||||
    override val sources = listOf(
 | 
			
		||||
        MultiLang(
 | 
			
		||||
            "Otaku Sanctuary",
 | 
			
		||||
            "https://otakusan.net",
 | 
			
		||||
            listOf("all", "vi", "en", "it", "fr", "es"),
 | 
			
		||||
            isNsfw = true
 | 
			
		||||
        ),
 | 
			
		||||
        MultiLang(
 | 
			
		||||
            "MyRockManga",
 | 
			
		||||
            "https://myrockmanga.com",
 | 
			
		||||
            listOf("all", "vi", "en", "it", "fr", "es"),
 | 
			
		||||
            isNsfw = true
 | 
			
		||||
        ),
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    companion object {
 | 
			
		||||
        @JvmStatic
 | 
			
		||||
        fun main(args: Array<String>) {
 | 
			
		||||
            OtakuSanctuaryGenerator().createAll()
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,158 @@
 | 
			
		||||
package eu.kanade.tachiyomi.multisrc.otakusanctuary
 | 
			
		||||
 | 
			
		||||
import okhttp3.HttpUrl.Companion.toHttpUrl
 | 
			
		||||
 | 
			
		||||
class OtakuSanctuaryHelper(private val lang: String) {
 | 
			
		||||
 | 
			
		||||
    fun otakusanLang() = when (lang) {
 | 
			
		||||
        "vi" -> "vn"
 | 
			
		||||
        "en" -> "us"
 | 
			
		||||
        else -> lang
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fun processUrl(url: String, vi: String): String {
 | 
			
		||||
        var url = url.replace("_h_", "http")
 | 
			
		||||
            .replace("_e_", "/extendContent/Manga")
 | 
			
		||||
            .replace("_r_", "/extendContent/MangaRaw")
 | 
			
		||||
 | 
			
		||||
        if (url.startsWith("//")) {
 | 
			
		||||
            url = "https:$url"
 | 
			
		||||
        }
 | 
			
		||||
        if (url.contains("drive.google.com")) {
 | 
			
		||||
            return url
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        url = when (url.slice(0..4)) {
 | 
			
		||||
            "[GDP]" -> url.replace("[GDP]", "https://drive.google.com/uc?export=view&id=")
 | 
			
		||||
            "[GDT]" -> if (otakusanLang() == "us") {
 | 
			
		||||
                url.replace("image2.otakuscan.net", "image3.shopotaku.net")
 | 
			
		||||
                    .replace("image2.otakusan.net", "image3.shopotaku.net")
 | 
			
		||||
            } else {
 | 
			
		||||
                url
 | 
			
		||||
            }
 | 
			
		||||
            "[IS1]" -> {
 | 
			
		||||
                var url = url.replace("[IS1]", "https://imagepi.otakuscan.net/")
 | 
			
		||||
                if (url.contains("vi") && url.contains("otakusan.net_")) {
 | 
			
		||||
                    url
 | 
			
		||||
                } else {
 | 
			
		||||
                    url.toHttpUrl().newBuilder().apply {
 | 
			
		||||
                        addQueryParameter("vi", vi)
 | 
			
		||||
                    }.build().toString()
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            "[IS3]" -> url.replace("[IS3]", "https://image3.otakusan.net/")
 | 
			
		||||
            "[IO3]" -> url.replace("[IO3]", "http://image3.shopotaku.net/")
 | 
			
		||||
            else -> url
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (url.contains("/Content/Workshop") || url.contains("otakusan") || url.contains("myrockmanga")) {
 | 
			
		||||
            return url
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (url.contains("file-bato-orig.anyacg.co")) {
 | 
			
		||||
            url = url.replace("file-bato-orig.anyacg.co", "file-bato-orig.bato.to")
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (url.contains("file-comic")) {
 | 
			
		||||
            if (url.contains("file-comic-1")) {
 | 
			
		||||
                url = url.replace("file-comic-1.anyacg.co", "z-img-01.mangapark.net")
 | 
			
		||||
            }
 | 
			
		||||
            if (url.contains("file-comic-2")) {
 | 
			
		||||
                url = url.replace("file-comic-2.anyacg.co", "z-img-02.mangapark.net")
 | 
			
		||||
            }
 | 
			
		||||
            if (url.contains("file-comic-3")) {
 | 
			
		||||
                url = url.replace("file-comic-3.anyacg.co", "z-img-03.mangapark.net")
 | 
			
		||||
            }
 | 
			
		||||
            if (url.contains("file-comic-4")) {
 | 
			
		||||
                url = url.replace("file-comic-4.anyacg.co", "z-img-04.mangapark.net")
 | 
			
		||||
            }
 | 
			
		||||
            if (url.contains("file-comic-5")) {
 | 
			
		||||
                url = url.replace("file-comic-5.anyacg.co", "z-img-05.mangapark.net")
 | 
			
		||||
            }
 | 
			
		||||
            if (url.contains("file-comic-6")) {
 | 
			
		||||
                url = url.replace("file-comic-6.anyacg.co", "z-img-06.mangapark.net")
 | 
			
		||||
            }
 | 
			
		||||
            if (url.contains("file-comic-9")) {
 | 
			
		||||
                url = url.replace("file-comic-9.anyacg.co", "z-img-09.mangapark.net")
 | 
			
		||||
            }
 | 
			
		||||
            if (url.contains("file-comic-10")) {
 | 
			
		||||
                url = url.replace("file-comic-10.anyacg.co", "z-img-10.mangapark.net")
 | 
			
		||||
            }
 | 
			
		||||
            if (url.contains("file-comic-99")) {
 | 
			
		||||
                url = url.replace("file-comic-99.anyacg.co/uploads", "file-bato-0001.bato.to")
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (url.contains("cdn.nettruyen.com")) {
 | 
			
		||||
            url = url.replace(
 | 
			
		||||
                "cdn.nettruyen.com/Data/Images/",
 | 
			
		||||
                "truyen.cloud/data/images/",
 | 
			
		||||
            )
 | 
			
		||||
        }
 | 
			
		||||
        if (url.contains("url=")) {
 | 
			
		||||
            url = url.substringAfter("url=")
 | 
			
		||||
        }
 | 
			
		||||
        if (url.contains("blogspot") || url.contains("fshare")) {
 | 
			
		||||
            url = url.replace("http:", "https:")
 | 
			
		||||
        }
 | 
			
		||||
        if (url.contains("blogspot") && !url.contains("http")) {
 | 
			
		||||
            url = "https://$url"
 | 
			
		||||
        }
 | 
			
		||||
        if (url.contains("app/manga/uploads/") && !url.contains("http")) {
 | 
			
		||||
            url = "https://lhscan.net$url"
 | 
			
		||||
        }
 | 
			
		||||
        url = url.replace("//cdn.adtrue.com/rtb/async.js", "")
 | 
			
		||||
 | 
			
		||||
        if (url.contains(".webp")) {
 | 
			
		||||
            url = "https://otakusan.net/api/Value/ImageSyncing?ip=34512351".toHttpUrl().newBuilder()
 | 
			
		||||
                .apply {
 | 
			
		||||
                    addQueryParameter("url", url)
 | 
			
		||||
                }.build().toString()
 | 
			
		||||
        } else if (
 | 
			
		||||
            (
 | 
			
		||||
                url.contains("merakiscans") ||
 | 
			
		||||
                    url.contains("mangazuki") ||
 | 
			
		||||
                    url.contains("ninjascans") ||
 | 
			
		||||
                    url.contains("anyacg.co") ||
 | 
			
		||||
                    url.contains("mangakatana") ||
 | 
			
		||||
                    url.contains("zeroscans") ||
 | 
			
		||||
                    url.contains("mangapark") ||
 | 
			
		||||
                    url.contains("mangadex") ||
 | 
			
		||||
                    url.contains("uptruyen") ||
 | 
			
		||||
                    url.contains("hocvientruyentranh") ||
 | 
			
		||||
                    url.contains("ntruyen.info") ||
 | 
			
		||||
                    url.contains("chancanvas") ||
 | 
			
		||||
                    url.contains("bato.to")
 | 
			
		||||
                ) &&
 | 
			
		||||
            (
 | 
			
		||||
                !url.contains("googleusercontent") &&
 | 
			
		||||
                    !url.contains("otakusan") &&
 | 
			
		||||
                    !url.contains("otakuscan") &&
 | 
			
		||||
                    !url.contains("shopotaku")
 | 
			
		||||
                )
 | 
			
		||||
        ) {
 | 
			
		||||
            url =
 | 
			
		||||
                "https://images2-focus-opensocial.googleusercontent.com/gadgets/proxy?container=focus&gadget=a&no_expand=1&resize_h=0&rewriteMime=image%2F*".toHttpUrl()
 | 
			
		||||
                    .newBuilder().apply {
 | 
			
		||||
                        addQueryParameter("url", url)
 | 
			
		||||
                    }.build().toString()
 | 
			
		||||
        } else if (url.contains("imageinstant.com")) {
 | 
			
		||||
            url = "https://images.weserv.nl/".toHttpUrl().newBuilder().apply {
 | 
			
		||||
                addQueryParameter("url", url)
 | 
			
		||||
            }.build().toString()
 | 
			
		||||
        } else if (!url.contains("otakusan.net")) {
 | 
			
		||||
            url = "https://otakusan.net/api/Value/ImageSyncing?ip=34512351".toHttpUrl().newBuilder()
 | 
			
		||||
                .apply {
 | 
			
		||||
                    addQueryParameter("url", url)
 | 
			
		||||
                }.build().toString()
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return if (url.contains("vi=") && !url.contains("otakusan.net_")) {
 | 
			
		||||
            url
 | 
			
		||||
        } else {
 | 
			
		||||
            url.toHttpUrl().newBuilder().apply {
 | 
			
		||||
                addQueryParameter("vi", vi)
 | 
			
		||||
            }.build().toString()
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||