Refactor and Bump version to 1.1.0
This commit is contained in:
@@ -1,43 +0,0 @@
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
|
||||
env:
|
||||
INFENDRO__TOKEN: ${{ secrets.TOKEN }}
|
||||
|
||||
jobs:
|
||||
release:
|
||||
runs-on: linux
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: actions/cache/restore@v4
|
||||
with:
|
||||
key: gradle
|
||||
path: |
|
||||
~/.gradle/caches/
|
||||
~/.gradle/wrapper/
|
||||
~/.konan/
|
||||
|
||||
- uses: actions/setup-java@v4
|
||||
with:
|
||||
java-version: '24'
|
||||
distribution: 'temurin'
|
||||
|
||||
- run: |
|
||||
./gradlew assemble
|
||||
mv ./build/bin/linuxX64/releaseExecutable/ddns.kexe ./ddns
|
||||
|
||||
- uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: ddns
|
||||
path: ./ddns
|
||||
|
||||
- uses: actions/cache/save@v4
|
||||
with:
|
||||
key: gradle
|
||||
path: |
|
||||
~/.gradle/caches/
|
||||
~/.gradle/wrapper/
|
||||
~/.konan/
|
||||
20
README.md
20
README.md
@@ -15,7 +15,7 @@ The resulting binary will be located in `./build/bin/releaseExecutable/`.
|
||||
The following command updates all A and AAAA DNS records in Porkbun for `example.com` and `test.example.com`.
|
||||
|
||||
```
|
||||
ddns porkbun \
|
||||
ddns porkbun update \
|
||||
--key=<key> \
|
||||
--secret-key=<secret key> \
|
||||
--domain=example.com \
|
||||
@@ -27,12 +27,18 @@ Alternatively, a file can be used to declare one or more configurations.
|
||||
The above example can be declared as follows.
|
||||
|
||||
```
|
||||
porkbun
|
||||
key=<key>
|
||||
secret-key=<secret key>
|
||||
domain=example.com
|
||||
subdomain=
|
||||
subdomain=test
|
||||
[
|
||||
{
|
||||
"type": "porkbun",
|
||||
"key": "<key>",
|
||||
"secretKey": "<secret key>"
|
||||
"domain": "example.com",
|
||||
"subdomains": [
|
||||
"",
|
||||
"test"
|
||||
]
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
To use this config file, execute the command `ddns --config=<config file>`.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import com.infendro.plugin.infendro
|
||||
|
||||
group = "com.infendro"
|
||||
version = "1.0.0"
|
||||
version = "1.1.0"
|
||||
|
||||
plugins {
|
||||
alias(libs.plugins.infendro)
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
[versions]
|
||||
infendro = "1.0.0"
|
||||
kotlin = "2.2.21"
|
||||
io = "0.8.2"
|
||||
infendro = "1.1.0"
|
||||
kotlin = "2.3.0"
|
||||
io = "0.9.0"
|
||||
coroutines = "1.10.2"
|
||||
serialization = "1.9.0"
|
||||
cli = "1.3.0"
|
||||
ktor = "3.3.3"
|
||||
serialization = "1.10.0"
|
||||
cli = "1.4.0"
|
||||
ktor = "3.4.0"
|
||||
|
||||
[plugins]
|
||||
infendro = { id = "com.infendro.plugin", version.ref = "infendro" }
|
||||
|
||||
@@ -1,110 +1,5 @@
|
||||
package com.infendro.ddns
|
||||
|
||||
import com.infendro.cli.argument.string
|
||||
import com.infendro.cli.argument.stringOrElse
|
||||
import com.infendro.cli.argument.strings
|
||||
import com.infendro.cli.command.cli
|
||||
import com.infendro.ddns.Argument.CONFIG
|
||||
import com.infendro.ddns.Argument.DOMAIN
|
||||
import com.infendro.ddns.Argument.IP_SERVICE
|
||||
import com.infendro.ddns.Argument.KEY
|
||||
import com.infendro.ddns.Argument.SECRET_KEY
|
||||
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.DnsService.Companion.PORKBUN
|
||||
import com.infendro.ddns.dns.model.DnsRecord
|
||||
import com.infendro.ddns.dns.porkbun.Porkbun
|
||||
import com.infendro.ddns.ip.IpService
|
||||
import com.infendro.ddns.command.ddns
|
||||
|
||||
private object Argument {
|
||||
val CONFIG = stringOrElse("config", "/etc/ddns.conf")
|
||||
|
||||
val DOMAIN = string("domain")
|
||||
val SUBDOMAIN = strings("subdomain", min = 1)
|
||||
val IP_SERVICE = ipService("ip-service")
|
||||
|
||||
// Porkbun
|
||||
val KEY = string("key")
|
||||
val SECRET_KEY = string("secret-key")
|
||||
}
|
||||
|
||||
fun main(
|
||||
args: Array<String>,
|
||||
) {
|
||||
cli {
|
||||
arguments(CONFIG)
|
||||
|
||||
execute {
|
||||
val config by CONFIG
|
||||
|
||||
Config.get(config)
|
||||
.run {
|
||||
val domain by DOMAIN
|
||||
val subdomains by SUBDOMAIN
|
||||
val ipService by IP_SERVICE
|
||||
|
||||
val dnsService = when (name) {
|
||||
PORKBUN -> {
|
||||
val key by KEY
|
||||
val secretkey by SECRET_KEY
|
||||
|
||||
Porkbun(key, secretkey)
|
||||
}
|
||||
|
||||
else -> throw Exception()
|
||||
}
|
||||
|
||||
dnsService.update(ipService, domain, subdomains)
|
||||
}
|
||||
}
|
||||
|
||||
command(PORKBUN) {
|
||||
arguments(
|
||||
DOMAIN,
|
||||
SUBDOMAIN,
|
||||
IP_SERVICE,
|
||||
KEY,
|
||||
SECRET_KEY,
|
||||
)
|
||||
|
||||
execute {
|
||||
val domain by DOMAIN
|
||||
val subdomains by SUBDOMAIN
|
||||
val ipService by IP_SERVICE
|
||||
|
||||
val key by KEY
|
||||
val secretkey by SECRET_KEY
|
||||
val dnsService = Porkbun(key, secretkey)
|
||||
|
||||
dnsService.update(ipService, domain, subdomains)
|
||||
}
|
||||
}
|
||||
}.run(args)
|
||||
}
|
||||
|
||||
fun Config.run(
|
||||
block: Config.Service.() -> Unit,
|
||||
) {
|
||||
for (service in services) {
|
||||
service.block()
|
||||
}
|
||||
}
|
||||
|
||||
fun DnsService.update(
|
||||
ipService: IpService,
|
||||
domain: String,
|
||||
subdomains: List<String>,
|
||||
) {
|
||||
val (ipv4, ipv6) = ipService.ip
|
||||
|
||||
val records = getRecords(domain, subdomains)
|
||||
val aRecords = records
|
||||
.filter { it.type == DnsRecord.Type.A }
|
||||
val aaaaRecords = records
|
||||
.filter { it.type == DnsRecord.Type.AAAA }
|
||||
|
||||
updateRecords(aRecords, ipv4)
|
||||
updateRecords(aaaaRecords, ipv6)
|
||||
}
|
||||
fun main(args: Array<String>) = ddns.run(*args)
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
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.ipify.Ipify
|
||||
|
||||
object IpServiceParser : Argument.Parser<IpService> {
|
||||
override fun parse(
|
||||
text: String?,
|
||||
): IpService {
|
||||
return when (text) {
|
||||
IpService.IPIFY -> Ipify
|
||||
else -> throw Exception()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class IpServiceOrDefaultArgument(
|
||||
override val name: String,
|
||||
) : Argument.SingleOrElse<IpService>() {
|
||||
override val other: IpService
|
||||
get() = IpService.DEFAULT
|
||||
|
||||
override val parser: Parser<IpService>
|
||||
get() = IpServiceParser
|
||||
}
|
||||
|
||||
fun ipService(
|
||||
name: String,
|
||||
) = IpServiceOrDefaultArgument(name)
|
||||
|
||||
fun Command.Builder.ipService(
|
||||
name: String,
|
||||
) = IpServiceOrDefaultArgument(name)
|
||||
.also { argument(it) }
|
||||
@@ -0,0 +1,12 @@
|
||||
package com.infendro.ddns.command
|
||||
|
||||
import com.infendro.cli.command.argument.argument
|
||||
import com.infendro.cli.command.option.option
|
||||
import com.infendro.ddns.ip.ipify.Ipify
|
||||
import com.infendro.ddns.parameter.ipService
|
||||
|
||||
internal object Parameters {
|
||||
val DOMAIN = argument.string("domain")
|
||||
val SUBDOMAINS = argument.string("subdomains").variable(min = 1)
|
||||
val IP_SERVICE = option.ipService("ip-service").orElse(Ipify)
|
||||
}
|
||||
9
src/commonMain/kotlin/com/infendro/ddns/command/ddns.kt
Normal file
9
src/commonMain/kotlin/com/infendro/ddns/command/ddns.kt
Normal file
@@ -0,0 +1,9 @@
|
||||
package com.infendro.ddns.command
|
||||
|
||||
import com.infendro.cli.command.command
|
||||
|
||||
val ddns = command("ddns") {
|
||||
execute { help() }
|
||||
+update
|
||||
+porkbun
|
||||
}
|
||||
29
src/commonMain/kotlin/com/infendro/ddns/command/porkbun.kt
Normal file
29
src/commonMain/kotlin/com/infendro/ddns/command/porkbun.kt
Normal file
@@ -0,0 +1,29 @@
|
||||
package com.infendro.ddns.command
|
||||
|
||||
import com.infendro.cli.command.command
|
||||
import com.infendro.cli.command.option.option
|
||||
import com.infendro.ddns.command.Parameters.DOMAIN
|
||||
import com.infendro.ddns.command.Parameters.IP_SERVICE
|
||||
import com.infendro.ddns.command.Parameters.SUBDOMAINS
|
||||
import com.infendro.ddns.dns.porkbun.Porkbun
|
||||
|
||||
val porkbun = command("porkbun") {
|
||||
execute { help() }
|
||||
|
||||
+command("update") {
|
||||
val key = +option.string("key")
|
||||
val secretKey = +option.string("secret-key")
|
||||
register(DOMAIN, SUBDOMAINS)
|
||||
register(IP_SERVICE)
|
||||
|
||||
execute {
|
||||
val key by key
|
||||
val secretKey by secretKey
|
||||
val domain by DOMAIN
|
||||
val subdomains by SUBDOMAINS
|
||||
val ipService by IP_SERVICE
|
||||
|
||||
Porkbun(key, secretKey).update(domain, subdomains, ipService)
|
||||
}
|
||||
}
|
||||
}
|
||||
35
src/commonMain/kotlin/com/infendro/ddns/command/update.kt
Normal file
35
src/commonMain/kotlin/com/infendro/ddns/command/update.kt
Normal file
@@ -0,0 +1,35 @@
|
||||
package com.infendro.ddns.command
|
||||
|
||||
import com.infendro.cli.command.command
|
||||
import com.infendro.cli.command.option.option
|
||||
import com.infendro.ddns.config.Config
|
||||
import com.infendro.ddns.ip.ipify.Ipify
|
||||
import com.infendro.ddns.parameter.path
|
||||
import kotlinx.io.buffered
|
||||
import kotlinx.io.files.Path
|
||||
import kotlinx.io.files.SystemFileSystem
|
||||
import kotlinx.io.readString
|
||||
import kotlinx.serialization.json.Json
|
||||
|
||||
val update = command("update") {
|
||||
val config = +option.path("config").orElse(Path("/etc/ddns.conf"))
|
||||
|
||||
execute {
|
||||
val config by config
|
||||
|
||||
val source = SystemFileSystem.source(config).buffered()
|
||||
val text = source.readString()
|
||||
|
||||
val entries: List<Config.Entry> = Json.decodeFromString(text)
|
||||
update(entries)
|
||||
}
|
||||
}
|
||||
|
||||
private fun update(entries: List<Config.Entry>) {
|
||||
for (entry in entries) {
|
||||
val domain = entry.domain
|
||||
val subdomains = entry.subdomains
|
||||
val ipService = entry.ipService ?: Ipify
|
||||
entry.dnsService.update(domain, subdomains, ipService)
|
||||
}
|
||||
}
|
||||
@@ -1,128 +1,29 @@
|
||||
package com.infendro.ddns.config
|
||||
|
||||
import com.infendro.cli.argument.Argument.*
|
||||
import com.infendro.ddns.config.Regex.ARGUMENT
|
||||
import com.infendro.ddns.config.Regex.EMPTY_LINES
|
||||
import kotlin.reflect.KProperty
|
||||
import kotlinx.io.buffered
|
||||
import kotlinx.io.files.Path
|
||||
import kotlinx.io.files.SystemFileSystem
|
||||
import kotlinx.io.readString
|
||||
import com.infendro.ddns.dns.DnsService
|
||||
import com.infendro.ddns.ip.IpService
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
class Config(
|
||||
val services: List<Service>,
|
||||
) {
|
||||
class Service(
|
||||
val name: String,
|
||||
val arguments: List<Argument>,
|
||||
) {
|
||||
class Argument(
|
||||
val name: String,
|
||||
val value: String,
|
||||
)
|
||||
interface Config {
|
||||
@Serializable
|
||||
sealed class Entry {
|
||||
abstract val domain: String
|
||||
abstract val subdomains: List<String>
|
||||
abstract val ipService: IpService?
|
||||
abstract val dnsService: DnsService
|
||||
|
||||
operator fun <T> Single<T>.getValue(
|
||||
thisRef: Any?,
|
||||
property: KProperty<*>,
|
||||
): T {
|
||||
return parser.parse(
|
||||
arguments
|
||||
.find { it.name == name }!!
|
||||
.value
|
||||
)
|
||||
}
|
||||
|
||||
operator fun <T> SingleOrElse<T>.getValue(
|
||||
thisRef: Any?,
|
||||
property: KProperty<*>,
|
||||
): T {
|
||||
return arguments
|
||||
.find { it.name == name }
|
||||
?.let { parser.parse(it.value) }
|
||||
?: other
|
||||
}
|
||||
|
||||
operator fun <T> SingleOrNull<T>.getValue(
|
||||
thisRef: Any?,
|
||||
property: KProperty<*>,
|
||||
): T? {
|
||||
return arguments
|
||||
.find { it.name == name }
|
||||
?.let { parser.parse(it.value) }
|
||||
}
|
||||
|
||||
operator fun <T> Multiple<T>.getValue(
|
||||
thisRef: Any?,
|
||||
property: KProperty<*>,
|
||||
): List<T> {
|
||||
return arguments
|
||||
.filter { it.name == name }
|
||||
.map { parser.parse(it.value) }
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun get(
|
||||
path: String,
|
||||
): Config {
|
||||
val path = Path(path)
|
||||
val source = SystemFileSystem.source(path).buffered()
|
||||
val text = source
|
||||
.readString()
|
||||
.process()
|
||||
|
||||
return parse(text)
|
||||
}
|
||||
|
||||
private fun String.process(): String {
|
||||
val builder = StringBuilder()
|
||||
for (line in lines()) {
|
||||
val comment = line.indexOf("""//""")
|
||||
if (comment != -1) {
|
||||
builder.appendLine(
|
||||
line
|
||||
.slice(0..<comment)
|
||||
.trim()
|
||||
)
|
||||
} else {
|
||||
builder.appendLine(
|
||||
line.trim()
|
||||
)
|
||||
}
|
||||
}
|
||||
return builder.toString().trim()
|
||||
}
|
||||
|
||||
private fun parse(
|
||||
text: String,
|
||||
): Config {
|
||||
val services = text
|
||||
.split(EMPTY_LINES)
|
||||
.map { parseService(it) }
|
||||
|
||||
return Config(services)
|
||||
}
|
||||
|
||||
private fun parseService(
|
||||
text: String,
|
||||
): Service {
|
||||
val lines = text.lines()
|
||||
val name = lines[0]
|
||||
val arguments = lines
|
||||
.drop(1)
|
||||
.map { parseArgument(it) }
|
||||
|
||||
return Service(name, arguments)
|
||||
}
|
||||
|
||||
private fun parseArgument(
|
||||
text: String,
|
||||
): Service.Argument {
|
||||
val match = ARGUMENT.find(text)!!
|
||||
val name = match.groups["name"]!!.value
|
||||
val value = match.groups["value"]!!.value
|
||||
|
||||
return Service.Argument(name, value)
|
||||
@Serializable
|
||||
@SerialName("porkbun")
|
||||
class Porkbun(
|
||||
val key: String,
|
||||
val secretKey: String,
|
||||
override val domain: String,
|
||||
override val subdomains: List<String>,
|
||||
@Serializable(with = IpServiceSerializer::class)
|
||||
override val ipService: IpService? = null,
|
||||
) : Entry() {
|
||||
override val dnsService: DnsService = com.infendro.ddns.dns.porkbun.Porkbun(key, secretKey)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.infendro.ddns.config
|
||||
|
||||
import com.infendro.ddns.ip.IpService
|
||||
import com.infendro.ddns.ip.ipify.Ipify
|
||||
import kotlinx.serialization.KSerializer
|
||||
import kotlinx.serialization.descriptors.PrimitiveKind
|
||||
import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor
|
||||
import kotlinx.serialization.descriptors.SerialDescriptor
|
||||
import kotlinx.serialization.encoding.Decoder
|
||||
import kotlinx.serialization.encoding.Encoder
|
||||
|
||||
object IpServiceSerializer : KSerializer<IpService> {
|
||||
override val descriptor: SerialDescriptor =
|
||||
PrimitiveSerialDescriptor("IpService", PrimitiveKind.STRING)
|
||||
|
||||
override fun serialize(encoder: Encoder, value: IpService) = throw NotImplementedError()
|
||||
|
||||
override fun deserialize(decoder: Decoder): IpService {
|
||||
val value = decoder.decodeString()
|
||||
return when (value) {
|
||||
"ipify" -> Ipify
|
||||
else -> throw Exception()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
package com.infendro.ddns.config
|
||||
|
||||
object Regex {
|
||||
val EMPTY_LINES = Regex("""\n{2,}""")
|
||||
val ARGUMENT = Regex("""(?<name>[a-z]+(?:-[a-z]+)*)(?:=(?<value>.*))?""")
|
||||
}
|
||||
@@ -1,29 +1,30 @@
|
||||
package com.infendro.ddns.dns
|
||||
|
||||
import com.infendro.ddns.dns.model.DnsRecord
|
||||
import com.infendro.ddns.ip.IpService
|
||||
|
||||
interface DnsService {
|
||||
fun getRecords(
|
||||
domain: String,
|
||||
subdomains: List<String>,
|
||||
): List<DnsRecord>
|
||||
fun getRecords(domain: String, subdomains: List<String>): List<DnsRecord>
|
||||
|
||||
fun updateRecord(
|
||||
record: DnsRecord,
|
||||
value: String,
|
||||
)
|
||||
fun updateRecord(record: DnsRecord, value: String)
|
||||
|
||||
fun updateRecords(
|
||||
records: List<DnsRecord>,
|
||||
value: String,
|
||||
) {
|
||||
fun updateRecords(records: List<DnsRecord>, value: String) {
|
||||
for (record in records) {
|
||||
if (record.value == value) continue
|
||||
updateRecord(record, value)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val PORKBUN = "porkbun"
|
||||
fun update(domain: String, subdomains: List<String>, ipService: IpService) {
|
||||
val (ipv4, ipv6) = ipService.ip
|
||||
|
||||
val records = getRecords(domain, subdomains)
|
||||
val aRecords = records
|
||||
.filter { it.type == DnsRecord.Type.A }
|
||||
val aaaaRecords = records
|
||||
.filter { it.type == DnsRecord.Type.AAAA }
|
||||
|
||||
updateRecords(aRecords, ipv4)
|
||||
updateRecords(aaaaRecords, ipv6)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,10 +13,9 @@ data class DnsRecord(
|
||||
val domain: String,
|
||||
) {
|
||||
val full: String
|
||||
get() = if (subdomain != null) {
|
||||
"$subdomain.$domain"
|
||||
} else {
|
||||
domain
|
||||
get() = when {
|
||||
subdomain != null -> "$subdomain.$domain"
|
||||
else -> domain
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,10 +15,7 @@ class Porkbun(
|
||||
val key: String,
|
||||
val secretkey: String,
|
||||
) : DnsService {
|
||||
override fun getRecords(
|
||||
domain: String,
|
||||
subdomains: List<String>,
|
||||
): List<DnsRecord> = runBlocking {
|
||||
override fun getRecords(domain: String, subdomains: List<String>): List<DnsRecord> = runBlocking {
|
||||
val response = http.post("https://api.porkbun.com/api/json/v3/dns/retrieve/$domain") {
|
||||
val request = GetRecordsRequest(
|
||||
apikey = key,
|
||||
@@ -50,10 +47,7 @@ class Porkbun(
|
||||
.filter { it.type in DnsRecord.Type.address && (it.domain.subdomain ?: "") in subdomains }
|
||||
}
|
||||
|
||||
override fun updateRecord(
|
||||
record: DnsRecord,
|
||||
value: String,
|
||||
): Unit = runBlocking {
|
||||
override fun updateRecord(record: DnsRecord, value: String): Unit = runBlocking {
|
||||
http.post("https://api.porkbun.com/api/json/v3/dns/edit/${record.domain.domain}/${record.id}") {
|
||||
val request = UpdateRecordRequest(
|
||||
apikey = key,
|
||||
|
||||
@@ -1,16 +1,9 @@
|
||||
package com.infendro.ddns.ip
|
||||
|
||||
import com.infendro.ddns.ip.ipify.Ipify
|
||||
|
||||
interface IpService {
|
||||
val ipv4: String
|
||||
val ipv6: String
|
||||
|
||||
val ip: Pair<String, String>
|
||||
get() = Pair(ipv4, ipv6)
|
||||
|
||||
companion object {
|
||||
const val IPIFY = "ipify"
|
||||
val DEFAULT = Ipify
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ import kotlinx.coroutines.runBlocking
|
||||
object Ipify : IpService {
|
||||
override val ipv4: String
|
||||
get() = runBlocking {
|
||||
val response = http.get("https://api.ipify.org?format=json")
|
||||
val response = http.get("https://api4.ipify.org?format=json")
|
||||
val body = response.body<GetIpResponse>()
|
||||
body.ip
|
||||
}
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.infendro.ddns.parameter
|
||||
|
||||
import com.infendro.cli.command.argument.ArgumentFactory
|
||||
import com.infendro.cli.command.argument.argument
|
||||
import com.infendro.cli.command.option.OptionFactory
|
||||
import com.infendro.cli.command.option.option
|
||||
import com.infendro.cli.parser.Parser
|
||||
import com.infendro.ddns.ip.IpService
|
||||
import com.infendro.ddns.ip.ipify.Ipify
|
||||
|
||||
object IpServiceParser : Parser<IpService>(IpService::class) {
|
||||
override fun parse(text: String): Result<IpService> {
|
||||
val service = when (text) {
|
||||
"ipify" -> Ipify
|
||||
else -> return failure(text)
|
||||
}
|
||||
return success(service)
|
||||
}
|
||||
}
|
||||
|
||||
fun ArgumentFactory.ipService(name: String, description: String? = null) =
|
||||
argument(IpServiceParser, name, description)
|
||||
|
||||
fun OptionFactory.ipService(vararg names: String, description: String? = null) =
|
||||
option(IpServiceParser, *names, description = description)
|
||||
19
src/commonMain/kotlin/com/infendro/ddns/parameter/Path.kt
Normal file
19
src/commonMain/kotlin/com/infendro/ddns/parameter/Path.kt
Normal file
@@ -0,0 +1,19 @@
|
||||
package com.infendro.ddns.parameter
|
||||
|
||||
import com.infendro.cli.command.argument.ArgumentFactory
|
||||
import com.infendro.cli.command.argument.argument
|
||||
import com.infendro.cli.command.option.OptionFactory
|
||||
import com.infendro.cli.command.option.option
|
||||
import com.infendro.cli.parser.Parser
|
||||
import kotlinx.io.files.Path
|
||||
|
||||
object PathParser : Parser<Path>(Path::class) {
|
||||
override fun parse(text: String) =
|
||||
success(Path(text))
|
||||
}
|
||||
|
||||
fun ArgumentFactory.path(name: String, description: String? = null) =
|
||||
argument(PathParser, name, description)
|
||||
|
||||
fun OptionFactory.path(vararg names: String, description: String? = null) =
|
||||
option(PathParser, *names, description = description)
|
||||
Reference in New Issue
Block a user