Implemented module to query Wolfram Alpha
This commit is contained in:
parent
0880d53894
commit
3ba2dfba4a
6 changed files with 215 additions and 0 deletions
|
@ -66,6 +66,8 @@
|
|||
<ID>ReturnCount:ExceptionSanitizer.kt$ExceptionSanitizer$fun ModuleException.sanitize(vararg sanitize: String): ModuleException</ID>
|
||||
<ID>SwallowedException:GoogleSearchTest.kt$GoogleSearchTest$e: ModuleException</ID>
|
||||
<ID>SwallowedException:StockQuoteTest.kt$StockQuoteTest$e: ModuleException</ID>
|
||||
<ID>SwallowedException:WolframAlpha.kt$WolframAlpha.Companion$ioe: IOException</ID>
|
||||
<ID>SwallowedException:WolframAlphaTest.kt$WolframAlphaTest$e: ModuleException</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$@Throws(ModuleException::class) private fun getJsonResponse(response: String, debugMessage: String): JSONObject</ID>
|
||||
|
|
|
@ -63,3 +63,9 @@ tell-max-size=50
|
|||
# Get Alpha Vantage Stock Quote API key from: https://www.alphavantage.co/support/#api-key
|
||||
#
|
||||
#alphavantage-api-key=
|
||||
|
||||
#
|
||||
# Get Wolfram Alpa API key from: https://developer.wolframalpha.com/portal/
|
||||
#
|
||||
#wolfram-api-key=
|
||||
#wolfram-units=imperial
|
||||
|
|
|
@ -79,6 +79,7 @@ import net.thauvin.erik.mobibot.modules.RockPaperScissors
|
|||
import net.thauvin.erik.mobibot.modules.StockQuote
|
||||
import net.thauvin.erik.mobibot.modules.War
|
||||
import net.thauvin.erik.mobibot.modules.Weather2
|
||||
import net.thauvin.erik.mobibot.modules.WolframAlpha
|
||||
import net.thauvin.erik.mobibot.modules.WorldTime
|
||||
import net.thauvin.erik.semver.Version
|
||||
import org.pircbotx.Configuration
|
||||
|
@ -426,6 +427,7 @@ class Mobibot(nickname: String, val channel: String, logsDirPath: String, p: Pro
|
|||
addons.add(Weather2())
|
||||
addons.add(WorldTime())
|
||||
addons.add(War())
|
||||
addons.add(WolframAlpha())
|
||||
|
||||
// Sort the addons
|
||||
addons.names.sort()
|
||||
|
|
133
src/main/kotlin/net/thauvin/erik/mobibot/modules/WolframAlpha.kt
Normal file
133
src/main/kotlin/net/thauvin/erik/mobibot/modules/WolframAlpha.kt
Normal file
|
@ -0,0 +1,133 @@
|
|||
/*
|
||||
* WolframAlpha.kt
|
||||
*
|
||||
* Copyright (c) 2004-2022, 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.Utils
|
||||
import net.thauvin.erik.mobibot.Utils.encodeUrl
|
||||
import net.thauvin.erik.mobibot.Utils.reader
|
||||
import net.thauvin.erik.mobibot.Utils.sendMessage
|
||||
import org.pircbotx.hooks.types.GenericMessageEvent
|
||||
import org.slf4j.Logger
|
||||
import org.slf4j.LoggerFactory
|
||||
import java.io.IOException
|
||||
import java.net.URL
|
||||
|
||||
class WolframAlpha : ThreadedModule() {
|
||||
private val logger: Logger = LoggerFactory.getLogger(WolframAlpha::class.java)
|
||||
|
||||
override val name = "WolframAlpha"
|
||||
|
||||
private fun getUnits(unit: String?): String {
|
||||
println("--> $unit")
|
||||
return if (unit?.lowercase() == METRIC) {
|
||||
METRIC
|
||||
} else {
|
||||
IMPERIAL
|
||||
}
|
||||
}
|
||||
|
||||
override fun run(channel: String, cmd: String, args: String, event: GenericMessageEvent) {
|
||||
if (args.isNotBlank()) {
|
||||
try {
|
||||
val query = args.trim().split("units=", limit = 2, ignoreCase = true)
|
||||
event.sendMessage(
|
||||
queryWolfram(
|
||||
query[0].trim(),
|
||||
units = if (query.size == 2) {
|
||||
getUnits(query[1].trim())
|
||||
} else {
|
||||
getUnits(properties[WOLFRAM_UNITS_PROP])
|
||||
},
|
||||
apiKey = properties[WOLFRAM_API_KEY_PROP]
|
||||
)
|
||||
)
|
||||
} catch (e: ModuleException) {
|
||||
if (logger.isWarnEnabled) logger.warn(e.debugMessage, e)
|
||||
e.message?.let {
|
||||
event.sendMessage(it)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
helpResponse(event)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
/**
|
||||
* The Wolfram Alpha API Key property.
|
||||
*/
|
||||
const val WOLFRAM_API_KEY_PROP = "wolfram-api-key"
|
||||
|
||||
/**
|
||||
* The Wolfram units properties
|
||||
*/
|
||||
const val WOLFRAM_UNITS_PROP = "wolfram-units"
|
||||
const val METRIC = "metric"
|
||||
const val IMPERIAL = "imperial"
|
||||
|
||||
// Wolfram command
|
||||
private const val WOLFRAM_CMD = "wolfram"
|
||||
|
||||
// Wolfram Alpha API URL
|
||||
private const val API_URL = "http://api.wolframalpha.com/v1/spoken?appid="
|
||||
|
||||
@JvmStatic
|
||||
@Throws(ModuleException::class)
|
||||
fun queryWolfram(query: String, units: String = IMPERIAL, apiKey: String?): String {
|
||||
if (!apiKey.isNullOrEmpty()) {
|
||||
try {
|
||||
return URL("${API_URL}${apiKey}&units=${units}&i=" + query.encodeUrl()).reader()
|
||||
} catch (ioe: IOException) {
|
||||
throw ModuleException(
|
||||
"wolfram($query): IOE",
|
||||
"Looks like Wolfram Alpha isn't able to answer that.",
|
||||
)
|
||||
}
|
||||
} else {
|
||||
throw ModuleException("wolfram($query): No API Key", "No Wolfram Alpha API key specified.")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
init {
|
||||
commands.add(WOLFRAM_CMD)
|
||||
with(help) {
|
||||
add("To get answers from Wolfram Alpha:")
|
||||
add(Utils.helpFormat("%c $WOLFRAM_CMD <query> [units=(${METRIC}|${IMPERIAL})]"))
|
||||
add("For example:")
|
||||
add(Utils.helpFormat("%c $WOLFRAM_CMD days until christmas"))
|
||||
add(Utils.helpFormat("%c $WOLFRAM_CMD distance earth moon units=metric"))
|
||||
}
|
||||
initProperties(WOLFRAM_API_KEY_PROP, WOLFRAM_UNITS_PROP)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* WolframAlphaTest.kt
|
||||
*
|
||||
* Copyright (c) 2004-2022, 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 assertk.assertThat
|
||||
import assertk.assertions.contains
|
||||
import assertk.assertions.isFailure
|
||||
import assertk.assertions.isInstanceOf
|
||||
import net.thauvin.erik.mobibot.ExceptionSanitizer.sanitize
|
||||
import net.thauvin.erik.mobibot.LocalProperties
|
||||
import org.testng.annotations.Test
|
||||
|
||||
class WolframAlphaTest : LocalProperties() {
|
||||
@Test
|
||||
@Throws(ModuleException::class)
|
||||
fun queryWolframTest() {
|
||||
val apiKey = getProperty(WolframAlpha.WOLFRAM_API_KEY_PROP)
|
||||
try {
|
||||
assertThat(WolframAlpha.queryWolfram("SFO to SEA", apiKey = apiKey), "SFO to SEA").contains("miles")
|
||||
|
||||
assertThat(
|
||||
WolframAlpha.queryWolfram("SFO to LAX", WolframAlpha.METRIC, apiKey),
|
||||
"SFO to LA"
|
||||
).contains("kilometers")
|
||||
|
||||
assertThat { WolframAlpha.queryWolfram("1 gallon to liter", apiKey = "") }
|
||||
.isFailure()
|
||||
.isInstanceOf(ModuleException::class.java)
|
||||
} catch (e: ModuleException) {
|
||||
// Avoid displaying api key in CI logs
|
||||
if ("true" == System.getenv("CI")) {
|
||||
throw e.sanitize(apiKey)
|
||||
} else {
|
||||
throw e
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -80,6 +80,10 @@
|
|||
<li>Performing Google searches
|
||||
<div><code>mobibot: google mobitopia on irc</code></div>
|
||||
</li>
|
||||
<li>Getting answers from <a href="https://wolframalpha.com/">Wolfram Alpha</a>
|
||||
<div><code>mobibot: wolfram days until christmas</code></div>
|
||||
<div><code>mobibot: wolfram 1 gallon to liter</code></div>
|
||||
</li>
|
||||
<li>Displaying weather information
|
||||
<div><code>mobibot: weather san francisco</code></div>
|
||||
<div><code>mobibot: weather 94123 </code></div>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue