blob: 15ed195e5485ea7df7eebfde1f1962bcc011ddcc (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
|
#!/usr/bin/env kscript
@file:DependsOnMaven("com.beust:klaxon:5.5")
import com.beust.klaxon.Klaxon
import java.net.URL
import kotlin.system.exitProcess
fun path(key: String) = "https://currencyapi.net/api/v1/rates?key=$key&base=USD"
data class CurrencyApi(
var valid: Boolean = false,
var base: String = "",
var rates: Map<String, Double> = mapOf()
) {
fun fromBase(amount: Double, currencyCode: String): Double? = rate(currencyCode)?.let { amount * it }
fun toBase(amount: Double, currencyCode: String): Double? = rate(currencyCode)?.let { amount / it }
fun convert(from: String, amount: Double, to: String): Double? =
toBase(amount, from)?.let { fromBase(it, to) }
fun rate(currencyCode: String): Double? =
currencyCode.toUpperCase().let { return@let if (currencyCode == base) 1.0 else rates[currencyCode] }
}
val apiKey: String? = System.getenv("CURRENCY_API_KEY")
fun E(text: String): Int {
System.err.println("curr: $text")
return 1
}
fun E_UNKNOWN_USAGE(): Int =
E("Unknown usage. See curr --help")
fun E_NO_API_KEY(): Int =
E("Missing currency api key. Get one at https://currencyapi.net/ and set in \$CURRENCY_API_KEY")
fun E_APIERR(): Int =
E("Failed to parse currency api response. This might be a rate limit.")
fun E_INVALID_AMOUNT(): Int =
E("Invalid amount. See curr --help")
fun E_INVALID_CODE(code: String): Int =
E("Invalid code: $code. See curr --codes")
fun getApi(key: String): CurrencyApi? = URL(path(key)).openStream().use { Klaxon().parse<CurrencyApi>(it) }
fun main(): Int {
val args = args.toMutableList()
if (args.size == 1 && (args[0] == "--help" || args[0] == "-h")) {
System.err.println(
"""
Usage: curr [-p/--plain] <from> <to> <amount>
Usage: curr --codes
Usage: curr --help
--plain -p Plain output mode.
--codes -c Display currency code list.
--help -h Display this help message.
Set your https://currencyapi.net/ api key in ${'$'}CURRENCY_API_KEY
""".trimIndent()
)
return 0
}
if (args.size == 1 && (args[0] == "--codes" || args[0] == "-c")) {
val api = getApi(apiKey ?: return E_NO_API_KEY()) ?: return E_APIERR()
println((api.rates.keys + api.base).joinToString("\n"))
return 0
}
var isPlain = args.removeAll { it == "-p" || it == "--plain" }
if (args.size == 3) {
val amount: Double = try {
args[2].toDouble()
} catch (e: NumberFormatException) {
return E_INVALID_AMOUNT()
}
val api = getApi(apiKey ?: return E_NO_API_KEY()) ?: return E_APIERR()
if (api.rate(args[0]) == null) return E_INVALID_CODE(args[0])
if (api.rate(args[1]) == null) return E_INVALID_CODE(args[1])
val converted = api.convert(args[0], amount, args[1])
if (isPlain) {
println(converted)
} else {
println("$amount ${args[0]} to ${args[1]}: $converted")
}
return 0
}
return E_UNKNOWN_USAGE()
}
exitProcess(main())
|