Implemented CryptoPrices (Coinbase API), replacing the Bitcoin module.
This commit is contained in:
parent
1f965a1833
commit
f580f0f7f2
7 changed files with 145 additions and 168 deletions
|
@ -50,9 +50,14 @@ dependencies {
|
||||||
implementation 'org.apache.commons:commons-lang3:3.12.0'
|
implementation 'org.apache.commons:commons-lang3:3.12.0'
|
||||||
|
|
||||||
implementation 'com.rometools:rome:1.15.0'
|
implementation 'com.rometools:rome:1.15.0'
|
||||||
|
implementation 'com.squareup.okhttp3:okhttp:4.9.1'
|
||||||
implementation 'net.aksingh:owm-japis:2.5.3.0'
|
implementation 'net.aksingh:owm-japis:2.5.3.0'
|
||||||
implementation 'net.objecthunter:exp4j:0.4.8'
|
implementation 'net.objecthunter:exp4j:0.4.8'
|
||||||
|
|
||||||
|
implementation 'net.thauvin.erik:cryptoprice:0.9.0-SNAPSHOT'
|
||||||
implementation 'net.thauvin.erik:pinboard-poster:1.0.3'
|
implementation 'net.thauvin.erik:pinboard-poster:1.0.3'
|
||||||
|
|
||||||
|
|
||||||
implementation 'org.json:json:20210307'
|
implementation 'org.json:json:20210307'
|
||||||
implementation 'org.jsoup:jsoup:1.13.1'
|
implementation 'org.jsoup:jsoup:1.13.1'
|
||||||
implementation 'org.twitter4j:twitter4j-core:4.0.7'
|
implementation 'org.twitter4j:twitter4j-core:4.0.7'
|
||||||
|
|
|
@ -15,8 +15,8 @@
|
||||||
<ID>LongParameterList:Mobibot.kt$Mobibot$( nick: String, list: List<String>, maxPerLine: Int, isPrivate: Boolean, isBold: Boolean = false, isIndent: Boolean = false )</ID>
|
<ID>LongParameterList:Mobibot.kt$Mobibot$( nick: String, list: List<String>, maxPerLine: Int, isPrivate: Boolean, isBold: Boolean = false, isIndent: Boolean = false )</ID>
|
||||||
<ID>LongParameterList:Twitter.kt$Twitter.Companion$( consumerKey: String?, consumerSecret: String?, token: String?, tokenSecret: String?, handle: String?, message: String, isDm: Boolean )</ID>
|
<ID>LongParameterList:Twitter.kt$Twitter.Companion$( consumerKey: String?, consumerSecret: String?, token: String?, tokenSecret: String?, handle: String?, message: String, isDm: Boolean )</ID>
|
||||||
<ID>NestedBlockDepth:Addons.kt$Addons$ fun add(command: AbstractCommand, props: Properties)</ID>
|
<ID>NestedBlockDepth:Addons.kt$Addons$ fun add(command: AbstractCommand, props: Properties)</ID>
|
||||||
<ID>NestedBlockDepth:Bitcoin.kt$Bitcoin$ override fun run(sender: String, cmd: String, args: String, isPrivate: Boolean)</ID>
|
|
||||||
<ID>NestedBlockDepth:Comment.kt$Comment$override fun commandResponse( sender: String, login: String, args: String, isOp: Boolean, isPrivate: Boolean )</ID>
|
<ID>NestedBlockDepth:Comment.kt$Comment$override fun commandResponse( sender: String, login: String, args: String, isOp: Boolean, isPrivate: Boolean )</ID>
|
||||||
|
<ID>NestedBlockDepth:CryptoPrices.kt$CryptoPrices$ override fun run(sender: String, cmd: String, args: String, isPrivate: Boolean)</ID>
|
||||||
<ID>NestedBlockDepth:CurrencyConverter.kt$CurrencyConverter$ override fun run(sender: String, cmd: String, args: String, isPrivate: Boolean)</ID>
|
<ID>NestedBlockDepth:CurrencyConverter.kt$CurrencyConverter$ override fun run(sender: String, cmd: String, args: String, isPrivate: Boolean)</ID>
|
||||||
<ID>NestedBlockDepth:CurrencyConverter.kt$CurrencyConverter$override fun helpResponse(sender: String, isPrivate: Boolean): Boolean</ID>
|
<ID>NestedBlockDepth:CurrencyConverter.kt$CurrencyConverter$override fun helpResponse(sender: String, isPrivate: Boolean): Boolean</ID>
|
||||||
<ID>NestedBlockDepth:CurrencyConverter.kt$CurrencyConverter.Companion$ @Suppress("MagicNumber") @JvmStatic fun convertCurrency(query: String): Message</ID>
|
<ID>NestedBlockDepth:CurrencyConverter.kt$CurrencyConverter.Companion$ @Suppress("MagicNumber") @JvmStatic fun convertCurrency(query: String): Message</ID>
|
||||||
|
@ -39,12 +39,12 @@
|
||||||
<ID>NestedBlockDepth:WorldTime.kt$WorldTime$override fun commandResponse( sender: String, cmd: String, args: String, isPrivate: Boolean )</ID>
|
<ID>NestedBlockDepth:WorldTime.kt$WorldTime$override fun commandResponse( sender: String, cmd: String, args: String, isPrivate: Boolean )</ID>
|
||||||
<ID>ReturnCount:Addons.kt$Addons$ fun exec(sender: String, login: String, cmd: String, args: String, isOp: Boolean, isPrivate: Boolean): Boolean</ID>
|
<ID>ReturnCount:Addons.kt$Addons$ fun exec(sender: String, login: String, cmd: String, args: String, isOp: Boolean, isPrivate: Boolean): Boolean</ID>
|
||||||
<ID>ReturnCount:Addons.kt$Addons$ fun help(sender: String, topic: String, isOp: Boolean, isPrivate: Boolean): Boolean</ID>
|
<ID>ReturnCount:Addons.kt$Addons$ fun help(sender: String, topic: String, isOp: Boolean, isPrivate: Boolean): Boolean</ID>
|
||||||
<ID>ThrowsCount:Bitcoin.kt$Bitcoin.Companion$ @JvmStatic @Throws(ModuleException::class) fun marketPrice(currency: String): List<Message></ID>
|
<ID>ThrowsCount:CryptoPrices.kt$CryptoPrices.Companion$ @JvmStatic @Throws(ModuleException::class) fun marketPrice(base: String, currency: String): Price</ID>
|
||||||
<ID>ThrowsCount:GoogleSearch.kt$GoogleSearch.Companion$ @JvmStatic @Throws(ModuleException::class) fun searchGoogle(query: String, apiKey: String?, cseKey: String?): List<Message></ID>
|
<ID>ThrowsCount:GoogleSearch.kt$GoogleSearch.Companion$ @JvmStatic @Throws(ModuleException::class) fun searchGoogle(query: String, apiKey: String?, cseKey: String?): List<Message></ID>
|
||||||
<ID>ThrowsCount:StockQuote.kt$StockQuote.Companion$ @JvmStatic @Throws(ModuleException::class) fun getQuote(symbol: String, apiKey: String?): List<Message></ID>
|
<ID>ThrowsCount:StockQuote.kt$StockQuote.Companion$ @JvmStatic @Throws(ModuleException::class) fun getQuote(symbol: String, apiKey: String?): List<Message></ID>
|
||||||
<ID>ThrowsCount:StockQuote.kt$StockQuote.Companion$@Throws(ModuleException::class) private fun getJsonResponse(response: String, debugMessage: String): JSONObject</ID>
|
<ID>ThrowsCount:StockQuote.kt$StockQuote.Companion$@Throws(ModuleException::class) private fun getJsonResponse(response: String, debugMessage: String): JSONObject</ID>
|
||||||
<ID>ThrowsCount:Weather2.kt$Weather2.Companion$ @JvmStatic @Throws(ModuleException::class) fun getWeather(query: String, apiKey: String?): List<Message></ID>
|
<ID>ThrowsCount:Weather2.kt$Weather2.Companion$ @JvmStatic @Throws(ModuleException::class) fun getWeather(query: String, apiKey: String?): List<Message></ID>
|
||||||
<ID>TooGenericExceptionCaught:Bitcoin.kt$Bitcoin.Companion$e: NullPointerException</ID>
|
<ID>TooGenericExceptionCaught:CryptoPrices.kt$CryptoPrices$e: Exception</ID>
|
||||||
<ID>TooGenericExceptionCaught:FeedReader.kt$FeedReader$e: Exception</ID>
|
<ID>TooGenericExceptionCaught:FeedReader.kt$FeedReader$e: Exception</ID>
|
||||||
<ID>TooGenericExceptionCaught:Mobibot.kt$Mobibot$e: Exception</ID>
|
<ID>TooGenericExceptionCaught:Mobibot.kt$Mobibot$e: Exception</ID>
|
||||||
<ID>TooGenericExceptionCaught:Mobibot.kt$Mobibot$ex: Exception</ID>
|
<ID>TooGenericExceptionCaught:Mobibot.kt$Mobibot$ex: Exception</ID>
|
||||||
|
|
|
@ -64,7 +64,7 @@ import net.thauvin.erik.mobibot.commands.links.View
|
||||||
import net.thauvin.erik.mobibot.commands.tell.Tell
|
import net.thauvin.erik.mobibot.commands.tell.Tell
|
||||||
import net.thauvin.erik.mobibot.entries.EntriesMgr
|
import net.thauvin.erik.mobibot.entries.EntriesMgr
|
||||||
import net.thauvin.erik.mobibot.entries.EntryLink
|
import net.thauvin.erik.mobibot.entries.EntryLink
|
||||||
import net.thauvin.erik.mobibot.modules.Bitcoin
|
import net.thauvin.erik.mobibot.modules.CryptoPrices
|
||||||
import net.thauvin.erik.mobibot.modules.Calc
|
import net.thauvin.erik.mobibot.modules.Calc
|
||||||
import net.thauvin.erik.mobibot.modules.CurrencyConverter
|
import net.thauvin.erik.mobibot.modules.CurrencyConverter
|
||||||
import net.thauvin.erik.mobibot.modules.Dice
|
import net.thauvin.erik.mobibot.modules.Dice
|
||||||
|
@ -678,8 +678,8 @@ class Mobibot(nickname: String, channel: String, logsDirPath: String, p: Propert
|
||||||
addons.add(View(this), p)
|
addons.add(View(this), p)
|
||||||
|
|
||||||
// Load the modules
|
// Load the modules
|
||||||
addons.add(Bitcoin(this), p)
|
|
||||||
addons.add(Calc(this), p)
|
addons.add(Calc(this), p)
|
||||||
|
addons.add(CryptoPrices(this), p)
|
||||||
addons.add(CurrencyConverter(this), p)
|
addons.add(CurrencyConverter(this), p)
|
||||||
addons.add(Dice(this), p)
|
addons.add(Dice(this), p)
|
||||||
addons.add(GoogleSearch(this), p)
|
addons.add(GoogleSearch(this), p)
|
||||||
|
|
|
@ -1,149 +0,0 @@
|
||||||
/*
|
|
||||||
* Bitcoin.kt
|
|
||||||
*
|
|
||||||
* Copyright (c) 2004-2021, Erik C. Thauvin (erik@thauvin.net)
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions are met:
|
|
||||||
*
|
|
||||||
* Redistributions of source code must retain the above copyright notice, this
|
|
||||||
* list of conditions and the following disclaimer.
|
|
||||||
*
|
|
||||||
* Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
* this list of conditions and the following disclaimer in the documentation
|
|
||||||
* and/or other materials provided with the distribution.
|
|
||||||
*
|
|
||||||
* Neither the name of this project nor the names of its contributors may be
|
|
||||||
* used to endorse or promote products derived from this software without
|
|
||||||
* specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
||||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
||||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
||||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
||||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
||||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
package net.thauvin.erik.mobibot.modules
|
|
||||||
|
|
||||||
import net.thauvin.erik.mobibot.Mobibot
|
|
||||||
import net.thauvin.erik.mobibot.Utils
|
|
||||||
import net.thauvin.erik.mobibot.msg.ErrorMessage
|
|
||||||
import net.thauvin.erik.mobibot.msg.Message
|
|
||||||
import net.thauvin.erik.mobibot.msg.NoticeMessage
|
|
||||||
import net.thauvin.erik.mobibot.msg.PublicMessage
|
|
||||||
import org.json.JSONException
|
|
||||||
import org.json.JSONObject
|
|
||||||
import java.io.IOException
|
|
||||||
import java.net.URL
|
|
||||||
import java.text.DecimalFormat
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The Bitcoin module.
|
|
||||||
*/
|
|
||||||
class Bitcoin(bot: Mobibot) : ThreadedModule(bot) {
|
|
||||||
// Currencies
|
|
||||||
private val currencies = listOf(
|
|
||||||
"USD", "AUD", "BRL", "CAD", "CHF", "CLP", "CNY", "DKK", "EUR", "GBP", "HKD", "INR", "ISK", "JPY", "KRW",
|
|
||||||
"NZD", "PLN", "RUB", "SEK", "SGD", "THB", "TRY", "TWD");
|
|
||||||
|
|
||||||
override fun helpResponse(sender: String, isPrivate: Boolean): Boolean {
|
|
||||||
with(bot) {
|
|
||||||
send(sender, "To retrieve the bitcoin market price:", isPrivate)
|
|
||||||
send(
|
|
||||||
sender,
|
|
||||||
Utils.helpFormat(
|
|
||||||
Utils.buildCmdSyntax(
|
|
||||||
"%c $BITCOIN_CMD <USD|GBP|EUR|...>",
|
|
||||||
nick,
|
|
||||||
isPrivateMsgEnabled)
|
|
||||||
),
|
|
||||||
isPrivate
|
|
||||||
)
|
|
||||||
send(sender, "The supported currencies are: ", isPrivate)
|
|
||||||
@Suppress("MagicNumber")
|
|
||||||
sendList(sender, currencies, 12, isPrivate, isIndent = true)
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the bitcoin market price from [Blockchain.info](https://blockchain.info/ticker).
|
|
||||||
*/
|
|
||||||
override fun run(sender: String, cmd: String, args: String, isPrivate: Boolean) {
|
|
||||||
with(bot) {
|
|
||||||
val arg = args.trim().uppercase()
|
|
||||||
@Suppress("MagicNumber")
|
|
||||||
if (!currencies.contains(arg)) {
|
|
||||||
helpResponse(sender, isPrivate)
|
|
||||||
} else {
|
|
||||||
try {
|
|
||||||
val messages = marketPrice(arg)
|
|
||||||
for (msg in messages) {
|
|
||||||
send(sender, msg)
|
|
||||||
}
|
|
||||||
} catch (e: ModuleException) {
|
|
||||||
if (logger.isWarnEnabled) logger.warn(e.debugMessage, e)
|
|
||||||
send(e.message)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
// Blockchain Ticker URL
|
|
||||||
private const val TICKER_URL = "https://blockchain.info/ticker"
|
|
||||||
|
|
||||||
// Bitcoin command
|
|
||||||
private const val BITCOIN_CMD = "bitcoin"
|
|
||||||
|
|
||||||
// BTC command
|
|
||||||
private const val BTC_CMD = "btc"
|
|
||||||
|
|
||||||
private fun JSONObject.getDecimal(key: String): String {
|
|
||||||
return DecimalFormat("0.00").format(this.getBigDecimal(key))
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieves the bitcoin market price.
|
|
||||||
*/
|
|
||||||
@JvmStatic
|
|
||||||
@Throws(ModuleException::class)
|
|
||||||
fun marketPrice(currency: String): List<Message> {
|
|
||||||
val debugMessage = "marketPrice($currency)"
|
|
||||||
val messages = mutableListOf<Message>()
|
|
||||||
try {
|
|
||||||
val response = Utils.urlReader(URL("$TICKER_URL"))
|
|
||||||
val json = JSONObject(response)
|
|
||||||
val bpi = json.getJSONObject(currency.trim().uppercase())
|
|
||||||
val symbol = bpi.getString("symbol");
|
|
||||||
with(messages) {
|
|
||||||
add(PublicMessage("Bitcoin [BTC]: $symbol" + bpi.getDecimal("last") + " [$currency]"))
|
|
||||||
if (bpi.getBigDecimal("15m") != bpi.getBigDecimal("last")) {
|
|
||||||
add(NoticeMessage(" 15m: $symbol" + bpi.getDecimal("15m")))
|
|
||||||
add(NoticeMessage(" Buy: $symbol" + bpi.getDecimal("buy")))
|
|
||||||
add(NoticeMessage(" Sell: $symbol" + bpi.getDecimal("sell")))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return messages
|
|
||||||
} catch (e: IOException) {
|
|
||||||
throw ModuleException(debugMessage, "An IO error has occurred retrieving the bitcoin market price.", e)
|
|
||||||
} catch (e: NullPointerException) {
|
|
||||||
throw ModuleException(debugMessage, "An error has occurred retrieving the bitcoin market price.", e)
|
|
||||||
} catch (e: org.json.JSONException) {
|
|
||||||
throw ModuleException(
|
|
||||||
debugMessage, "A parsing error has occurred retriving the bitcoin market price.", e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
init {
|
|
||||||
commands.add(BITCOIN_CMD)
|
|
||||||
commands.add(BTC_CMD)
|
|
||||||
}
|
|
||||||
}
|
|
103
src/main/kotlin/net/thauvin/erik/mobibot/modules/CryptoPrices.kt
Normal file
103
src/main/kotlin/net/thauvin/erik/mobibot/modules/CryptoPrices.kt
Normal file
|
@ -0,0 +1,103 @@
|
||||||
|
/*
|
||||||
|
* CryptoPrices.kt
|
||||||
|
*
|
||||||
|
* Copyright (c) 2004-2021, Erik C. Thauvin (erik@thauvin.net)
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* Redistributions of source code must retain the above copyright notice, this
|
||||||
|
* list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* Neither the name of this project nor the names of its contributors may be
|
||||||
|
* used to endorse or promote products derived from this software without
|
||||||
|
* specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
package net.thauvin.erik.mobibot.modules
|
||||||
|
|
||||||
|
import okhttp3.OkHttpClient
|
||||||
|
import okhttp3.Request
|
||||||
|
import net.thauvin.erik.crypto.CryptoPrice.Companion.marketPrice
|
||||||
|
import net.thauvin.erik.crypto.CryptoException
|
||||||
|
import net.thauvin.erik.mobibot.Mobibot
|
||||||
|
import net.thauvin.erik.mobibot.Utils
|
||||||
|
import net.thauvin.erik.mobibot.msg.ErrorMessage
|
||||||
|
import net.thauvin.erik.mobibot.msg.Message
|
||||||
|
import net.thauvin.erik.mobibot.msg.NoticeMessage
|
||||||
|
import net.thauvin.erik.mobibot.msg.PublicMessage
|
||||||
|
import org.json.JSONException
|
||||||
|
import org.json.JSONObject
|
||||||
|
import java.io.IOException
|
||||||
|
import java.net.URL
|
||||||
|
import java.text.DecimalFormat
|
||||||
|
import java.time.format.DateTimeFormatter
|
||||||
|
import java.time.Instant
|
||||||
|
import java.time.temporal.ChronoUnit
|
||||||
|
import java.time.ZoneId
|
||||||
|
import java.time.ZoneOffset
|
||||||
|
|
||||||
|
data class Price(val base: String, val currency: String, val amount: Double)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Cryptocurrency Prices module.
|
||||||
|
*/
|
||||||
|
class CryptoPrices(bot: Mobibot) : ThreadedModule(bot) {
|
||||||
|
val dateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd").withZone(ZoneOffset.UTC)
|
||||||
|
val decimalFormat = DecimalFormat("0.00")
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the cryptocurrency market price from [Coinbase](https://developers.coinbase.com/api/v2#get-spot-price).
|
||||||
|
*/
|
||||||
|
override fun run(sender: String, cmd: String, args: String, isPrivate: Boolean) {
|
||||||
|
val debugMessage = "crypto($cmd $args)"
|
||||||
|
with(bot) {
|
||||||
|
if (args.matches("\\w+( [a-zA-Z]{3}+)?".toRegex())) {
|
||||||
|
val params = args.trim().split(" ");
|
||||||
|
try {
|
||||||
|
val currency = if (params.size == 2) params[1] else "USD"
|
||||||
|
val price = marketPrice(params[0], currency)
|
||||||
|
send(sender, PublicMessage("${price.base}: ${price.amount} [${price.currency}]"))
|
||||||
|
} catch (e: CryptoException) {
|
||||||
|
if (logger.isWarnEnabled) logger.warn("$debugMessage => ${e.statusCode}", e)
|
||||||
|
send(e.message)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
if (logger.isErrorEnabled) logger.error(debugMessage, e)
|
||||||
|
send("An error has occurred while retrieving the cryptocurrency market price.")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
helpResponse(sender, isPrivate)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
// Crypto command
|
||||||
|
private const val CRYPTO_CMD = "crypto"
|
||||||
|
}
|
||||||
|
|
||||||
|
init {
|
||||||
|
commands.add(CRYPTO_CMD)
|
||||||
|
help.add("To retrieve a cryptocurrency's market price:")
|
||||||
|
help.add(Utils.helpFormat("%c $CRYPTO_CMD <symbol> [<currency>]"))
|
||||||
|
help.add("For example:")
|
||||||
|
help.add(Utils.helpFormat("%c $CRYPTO_CMD BTC"))
|
||||||
|
help.add(Utils.helpFormat("%c $CRYPTO_CMD ETH EUR"))
|
||||||
|
help.add(Utils.helpFormat("%c $CRYPTO_CMD ETH2 GPB"))
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* BitcoinTest.kt
|
* CryptoPricesTest.kt
|
||||||
*
|
*
|
||||||
* Copyright (c) 2004-2021, Erik C. Thauvin (erik@thauvin.net)
|
* Copyright (c) 2004-2021, Erik C. Thauvin (erik@thauvin.net)
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
|
@ -31,25 +31,43 @@
|
||||||
*/
|
*/
|
||||||
package net.thauvin.erik.mobibot.modules
|
package net.thauvin.erik.mobibot.modules
|
||||||
|
|
||||||
|
import net.thauvin.erik.crypto.CryptoPrice.Companion.marketPrice
|
||||||
|
import net.thauvin.erik.crypto.CryptoException
|
||||||
import net.thauvin.erik.mobibot.LocalProperties
|
import net.thauvin.erik.mobibot.LocalProperties
|
||||||
import net.thauvin.erik.mobibot.modules.Bitcoin.Companion.marketPrice
|
|
||||||
import org.assertj.core.api.Assertions.assertThat
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
|
import org.assertj.core.api.Assertions.assertThatThrownBy
|
||||||
import org.testng.annotations.Test
|
import org.testng.annotations.Test
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The `BitcoinTest` class.
|
* The `CryptoPricesTest` class.
|
||||||
*/
|
*/
|
||||||
class BitcoinTest : LocalProperties() {
|
class CryptoPricesTest {
|
||||||
@Test
|
@Test
|
||||||
@Throws(ModuleException::class)
|
@Throws(ModuleException::class)
|
||||||
fun testMarketPrice() {
|
fun testMarketPrice() {
|
||||||
var messages = marketPrice("USD")
|
var price = marketPrice("BTC", "USD")
|
||||||
assertThat(messages).`as`("not empty").isNotEmpty
|
assertThat(price.base).`as`("is BTC").isEqualTo("BTC")
|
||||||
assertThat(messages[0].msg).`as`("bitcoin, BTC, $").startsWith("Bitcoin").contains("BTC").contains("$")
|
assertThat(price.currency).`as`("is USD").isEqualTo("USD")
|
||||||
//assertThat(messages[1].msg).`as`("15m").contains("15m")
|
assertThat(price.amount).`as`("BTC > 0").isGreaterThan(0.00)
|
||||||
|
|
||||||
messages = marketPrice("GBP")
|
price = marketPrice("ETH", "EUR")
|
||||||
assertThat(messages[0].msg).`as`("£").contains("£").contains("GBP")
|
assertThat(price.base).`as`("is ETH").isEqualTo("ETH")
|
||||||
//assertThat(messages[1].msg).`as`("GBP 15m").contains("15m")
|
assertThat(price.currency).`as`("is EUR").isEqualTo("EUR")
|
||||||
|
assertThat(price.amount).`as`("ETH > 0").isGreaterThan(0.00)
|
||||||
|
|
||||||
|
price = marketPrice("ETH2", "GBP")
|
||||||
|
assertThat(price.base).`as`("is ETH2").isEqualTo("ETH2")
|
||||||
|
assertThat(price.currency).`as`("is GBP").isEqualTo("GBP")
|
||||||
|
assertThat(price.amount).`as`("ETH2 > 0").isGreaterThan(0.00)
|
||||||
|
|
||||||
|
assertThatThrownBy { marketPrice("FOO", "USD") }
|
||||||
|
.`as`("FOO")
|
||||||
|
.isInstanceOf(CryptoException::class.java)
|
||||||
|
.hasMessageContaining("Invalid base currency")
|
||||||
|
|
||||||
|
assertThatThrownBy { marketPrice("FOO", "BAR") }
|
||||||
|
.`as`("FOO-BAR")
|
||||||
|
.isInstanceOf(CryptoException::class.java)
|
||||||
|
.hasMessageContaining("Invalid currency (BAR)")
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,9 +1,9 @@
|
||||||
#Generated by the Semver Plugin for Gradle
|
#Generated by the Semver Plugin for Gradle
|
||||||
#Tue May 04 23:36:08 PDT 2021
|
#Sat May 08 02:52:53 PDT 2021
|
||||||
version.buildmeta=632
|
version.buildmeta=688
|
||||||
version.major=0
|
version.major=0
|
||||||
version.minor=8
|
version.minor=8
|
||||||
version.patch=0
|
version.patch=0
|
||||||
version.prerelease=beta
|
version.prerelease=beta
|
||||||
version.project=mobibot
|
version.project=mobibot
|
||||||
version.semver=0.8.0-beta+632
|
version.semver=0.8.0-beta+688
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue