145 lines
5.3 KiB
Kotlin
145 lines
5.3 KiB
Kotlin
import api.CloudflareApiService
|
|
import com.google.gson.Gson
|
|
import kotlinx.coroutines.Dispatchers
|
|
import kotlinx.coroutines.runBlocking
|
|
import kotlinx.coroutines.withContext
|
|
import model.Configure
|
|
import model.zones.UpdateDnsBody
|
|
import okhttp3.OkHttpClient
|
|
import okhttp3.Request
|
|
import retrofit2.Retrofit
|
|
import retrofit2.converter.gson.GsonConverterFactory
|
|
import java.io.File
|
|
import java.io.IOException
|
|
import kotlin.system.exitProcess
|
|
|
|
|
|
private lateinit var config: Configure
|
|
|
|
private lateinit var token: String
|
|
private lateinit var domain: String
|
|
|
|
fun main() {
|
|
println("Cloudflare DDNS 更新程式已啟動")
|
|
|
|
val confFile = File("config.json")
|
|
if (!confFile.exists()) {
|
|
confFile.createNewFile()
|
|
|
|
println("請先設定 config.json 檔案")
|
|
return
|
|
}
|
|
|
|
val configRawText = confFile.readText(Charsets.UTF_8)
|
|
if (configRawText.isEmpty()) {
|
|
println("請先設定 config.json 檔案")
|
|
return
|
|
}
|
|
|
|
config = loadConfigFile(configRawText)
|
|
|
|
val retrofit = Retrofit.Builder()
|
|
.baseUrl("https://api.cloudflare.com")
|
|
.addConverterFactory(GsonConverterFactory.create())
|
|
.build()
|
|
val apiService = retrofit.create(CloudflareApiService::class.java)
|
|
|
|
runBlocking {
|
|
println("-------- [ 開始更新 DNS ] --------")
|
|
val client = OkHttpClient()
|
|
val request: Request = Request.Builder()
|
|
.url("https://ifconfig.me")
|
|
.addHeader("User-Agent", "")
|
|
.method("GET", null)
|
|
.build()
|
|
val ipAddress = try {
|
|
val response = withContext(Dispatchers.IO) {
|
|
client.newCall(request).execute()
|
|
}
|
|
|
|
if (response.isSuccessful) {
|
|
response.body()?.string() ?: run {
|
|
println("無法取得 WAN IP 位址")
|
|
return@runBlocking
|
|
}
|
|
} else {
|
|
null
|
|
}
|
|
} catch (e: IOException) {
|
|
null
|
|
} finally {
|
|
client.dispatcher().executorService().shutdown()
|
|
}
|
|
|
|
if (ipAddress != null) {
|
|
println("您目前的 WAN IP 位址為: $ipAddress")
|
|
try {
|
|
println("驗證 CF 權杖是否有效...")
|
|
val verifyTokenResult = apiService.getVerifyToken("Bearer $token")
|
|
if (verifyTokenResult.success) {
|
|
println("CF 權杖有效,載入 Zone 資料中...")
|
|
val zonesResult = apiService.getZones("Bearer $token")
|
|
if (zonesResult.success) {
|
|
println("Zone 資料載入成功,取得域名資料中...")
|
|
val zoneData = zonesResult.result.firstOrNull { it.name == domain } ?: run {
|
|
println("無法找到指定的域名 [ $domain ]...")
|
|
return@runBlocking
|
|
}
|
|
val zoneId = zoneData.id
|
|
val zoneDnsRecords = apiService.getZoneDnsRecords("Bearer $token", zoneId)
|
|
if (zoneDnsRecords.success) {
|
|
println("域名資料載入成功,處理中...")
|
|
val record = zoneDnsRecords.result.firstOrNull { it.name == domain } ?: run {
|
|
println("無法找到指定的域名 [ $domain ]...")
|
|
return@runBlocking
|
|
}
|
|
val recordId = record.id
|
|
val updateDnsBody = UpdateDnsBody(
|
|
type = "A",
|
|
name = record.name,
|
|
content = ipAddress,
|
|
ttl = 120,
|
|
proxied = false
|
|
)
|
|
val updateDnsResult = apiService.updateZoneDnsRecords("Bearer $token", zoneId, recordId, updateDnsBody)
|
|
if (updateDnsResult.success) {
|
|
println("更新 DDNS 成功")
|
|
exitProcess(0)
|
|
} else {
|
|
println("更新 DDNS 失敗")
|
|
exitProcess(0)
|
|
}
|
|
} else {
|
|
println("無法取得域名資料資料")
|
|
exitProcess(0)
|
|
}
|
|
} else {
|
|
println("無法取得 Zone 資料")
|
|
exitProcess(0)
|
|
}
|
|
} else {
|
|
println("CF 權杖無效")
|
|
exitProcess(0)
|
|
}
|
|
} catch (e: Exception) {
|
|
e.printStackTrace()
|
|
println("Error: ${e.message}")
|
|
exitProcess(0)
|
|
}
|
|
} else {
|
|
println("無法取得 WAN IP 位址...")
|
|
exitProcess(0)
|
|
}
|
|
}
|
|
}
|
|
|
|
private fun loadConfigFile(configRawText: String): Configure {
|
|
val config = Gson().fromJson(configRawText, Configure::class.java)
|
|
token = config.token
|
|
domain = config.domain
|
|
|
|
println("-------- [ 設定檔已載入 ] --------")
|
|
println("CF 權杖: $token")
|
|
println("欲更新的域名: $domain")
|
|
return config
|
|
} |