CloudflareDDNSUpdater/src/main/kotlin/Main.kt

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
}