package com.cherret.zaprett import android.annotation.SuppressLint import android.app.DownloadManager import android.content.BroadcastReceiver import android.content.Context import android.content.Intent import android.content.IntentFilter import android.net.Uri import android.os.Build import androidx.core.content.ContextCompat import androidx.core.net.toUri import com.squareup.moshi.Moshi import com.squareup.moshi.Types import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory import okhttp3.Call import okhttp3.Callback import okhttp3.OkHttpClient import okhttp3.Request import okhttp3.Response import okio.IOException import java.io.File import java.security.MessageDigest private val client = OkHttpClient() fun getHostList(callback: (List?) -> Unit) { val request = Request.Builder().url("https://raw.githubusercontent.com/CherretGit/zaprett-hosts-repo/refs/heads/main/hosts.json").build() val moshi = Moshi.Builder().add(KotlinJsonAdapterFactory()).build() val type = Types.newParameterizedType(List::class.java, HostsInfo::class.java) val jsonAdapter = moshi.adapter>(type) client.newCall(request).enqueue(object : Callback { override fun onFailure(call: Call, e: IOException) { e.printStackTrace() callback(null) } override fun onResponse(call: Call, response: Response) { response.use { if (!response.isSuccessful) { throw IOException() callback(null) } val jsonString = response.body!!.string() val updateInfo = jsonAdapter.fromJson(jsonString) if (updateInfo != null) { callback(updateInfo) } } } }) } fun registerDownloadListenerHost(context: Context, downloadId: Long, onDownloaded: (Uri) -> Unit) {// AI Generated val receiver = object : BroadcastReceiver() { @SuppressLint("Range") override fun onReceive(context: Context?, intent: Intent?) { if (intent?.action != DownloadManager.ACTION_DOWNLOAD_COMPLETE) return if (intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1) != downloadId) return val dm = context?.getSystemService(Context.DOWNLOAD_SERVICE) as? DownloadManager ?: return val query = DownloadManager.Query().setFilterById(downloadId) dm.query(query)?.use { cursor -> if (cursor.moveToFirst()) { val status = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS)) if (status == DownloadManager.STATUS_SUCCESSFUL) { val uriString = cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI)) if (uriString != null) { val uri = uriString.toUri() context.unregisterReceiver(this) onDownloaded(uri) } } } } } } val intentFilter = IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { context.registerReceiver(receiver, intentFilter, Context.RECEIVER_EXPORTED) } else { ContextCompat.registerReceiver(context, receiver, IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE), ContextCompat.RECEIVER_EXPORTED) } } fun getFileSha256(file: File): String { val digest = MessageDigest.getInstance("SHA-256") file.inputStream().use { input -> val buffer = ByteArray(1024) var bytesRead: Int while (input.read(buffer).also { bytesRead = it } != -1) { digest.update(buffer, 0, bytesRead) } } return digest.digest().joinToString("") { "%02x".format(it) } } data class HostsInfo( val name: String, val description: String, val hash: String, val url: String )