表情包下载

import com.sun.jna.platform.win32.Advapi32Util
import com.sun.jna.platform.win32.WinReg
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.jsonArray
import kotlinx.serialization.json.jsonObject
import kotlinx.serialization.json.jsonPrimitive
import okhttp3.OkHttpClient
import okhttp3.Request
import org.jsoup.Jsoup
import java.io.File
import java.io.OutputStream
import java.net.InetSocketAddress
import java.net.Proxy
import java.security.SecureRandom
import java.security.cert.X509Certificate
import javax.net.ssl.SSLContext
import javax.net.ssl.X509TrustManager

class SigstickDL {
    val trustAllCerts = object : X509TrustManager {
        override fun checkClientTrusted(chain: Array<X509Certificate?>?, authType: String?) = Unit
        override fun checkServerTrusted(chain: Array<X509Certificate?>?, authType: String?) = Unit
        override fun getAcceptedIssuers(): Array<X509Certificate> = emptyArray()
    }
    val sslContext = SSLContext.getInstance("SSL").also {
        it.init(null, arrayOf(trustAllCerts), SecureRandom())
    }

    val client = OkHttpClient.Builder()
        .proxy(queryRegProxy())
        .sslSocketFactory(sslContext.socketFactory, trustAllCerts)
        .hostnameVerifier { _, _ -> true }
        .build()

    private fun queryRegProxy(): Proxy {
        val key = "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings"
        val proxy = Advapi32Util.registryGetStringValue(WinReg.HKEY_CURRENT_USER, key, "ProxyServer")
        val host = proxy.substringBefore(':')
        val port = proxy.substringAfter(':').toInt()
        return Proxy(Proxy.Type.HTTP, InetSocketAddress(host, port))
    }

    fun download(url: String): Stickers {
        val html = client.newCall(
            Request.Builder()
                .url(url)
                .build()
        ).execute().use { it.body.string() }
        val doc = Jsoup.parse(html)
        val json = doc.getElementById("__NEXT_DATA__")!!.html()
        val pack = Json.parseToJsonElement(json)
            .jsonObject["props"]!!
            .jsonObject["pageProps"]!!
            .jsonObject["pack"]!!

        val title = pack.jsonObject["title"]!!.jsonPrimitive.content
        val stickers = pack.jsonObject["stickers"]!!.jsonArray.map { it.jsonObject["url"]!!.jsonPrimitive.content }
        return Stickers(title, stickers)
    }

    fun download(url: String, out: OutputStream) {
        client.newCall(Request.Builder().url(url).build()).execute().use {
            it.body.byteStream().use { it.copyTo(out) }
        }
    }

    data class Stickers(
        val title: String,
        val stickers: List<String>
    )

}

fun main() {
    val url = "https://www.sigstick.com/pack/6suf7TuIcpOf6hVUYyvd"
    val sigstickDL = SigstickDL()
    val (title, stickers) = sigstickDL.download(url)
    val regexp = "[\\s\\\\/:*?\"<>|@]".toRegex()
    val folderName = regexp.replace(title, "")
    val pt = File("stickers").also { it.mkdirs() }
    val folder = File(pt, folderName).also { it.mkdirs() }
    stickers.forEach { link ->
        val file = File(folder, link.substringAfterLast('/'))
        file.outputStream().use {
            sigstickDL.download(link, it)
        }
    }
}
dependencies {
    implementation("com.squareup.okhttp3:okhttp:5.0.0-alpha.11")
    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.9.0")
    implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.7.3")
    implementation(kotlin("reflect"))
    implementation("org.jsoup:jsoup:1.18.1")
    implementation("net.java.dev.jna:jna:5.15.0")
    implementation("net.java.dev.jna:jna-platform:5.15.0")
}