diff --git a/src/commonMain/kotlin/com/infendro/ddns/Http.kt b/src/commonMain/kotlin/com/infendro/ddns/Http.kt index c2b03b2..503ffca 100644 --- a/src/commonMain/kotlin/com/infendro/ddns/Http.kt +++ b/src/commonMain/kotlin/com/infendro/ddns/Http.kt @@ -1,13 +1,11 @@ package com.infendro.ddns -import io.ktor.client.HttpClient -import io.ktor.client.plugins.contentnegotiation.ContentNegotiation -import io.ktor.serialization.kotlinx.json.json +import io.ktor.client.* +import io.ktor.client.plugins.contentnegotiation.* +import io.ktor.serialization.kotlinx.json.* -object Http { - val client = HttpClient { - install(ContentNegotiation) { - json() - } +val http = HttpClient { + install(ContentNegotiation) { + json() } } diff --git a/src/commonMain/kotlin/com/infendro/ddns/Main.kt b/src/commonMain/kotlin/com/infendro/ddns/Main.kt index 0645597..4407eb0 100644 --- a/src/commonMain/kotlin/com/infendro/ddns/Main.kt +++ b/src/commonMain/kotlin/com/infendro/ddns/Main.kt @@ -13,7 +13,7 @@ import com.infendro.ddns.Argument.SUBDOMAIN import com.infendro.ddns.argument.ipService import com.infendro.ddns.config.Config import com.infendro.ddns.dns.DnsService -import com.infendro.ddns.dns.DnsServices.PORKBUN +import com.infendro.ddns.dns.DnsService.Companion.PORKBUN import com.infendro.ddns.dns.model.DnsRecord import com.infendro.ddns.dns.porkbun.Porkbun import com.infendro.ddns.ip.IpService diff --git a/src/commonMain/kotlin/com/infendro/ddns/argument/IpService.kt b/src/commonMain/kotlin/com/infendro/ddns/argument/IpService.kt index f84d9e0..c0ccf8b 100644 --- a/src/commonMain/kotlin/com/infendro/ddns/argument/IpService.kt +++ b/src/commonMain/kotlin/com/infendro/ddns/argument/IpService.kt @@ -3,13 +3,16 @@ package com.infendro.ddns.argument import com.infendro.cli.argument.Argument import com.infendro.cli.command.Command import com.infendro.ddns.ip.IpService -import com.infendro.ddns.ip.IpServices +import com.infendro.ddns.ip.ipify.Ipify object IpServiceParser : Argument.Parser { override fun parse( text: String?, ): IpService { - return IpServices.get(text!!) + return when (text) { + IpService.IPIFY -> Ipify + else -> throw Exception() + } } } @@ -17,7 +20,7 @@ class IpServiceOrDefaultArgument( override val name: String, ) : Argument.SingleOrElse() { override val other: IpService - get() = IpServices.DEFAULT + get() = IpService.DEFAULT override val parser: Parser get() = IpServiceParser diff --git a/src/commonMain/kotlin/com/infendro/ddns/dns/DnsService.kt b/src/commonMain/kotlin/com/infendro/ddns/dns/DnsService.kt index 815a42c..6b716a5 100644 --- a/src/commonMain/kotlin/com/infendro/ddns/dns/DnsService.kt +++ b/src/commonMain/kotlin/com/infendro/ddns/dns/DnsService.kt @@ -2,13 +2,13 @@ package com.infendro.ddns.dns import com.infendro.ddns.dns.model.DnsRecord -abstract class DnsService { - abstract fun getRecords( +interface DnsService { + fun getRecords( domain: String, subdomains: List, ): List - abstract fun updateRecord( + fun updateRecord( record: DnsRecord, value: String, ) @@ -22,4 +22,8 @@ abstract class DnsService { updateRecord(record, value) } } + + companion object { + const val PORKBUN = "porkbun" + } } diff --git a/src/commonMain/kotlin/com/infendro/ddns/dns/DnsServices.kt b/src/commonMain/kotlin/com/infendro/ddns/dns/DnsServices.kt deleted file mode 100644 index d06c37c..0000000 --- a/src/commonMain/kotlin/com/infendro/ddns/dns/DnsServices.kt +++ /dev/null @@ -1,5 +0,0 @@ -package com.infendro.ddns.dns - -object DnsServices { - const val PORKBUN = "porkbun" -} diff --git a/src/commonMain/kotlin/com/infendro/ddns/dns/Regex.kt b/src/commonMain/kotlin/com/infendro/ddns/dns/Regex.kt deleted file mode 100644 index b13d312..0000000 --- a/src/commonMain/kotlin/com/infendro/ddns/dns/Regex.kt +++ /dev/null @@ -1,5 +0,0 @@ -package com.infendro.ddns.dns - -object Regex { - val DOMAIN = Regex("""(?:(?(?:\w+\.)*\w+)\.)?(?\w+\.\w+)""") -} diff --git a/src/commonMain/kotlin/com/infendro/ddns/dns/porkbun/Porkbun.kt b/src/commonMain/kotlin/com/infendro/ddns/dns/porkbun/Porkbun.kt index c02302b..c1a4579 100644 --- a/src/commonMain/kotlin/com/infendro/ddns/dns/porkbun/Porkbun.kt +++ b/src/commonMain/kotlin/com/infendro/ddns/dns/porkbun/Porkbun.kt @@ -1,36 +1,52 @@ package com.infendro.ddns.dns.porkbun -import com.infendro.ddns.Http.client -import com.infendro.ddns.dns.Regex.DOMAIN import com.infendro.ddns.dns.DnsService import com.infendro.ddns.dns.model.DnsRecord import com.infendro.ddns.dns.porkbun.dto.request.GetRecordsRequest import com.infendro.ddns.dns.porkbun.dto.request.UpdateRecordRequest import com.infendro.ddns.dns.porkbun.dto.response.GetRecordsResponse -import io.ktor.client.call.body -import io.ktor.client.request.post -import io.ktor.client.request.setBody -import io.ktor.http.ContentType -import io.ktor.http.contentType +import com.infendro.ddns.http +import io.ktor.client.call.* +import io.ktor.client.request.* +import io.ktor.http.* import kotlinx.coroutines.runBlocking class Porkbun( val key: String, val secretkey: String, -) : DnsService() { +) : DnsService { override fun getRecords( domain: String, subdomains: List, ): List = runBlocking { - val response = client.post("https://api.porkbun.com/api/json/v3/dns/retrieve/$domain") { - val request = getRecordsRequest() + val response = http.post("https://api.porkbun.com/api/json/v3/dns/retrieve/$domain") { + val request = GetRecordsRequest( + apikey = key, + secretapikey = secretkey, + ) contentType(ContentType.Application.Json) setBody(request) } val body = response.body() body.records - .map { model(it) } + .map { + val labels = it.name.split('.') + val subdomain = labels.dropLast(2).joinToString(".") + val domain = labels.takeLast(2).joinToString(".") + + DnsRecord( + id = it.id, + type = DnsRecord.Type.valueOf(it.type), + domain = DnsRecord.Domain( + subdomain = subdomain, + domain = domain, + ), + value = it.content, + ttl = it.ttl.toInt(), + priority = it.prio?.toInt(), + ) + } .filter { it.type in DnsRecord.Type.address && (it.domain.subdomain ?: "") in subdomains } } @@ -38,51 +54,17 @@ class Porkbun( record: DnsRecord, value: String, ): Unit = runBlocking { - client.post("https://api.porkbun.com/api/json/v3/dns/edit/${record.domain.domain}/${record.id}") { - val request = updateRecordRequest(record, value) + http.post("https://api.porkbun.com/api/json/v3/dns/edit/${record.domain.domain}/${record.id}") { + val request = UpdateRecordRequest( + apikey = key, + secretapikey = secretkey, + type = record.type.toString(), + name = record.domain.subdomain ?: "", + content = value, + ttl = record.ttl.toString(), + ) contentType(ContentType.Application.Json) setBody(request) } } - - private fun model( - record: GetRecordsResponse.Record, - ): DnsRecord { - val match = DOMAIN.matchEntire(record.name)!! - val domain = match.groups["domain"]!!.value - val subdomain = match.groups["subdomain"]?.value - - return DnsRecord( - id = record.id, - type = DnsRecord.Type.valueOf(record.type), - domain = DnsRecord.Domain( - subdomain = subdomain, - domain = domain, - ), - value = record.content, - ttl = record.ttl.toInt(), - priority = record.prio?.toInt(), - ) - } - - private fun getRecordsRequest(): GetRecordsRequest { - return GetRecordsRequest( - apikey = key, - secretapikey = secretkey, - ) - } - - private fun updateRecordRequest( - record: DnsRecord, - ip: String, - ): UpdateRecordRequest { - return UpdateRecordRequest( - apikey = key, - secretapikey = secretkey, - type = record.type.toString(), - name = record.domain.subdomain ?: "", - content = ip, - ttl = record.ttl.toString(), - ) - } } diff --git a/src/commonMain/kotlin/com/infendro/ddns/ip/IpService.kt b/src/commonMain/kotlin/com/infendro/ddns/ip/IpService.kt index 8fe5795..8e21661 100644 --- a/src/commonMain/kotlin/com/infendro/ddns/ip/IpService.kt +++ b/src/commonMain/kotlin/com/infendro/ddns/ip/IpService.kt @@ -1,9 +1,16 @@ package com.infendro.ddns.ip -abstract class IpService { - abstract val ipv4: String - abstract val ipv6: String +import com.infendro.ddns.ip.ipify.Ipify - val ip: List - get() = listOf(ipv4, ipv6) +interface IpService { + val ipv4: String + val ipv6: String + + val ip: Pair + get() = Pair(ipv4, ipv6) + + companion object { + const val IPIFY = "ipify" + val DEFAULT = Ipify + } } diff --git a/src/commonMain/kotlin/com/infendro/ddns/ip/IpServices.kt b/src/commonMain/kotlin/com/infendro/ddns/ip/IpServices.kt deleted file mode 100644 index 5391205..0000000 --- a/src/commonMain/kotlin/com/infendro/ddns/ip/IpServices.kt +++ /dev/null @@ -1,17 +0,0 @@ -package com.infendro.ddns.ip - -import com.infendro.ddns.ip.ipify.Ipify - -object IpServices { - const val IPIFY = "ipify" - val DEFAULT = Ipify - - fun get( - name: String, - ): IpService { - return when (name) { - IPIFY -> Ipify - else -> throw Exception() - } - } -} diff --git a/src/commonMain/kotlin/com/infendro/ddns/ip/ipify/Ipify.kt b/src/commonMain/kotlin/com/infendro/ddns/ip/ipify/Ipify.kt index b1bff21..20d83cf 100644 --- a/src/commonMain/kotlin/com/infendro/ddns/ip/ipify/Ipify.kt +++ b/src/commonMain/kotlin/com/infendro/ddns/ip/ipify/Ipify.kt @@ -1,23 +1,23 @@ package com.infendro.ddns.ip.ipify -import com.infendro.ddns.Http +import com.infendro.ddns.http import com.infendro.ddns.ip.IpService import com.infendro.ddns.ip.ipify.dto.response.GetIpResponse -import io.ktor.client.call.body -import io.ktor.client.request.get +import io.ktor.client.call.* +import io.ktor.client.request.* import kotlinx.coroutines.runBlocking -object Ipify : IpService() { +object Ipify : IpService { override val ipv4: String get() = runBlocking { - val response = Http.client.get("https://api.ipify.org?format=json") + val response = http.get("https://api.ipify.org?format=json") val body = response.body() body.ip } override val ipv6: String get() = runBlocking { - val response = Http.client.get("https://api64.ipify.org?format=json") + val response = http.get("https://api6.ipify.org?format=json") val body = response.body() body.ip }