diff --git a/config/detekt/baseline.xml b/config/detekt/baseline.xml index 9c3a1f7..5658816 100644 --- a/config/detekt/baseline.xml +++ b/config/detekt/baseline.xml @@ -12,6 +12,7 @@ LongParameterList:EntryLink.kt$EntryLink$( // Link's comments val comments: MutableList<EntryComment> = mutableListOf(), // Tags/categories val tags: MutableList<SyndCategory> = mutableListOf(), // Channel var channel: String, // Creation date var date: Date = Calendar.getInstance().time, // Link's URL var link: String, // Author's login var login: String = "", // Author's nickname var nick: String, // Link's title var title: String ) LongParameterList:Twitter.kt$Twitter.Companion$( consumerKey: String?, consumerSecret: String?, token: String?, tokenSecret: String?, handle: String?, message: String, isDm: Boolean ) MagicNumber:Comment.kt$Comment$3 + MagicNumber:CryptoPrices.kt$CryptoPrices$10 MagicNumber:CurrencyConverter.kt$CurrencyConverter$11 MagicNumber:CurrencyConverter.kt$CurrencyConverter.Companion$3 MagicNumber:CurrencyConverter.kt$CurrencyConverter.Companion$4 diff --git a/src/main/kotlin/net/thauvin/erik/mobibot/modules/CryptoPrices.kt b/src/main/kotlin/net/thauvin/erik/mobibot/modules/CryptoPrices.kt index 8cb3396..e288286 100644 --- a/src/main/kotlin/net/thauvin/erik/mobibot/modules/CryptoPrices.kt +++ b/src/main/kotlin/net/thauvin/erik/mobibot/modules/CryptoPrices.kt @@ -35,7 +35,10 @@ import net.thauvin.erik.crypto.CryptoException import net.thauvin.erik.crypto.CryptoPrice import net.thauvin.erik.crypto.CryptoPrice.Companion.spotPrice import net.thauvin.erik.mobibot.Utils.helpFormat +import net.thauvin.erik.mobibot.Utils.sendList import net.thauvin.erik.mobibot.Utils.sendMessage +import net.thauvin.erik.mobibot.Utils.today +import org.json.JSONObject import org.pircbotx.hooks.types.GenericMessageEvent import org.slf4j.Logger import org.slf4j.LoggerFactory @@ -48,13 +51,32 @@ class CryptoPrices : ThreadedModule() { private val logger: Logger = LoggerFactory.getLogger(CryptoPrices::class.java) override val name = "CryptoPrices" + override fun commandResponse(channel: String, cmd: String, args: String, event: GenericMessageEvent) { + synchronized(this) { + if (pubDate != today()) { + CODES.clear() + } + } + super.commandResponse(channel, cmd, args, event) + } /** * Returns the cryptocurrency market price from [Coinbase](https://developers.coinbase.com/api/v2#get-spot-price). */ override fun run(channel: String, cmd: String, args: String, event: GenericMessageEvent) { + if (CODES.isEmpty()) { + try { + loadCodes() + } catch (e: ModuleException) { + if (logger.isWarnEnabled) logger.warn(e.debugMessage, e) + } + } + val debugMessage = "crypto($cmd $args)" - if (args.matches("\\w+( [a-zA-Z]{3}+)?".toRegex())) { + if (args == CURRENCY_CODES_KEYWORD) { + event.sendMessage("The supported currency codes are:") + event.sendList(ArrayList(CODES.keys), 10, isIndent = true) + } else if (args.matches("\\w+( [a-zA-Z]{3}+)?".toRegex())) { try { val price = currentPrice(args.split(' ')) val amount = try { @@ -62,7 +84,7 @@ class CryptoPrices : ThreadedModule() { } catch (ignore: IllegalArgumentException) { price.amount } - event.respond("${price.base} current price is $amount [${price.currency}]") + event.respond("${price.base} current price is $amount [${CODES[price.currency]}]") } catch (e: CryptoException) { if (logger.isWarnEnabled) logger.warn("$debugMessage => ${e.statusCode}", e) e.message?.let { @@ -82,6 +104,15 @@ class CryptoPrices : ThreadedModule() { // Crypto command private const val CRYPTO_CMD = "crypto" + // Currency codes + private val CODES: MutableMap = mutableMapOf() + + // Currency codes keyword + private const val CURRENCY_CODES_KEYWORD = "codes" + + // Last currency table retrieval date + private var pubDate = "" + /** * Get current market price. */ @@ -92,6 +123,38 @@ class CryptoPrices : ThreadedModule() { else spotPrice(args[0]) } + + /** + * For testing purposes. + */ + fun getCurrencyName(code: String): String? { + return CODES[code] + } + + /** + * Loads the country ISO codes. + */ + @JvmStatic + @Throws(ModuleException::class) + fun loadCodes() { + if (CODES.isEmpty()) { + try { + val json = JSONObject(CryptoPrice.apiCall(listOf("currencies"))) + val data = json.getJSONArray("data") + for (i in 0 until data.length()) { + val d = data.getJSONObject(i) + CODES[d.getString("id")] = d.getString("name") + } + pubDate = today() + } catch (e: CryptoException) { + throw ModuleException( + "loadCodes(): CE", + "An error has occurred while retrieving the currency table.", + e + ) + } + } + } } init { @@ -103,6 +166,8 @@ class CryptoPrices : ThreadedModule() { add(helpFormat("%c $CRYPTO_CMD BTC")) add(helpFormat("%c $CRYPTO_CMD ETH EUR")) add(helpFormat("%c $CRYPTO_CMD ETH2 GPB")) + add("To list the supported currency codes:") + add(helpFormat("%c $CRYPTO_CMD $CURRENCY_CODES_KEYWORD")) } } } diff --git a/src/test/kotlin/net/thauvin/erik/mobibot/modules/CryptoPricesTest.kt b/src/test/kotlin/net/thauvin/erik/mobibot/modules/CryptoPricesTest.kt index ca676d3..b8480cd 100644 --- a/src/test/kotlin/net/thauvin/erik/mobibot/modules/CryptoPricesTest.kt +++ b/src/test/kotlin/net/thauvin/erik/mobibot/modules/CryptoPricesTest.kt @@ -38,12 +38,21 @@ import assertk.assertions.isGreaterThan import assertk.assertions.prop import net.thauvin.erik.crypto.CryptoPrice import net.thauvin.erik.mobibot.modules.CryptoPrices.Companion.currentPrice +import net.thauvin.erik.mobibot.modules.CryptoPrices.Companion.getCurrencyName +import net.thauvin.erik.mobibot.modules.CryptoPrices.Companion.loadCodes +import org.testng.annotations.BeforeClass import org.testng.annotations.Test /** * The `CryptoPricesTest` class. */ class CryptoPricesTest { + @BeforeClass + @Throws(ModuleException::class) + fun before() { + loadCodes() + } + @Test @Throws(ModuleException::class) fun testMarketPrice() { @@ -61,4 +70,10 @@ class CryptoPricesTest { prop(CryptoPrice::amount).transform { it.signum() }.isGreaterThan(0) } } + + @Test + fun testGetCurrencyName() { + assertThat(getCurrencyName("USD")).isEqualTo("US Dollar") + assertThat(getCurrencyName("EUR")).isEqualTo("Euro") + } } diff --git a/version.properties b/version.properties index 3d7c19e..4c555de 100644 --- a/version.properties +++ b/version.properties @@ -1,9 +1,9 @@ #Generated by the Semver Plugin for Gradle -#Sun Jul 10 23:07:38 PDT 2022 -version.buildmeta=315 +#Mon Jul 11 07:36:52 PDT 2022 +version.buildmeta=324 version.major=0 version.minor=8 version.patch=0 version.prerelease=rc version.project=mobibot -version.semver=0.8.0-rc+315 +version.semver=0.8.0-rc+324