Switched to ExchangeRate-API
This commit is contained in:
parent
65fa55d51f
commit
8fb872ad6f
4 changed files with 72 additions and 43 deletions
|
@ -59,7 +59,8 @@
|
||||||
<ID>NestedBlockDepth:Addons.kt$Addons$fun add(module: AbstractModule): Boolean</ID>
|
<ID>NestedBlockDepth:Addons.kt$Addons$fun add(module: AbstractModule): Boolean</ID>
|
||||||
<ID>NestedBlockDepth:ChatGpt.kt$ChatGpt.Companion$@JvmStatic @Throws(ModuleException::class) fun chat(query: String, apiKey: String?, maxTokens: Int): String</ID>
|
<ID>NestedBlockDepth:ChatGpt.kt$ChatGpt.Companion$@JvmStatic @Throws(ModuleException::class) fun chat(query: String, apiKey: String?, maxTokens: Int): String</ID>
|
||||||
<ID>NestedBlockDepth:Comment.kt$Comment$override fun commandResponse(channel: String, args: String, event: GenericMessageEvent)</ID>
|
<ID>NestedBlockDepth:Comment.kt$Comment$override fun commandResponse(channel: String, args: String, event: GenericMessageEvent)</ID>
|
||||||
<ID>NestedBlockDepth:CurrencyConverter.kt$CurrencyConverter.Companion$@JvmStatic fun convertCurrency(query: String): Message</ID>
|
<ID>NestedBlockDepth:CurrencyConverter.kt$CurrencyConverter.Companion$@JvmStatic @Throws(ModuleException::class) fun loadSymbols(apiKey: String?)</ID>
|
||||||
|
<ID>NestedBlockDepth:CurrencyConverter.kt$CurrencyConverter.Companion$@JvmStatic fun convertCurrency(apiKey: String?, query: String): Message</ID>
|
||||||
<ID>NestedBlockDepth:EntryLink.kt$EntryLink$private fun setTags(tags: List<String?>)</ID>
|
<ID>NestedBlockDepth:EntryLink.kt$EntryLink$private fun setTags(tags: List<String?>)</ID>
|
||||||
<ID>NestedBlockDepth:FeedsManager.kt$FeedsManager.Companion$@JvmStatic @Throws(IOException::class, FeedException::class) fun loadFeed(entries: Entries, currentFile: String = currentXml): String</ID>
|
<ID>NestedBlockDepth:FeedsManager.kt$FeedsManager.Companion$@JvmStatic @Throws(IOException::class, FeedException::class) fun loadFeed(entries: Entries, currentFile: String = currentXml): String</ID>
|
||||||
<ID>NestedBlockDepth:FeedsManager.kt$FeedsManager.Companion$@JvmStatic fun saveFeed(entries: Entries, currentFile: String = currentXml)</ID>
|
<ID>NestedBlockDepth:FeedsManager.kt$FeedsManager.Companion$@JvmStatic fun saveFeed(entries: Entries, currentFile: String = currentXml)</ID>
|
||||||
|
|
|
@ -45,6 +45,12 @@ disabled-modules=mastodon
|
||||||
# Automatically post links to Mastodon
|
# Automatically post links to Mastodon
|
||||||
#mastodon-auto-post=true
|
#mastodon-auto-post=true
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Get Exchange Rate API key from: https://www.exchangerate-api.com/
|
||||||
|
#
|
||||||
|
#exchangerate-api-key=
|
||||||
|
|
||||||
#
|
#
|
||||||
# Create custom search engine at: https://programmablesearchengine.google.com/
|
# Create custom search engine at: https://programmablesearchengine.google.com/
|
||||||
# and get API key from: https://console.cloud.google.com/apis
|
# and get API key from: https://console.cloud.google.com/apis
|
||||||
|
|
|
@ -44,6 +44,7 @@ import org.pircbotx.hooks.types.GenericMessageEvent
|
||||||
import org.slf4j.Logger
|
import org.slf4j.Logger
|
||||||
import org.slf4j.LoggerFactory
|
import org.slf4j.LoggerFactory
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
|
import java.math.BigDecimal
|
||||||
import java.net.URL
|
import java.net.URL
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
|
@ -57,10 +58,10 @@ class CurrencyConverter : AbstractModule() {
|
||||||
override val name = "CurrencyConverter"
|
override val name = "CurrencyConverter"
|
||||||
|
|
||||||
// Reload currency codes
|
// Reload currency codes
|
||||||
private fun reload() {
|
private fun reload(apiKey: String?) {
|
||||||
if (SYMBOLS.isEmpty()) {
|
if (!apiKey.isNullOrEmpty() && SYMBOLS.isEmpty()) {
|
||||||
try {
|
try {
|
||||||
loadSymbols()
|
loadSymbols(apiKey)
|
||||||
} catch (e: ModuleException) {
|
} catch (e: ModuleException) {
|
||||||
if (logger.isWarnEnabled) logger.warn(e.debugMessage, e)
|
if (logger.isWarnEnabled) logger.warn(e.debugMessage, e)
|
||||||
}
|
}
|
||||||
|
@ -71,12 +72,12 @@ class CurrencyConverter : AbstractModule() {
|
||||||
* Converts the specified currencies.
|
* Converts the specified currencies.
|
||||||
*/
|
*/
|
||||||
override fun commandResponse(channel: String, cmd: String, args: String, event: GenericMessageEvent) {
|
override fun commandResponse(channel: String, cmd: String, args: String, event: GenericMessageEvent) {
|
||||||
reload()
|
reload(properties[API_KEY_PROP])
|
||||||
|
|
||||||
if (SYMBOLS.isEmpty()) {
|
if (SYMBOLS.isEmpty()) {
|
||||||
event.respond(EMPTY_SYMBOLS_TABLE)
|
event.respond(EMPTY_SYMBOLS_TABLE)
|
||||||
} else if (args.matches("\\d+([,\\d]+)?(\\.\\d+)? [a-zA-Z]{3}+ to [a-zA-Z]{3}+".toRegex())) {
|
} else if (args.matches("\\d+([,\\d]+)?(\\.\\d+)? [a-zA-Z]{3}+ to [a-zA-Z]{3}+".toRegex())) {
|
||||||
val msg = convertCurrency(args)
|
val msg = convertCurrency(properties[API_KEY_PROP], args)
|
||||||
event.respond(msg.msg)
|
event.respond(msg.msg)
|
||||||
if (msg.isError) {
|
if (msg.isError) {
|
||||||
helpResponse(event)
|
helpResponse(event)
|
||||||
|
@ -90,7 +91,7 @@ class CurrencyConverter : AbstractModule() {
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun helpResponse(event: GenericMessageEvent): Boolean {
|
override fun helpResponse(event: GenericMessageEvent): Boolean {
|
||||||
reload()
|
reload(properties[API_KEY_PROP])
|
||||||
|
|
||||||
if (SYMBOLS.isEmpty()) {
|
if (SYMBOLS.isEmpty()) {
|
||||||
event.sendMessage(EMPTY_SYMBOLS_TABLE)
|
event.sendMessage(EMPTY_SYMBOLS_TABLE)
|
||||||
|
@ -114,6 +115,11 @@ class CurrencyConverter : AbstractModule() {
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
/**
|
||||||
|
* The API Key property.
|
||||||
|
*/
|
||||||
|
const val API_KEY_PROP = "exchangerate-api-key"
|
||||||
|
|
||||||
// Currency command
|
// Currency command
|
||||||
private const val CURRENCY_CMD = "currency"
|
private const val CURRENCY_CMD = "currency"
|
||||||
|
|
||||||
|
@ -130,7 +136,11 @@ class CurrencyConverter : AbstractModule() {
|
||||||
* Converts from a currency to another.
|
* Converts from a currency to another.
|
||||||
*/
|
*/
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun convertCurrency(query: String): Message {
|
fun convertCurrency(apiKey: String?, query: String): Message {
|
||||||
|
if (apiKey.isNullOrEmpty()) {
|
||||||
|
throw ModuleException("${CURRENCY_CMD}($query)", "No Exchange Rate API key specified.")
|
||||||
|
}
|
||||||
|
|
||||||
val cmds = query.split(" ")
|
val cmds = query.split(" ")
|
||||||
return if (cmds.size == 4) {
|
return if (cmds.size == 4) {
|
||||||
if (cmds[3] == cmds[1] || "0" == cmds[0]) {
|
if (cmds[3] == cmds[1] || "0" == cmds[0]) {
|
||||||
|
@ -141,12 +151,14 @@ class CurrencyConverter : AbstractModule() {
|
||||||
if (SYMBOLS.contains(to) && SYMBOLS.contains(from)) {
|
if (SYMBOLS.contains(to) && SYMBOLS.contains(from)) {
|
||||||
try {
|
try {
|
||||||
val amt = cmds[0].replace(",", "")
|
val amt = cmds[0].replace(",", "")
|
||||||
val url = URL("https://api.exchangerate.host/convert?from=$to&to=$from&amount=$amt")
|
val url = URL("https://v6.exchangerate-api.com/v6/$apiKey/pair/$to/$from/$amt")
|
||||||
val json = JSONObject(url.reader().body)
|
val body = url.reader().body
|
||||||
|
val json = JSONObject(body)
|
||||||
|
|
||||||
if (json.getBoolean("success")) {
|
if (json.getString("result") == "success") {
|
||||||
|
val result = json.getDouble("conversion_result")
|
||||||
PublicMessage(
|
PublicMessage(
|
||||||
"${cmds[0]} ${SYMBOLS[to]} = ${json.get("result")} ${SYMBOLS[from]}"
|
"${cmds[0]} ${SYMBOLS[to]} = $result ${SYMBOLS[from]}"
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
ErrorMessage("Sorry, an error occurred while converting the currencies.")
|
ErrorMessage("Sorry, an error occurred while converting the currencies.")
|
||||||
|
@ -158,7 +170,9 @@ class CurrencyConverter : AbstractModule() {
|
||||||
ErrorMessage("Sounds like monopoly money to me!")
|
ErrorMessage("Sounds like monopoly money to me!")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else ErrorMessage("Invalid query. Let's try again.")
|
} else {
|
||||||
|
ErrorMessage("Invalid query. Let's try again.")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -166,14 +180,16 @@ class CurrencyConverter : AbstractModule() {
|
||||||
*/
|
*/
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
@Throws(ModuleException::class)
|
@Throws(ModuleException::class)
|
||||||
fun loadSymbols() {
|
fun loadSymbols(apiKey: String?) {
|
||||||
|
if (!apiKey.isNullOrEmpty()) {
|
||||||
try {
|
try {
|
||||||
val url = URL("https://api.exchangerate.host/symbols")
|
val url = URL("https://v6.exchangerate-api.com/v6/$apiKey/codes")
|
||||||
val json = JSONObject(url.reader().body)
|
val json = JSONObject(url.reader().body)
|
||||||
if (json.getBoolean("success")) {
|
if (json.getString("result") == "success") {
|
||||||
val symbols = json.getJSONObject("symbols")
|
val codes = json.getJSONArray("supported_codes")
|
||||||
for (key in symbols.keys()) {
|
for (i in 0 until codes.length()) {
|
||||||
SYMBOLS[key] = symbols.getJSONObject(key).getString("description")
|
val code = codes.getJSONArray(i);
|
||||||
|
SYMBOLS[code.getString(0)] = code.getString(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (e: IOException) {
|
} catch (e: IOException) {
|
||||||
|
@ -185,9 +201,11 @@ class CurrencyConverter : AbstractModule() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
init {
|
init {
|
||||||
commands.add(CURRENCY_CMD)
|
commands.add(CURRENCY_CMD)
|
||||||
loadSymbols()
|
initProperties(API_KEY_PROP)
|
||||||
|
loadSymbols(properties[ChatGpt.API_KEY_PROP])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,6 +36,7 @@ import assertk.assertions.contains
|
||||||
import assertk.assertions.isInstanceOf
|
import assertk.assertions.isInstanceOf
|
||||||
import assertk.assertions.matches
|
import assertk.assertions.matches
|
||||||
import assertk.assertions.prop
|
import assertk.assertions.prop
|
||||||
|
import net.thauvin.erik.mobibot.LocalProperties
|
||||||
import net.thauvin.erik.mobibot.modules.CurrencyConverter.Companion.convertCurrency
|
import net.thauvin.erik.mobibot.modules.CurrencyConverter.Companion.convertCurrency
|
||||||
import net.thauvin.erik.mobibot.modules.CurrencyConverter.Companion.loadSymbols
|
import net.thauvin.erik.mobibot.modules.CurrencyConverter.Companion.loadSymbols
|
||||||
import net.thauvin.erik.mobibot.msg.ErrorMessage
|
import net.thauvin.erik.mobibot.msg.ErrorMessage
|
||||||
|
@ -48,32 +49,35 @@ import org.testng.annotations.Test
|
||||||
/**
|
/**
|
||||||
* The `CurrencyConvertTest` class.
|
* The `CurrencyConvertTest` class.
|
||||||
*/
|
*/
|
||||||
class CurrencyConverterTest {
|
class CurrencyConverterTest: LocalProperties() {
|
||||||
|
|
||||||
@BeforeClass
|
@BeforeClass
|
||||||
@Throws(ModuleException::class)
|
@Throws(ModuleException::class)
|
||||||
fun before() {
|
fun before() {
|
||||||
loadSymbols()
|
val apiKey = getProperty(CurrencyConverter.API_KEY_PROP)
|
||||||
|
loadSymbols(apiKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(groups = ["modules"])
|
@Test(groups = ["modules"])
|
||||||
fun testConvertCurrency() {
|
fun testConvertCurrency() {
|
||||||
|
val apiKey = getProperty(CurrencyConverter.API_KEY_PROP)
|
||||||
assertThat(
|
assertThat(
|
||||||
convertCurrency("100 USD to EUR").msg,
|
convertCurrency(apiKey,"100 USD to EUR").msg,
|
||||||
"convertCurrency(100 USD to EUR)"
|
"convertCurrency(100 USD to EUR)"
|
||||||
).matches("100 United States Dollar = \\d{2,3}\\.\\d+ Euro".toRegex())
|
).matches("100 United States Dollar = \\d{2,3}\\.\\d+ Euro".toRegex())
|
||||||
assertThat(
|
assertThat(
|
||||||
convertCurrency("1 USD to BTC").msg,
|
convertCurrency(apiKey,"1 USD to GBP").msg,
|
||||||
"convertCurrency(1 USD to BTC)"
|
"convertCurrency(1 USD to BGP)"
|
||||||
).matches("1 United States Dollar = 0\\.\\d+ Bitcoin".toRegex())
|
).matches("1 United States Dollar = 0\\.\\d+ Pound Sterling".toRegex())
|
||||||
assertThat(
|
assertThat(
|
||||||
convertCurrency("100,000.00 GBP to BTC").msg,
|
convertCurrency(apiKey,"100,000.00 CAD to USD").msg,
|
||||||
"convertCurrency(100,000.00 GBP to BTC)"
|
"convertCurrency(100,000.00 GBP to USD)"
|
||||||
).matches("100,000.00 British Pound Sterling = \\d{1,2}\\.\\d+ Bitcoin".toRegex())
|
).matches("100,000.00 Canadian Dollar = \\d+\\.\\d+ United States Dollar".toRegex())
|
||||||
assertThat(convertCurrency("100 USD to USD"), "convertCurrency(100 USD to USD)").all {
|
assertThat(convertCurrency(apiKey,"100 USD to USD"), "convertCurrency(100 USD to USD)").all {
|
||||||
prop(Message::msg).contains("You're kidding, right?")
|
prop(Message::msg).contains("You're kidding, right?")
|
||||||
isInstanceOf(PublicMessage::class.java)
|
isInstanceOf(PublicMessage::class.java)
|
||||||
}
|
}
|
||||||
assertThat(convertCurrency("100 USD"), "convertCurrency(100 USD)").all {
|
assertThat(convertCurrency(apiKey,"100 USD"), "convertCurrency(100 USD)").all {
|
||||||
prop(Message::msg).contains("Invalid query.")
|
prop(Message::msg).contains("Invalid query.")
|
||||||
isInstanceOf(ErrorMessage::class.java)
|
isInstanceOf(ErrorMessage::class.java)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue