Upgraded to Koltin 1.9.0
This commit is contained in:
parent
5834a23b7e
commit
2313d36584
76 changed files with 549 additions and 645 deletions
3
.idea/codeStyles/codeStyleConfig.xml
generated
3
.idea/codeStyles/codeStyleConfig.xml
generated
|
@ -1,6 +1,5 @@
|
||||||
<component name="ProjectCodeStyleConfiguration">
|
<component name="ProjectCodeStyleConfiguration">
|
||||||
<state>
|
<state>
|
||||||
<option name="USE_PER_PROJECT_SETTINGS" value="true" />
|
<option name="PREFERRED_PROJECT_CODE_STYLE" value="Erik's Code Style" />
|
||||||
<option name="PREFERRED_PROJECT_CODE_STYLE" value="Default" />
|
|
||||||
</state>
|
</state>
|
||||||
</component>
|
</component>
|
2
.idea/kotlinc.xml
generated
2
.idea/kotlinc.xml
generated
|
@ -1,6 +1,6 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="KotlinJpsPluginSettings">
|
<component name="KotlinJpsPluginSettings">
|
||||||
<option name="version" value="1.8.22" />
|
<option name="version" value="1.9.0" />
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
|
@ -1,7 +1,7 @@
|
||||||
# mobibot
|
# mobibot
|
||||||
|
|
||||||
[](https://opensource.org/licenses/BSD-3-Clause)
|
[](https://opensource.org/licenses/BSD-3-Clause)
|
||||||
[](https://kotlinlang.org)
|
[](https://kotlinlang.org)
|
||||||
[](https://sonarcloud.io/summary/new_code?id=ethauvin_mobibot)
|
[](https://sonarcloud.io/summary/new_code?id=ethauvin_mobibot)
|
||||||
[](https://github.com/ethauvin/mobibot/actions/workflows/gradle.yml)
|
[](https://github.com/ethauvin/mobibot/actions/workflows/gradle.yml)
|
||||||
[](https://circleci.com/gh/ethauvin/mobibot/tree/master)
|
[](https://circleci.com/gh/ethauvin/mobibot/tree/master)
|
||||||
|
|
|
@ -10,8 +10,8 @@ plugins {
|
||||||
id 'io.gitlab.arturbosch.detekt' version '1.23.0'
|
id 'io.gitlab.arturbosch.detekt' version '1.23.0'
|
||||||
id 'java'
|
id 'java'
|
||||||
id 'net.thauvin.erik.gradle.semver' version '1.0.4'
|
id 'net.thauvin.erik.gradle.semver' version '1.0.4'
|
||||||
id 'org.jetbrains.kotlin.jvm' version '1.8.22'
|
id 'org.jetbrains.kotlin.jvm' version '1.9.0'
|
||||||
id 'org.jetbrains.kotlin.kapt' version '1.8.22'
|
id 'org.jetbrains.kotlin.kapt' version '1.9.0'
|
||||||
id 'org.jetbrains.kotlinx.kover' version '0.7.2'
|
id 'org.jetbrains.kotlinx.kover' version '0.7.2'
|
||||||
id 'org.sonarqube' version '4.2.1.3168'
|
id 'org.sonarqube' version '4.2.1.3168'
|
||||||
id 'pmd'
|
id 'pmd'
|
||||||
|
|
|
@ -46,6 +46,15 @@
|
||||||
<ID>MagicNumber:WorldTime.kt$WorldTime.Companion$3600</ID>
|
<ID>MagicNumber:WorldTime.kt$WorldTime.Companion$3600</ID>
|
||||||
<ID>MagicNumber:WorldTime.kt$WorldTime.Companion$60</ID>
|
<ID>MagicNumber:WorldTime.kt$WorldTime.Companion$60</ID>
|
||||||
<ID>MagicNumber:WorldTime.kt$WorldTime.Companion$86.4</ID>
|
<ID>MagicNumber:WorldTime.kt$WorldTime.Companion$86.4</ID>
|
||||||
|
<ID>MaxLineLength:DiceTest.kt$DiceTest$.</ID>
|
||||||
|
<ID>MaxLineLength:Lookup.kt$Lookup$("(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)")</ID>
|
||||||
|
<ID>MaxLineLength:Mastodon.kt$Mastodon.Companion$mapOf("status" to "${handle?.prefixIfMissing('@')} $message", "visibility" to "direct")</ID>
|
||||||
|
<ID>MaxLineLength:Mobibot.kt$Mobibot$helpCmdSyntax("%c ${Constants.HELP_CMD} <command>", event.bot().nick, event is PrivateMessageEvent)</ID>
|
||||||
|
<ID>MaxLineLength:PinboardTest.kt$PinboardTest$URL("https://api.pinboard.in/v1/posts/get?auth_token=${apiToken}&tag=test&" + url.encodeUrl()).reader().body</ID>
|
||||||
|
<ID>MaxLineLength:StockQuote.kt$StockQuote.Companion$+</ID>
|
||||||
|
<ID>MaxLineLength:Utils.kt$Utils$list.subList(i, list.size.coerceAtMost(i + maxPerLine)).joinToString(separator, truncated = "")</ID>
|
||||||
|
<ID>MaxLineLength:View.kt$View$helpCmdSyntax("%c $name ${index + 1} $query", event.bot().nick, event is PrivateMessageEvent)</ID>
|
||||||
|
<ID>MaxLineLength:Weather2.kt$Weather2.Companion$country.name.replace('_', ' ').capitalizeWords()</ID>
|
||||||
<ID>NestedBlockDepth:Addons.kt$Addons$fun add(command: AbstractCommand): Boolean</ID>
|
<ID>NestedBlockDepth:Addons.kt$Addons$fun add(command: AbstractCommand): Boolean</ID>
|
||||||
<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>
|
||||||
|
@ -87,6 +96,23 @@
|
||||||
<ID>TooManyFunctions:EntryLink.kt$EntryLink : Serializable</ID>
|
<ID>TooManyFunctions:EntryLink.kt$EntryLink : Serializable</ID>
|
||||||
<ID>TooManyFunctions:Mobibot.kt$Mobibot : ListenerAdapter</ID>
|
<ID>TooManyFunctions:Mobibot.kt$Mobibot : ListenerAdapter</ID>
|
||||||
<ID>TooManyFunctions:Tell.kt$Tell : AbstractCommand</ID>
|
<ID>TooManyFunctions:Tell.kt$Tell : AbstractCommand</ID>
|
||||||
|
<ID>WildcardImport:AddonsTest.kt$import net.thauvin.erik.mobibot.modules.*</ID>
|
||||||
|
<ID>WildcardImport:EntryLinkTest.kt$import assertk.assertions.*</ID>
|
||||||
|
<ID>WildcardImport:FeedMgrTest.kt$import assertk.assertions.*</ID>
|
||||||
<ID>WildcardImport:FeedReaderTest.kt$import assertk.assertions.*</ID>
|
<ID>WildcardImport:FeedReaderTest.kt$import assertk.assertions.*</ID>
|
||||||
|
<ID>WildcardImport:FeedsManager.kt$import com.rometools.rome.feed.synd.*</ID>
|
||||||
|
<ID>WildcardImport:GoogleSearchTest.kt$import assertk.assertions.*</ID>
|
||||||
|
<ID>WildcardImport:JokeTest.kt$import assertk.assertions.*</ID>
|
||||||
|
<ID>WildcardImport:Mobibot.kt$import java.io.*</ID>
|
||||||
|
<ID>WildcardImport:Mobibot.kt$import net.thauvin.erik.mobibot.commands.*</ID>
|
||||||
|
<ID>WildcardImport:Mobibot.kt$import net.thauvin.erik.mobibot.commands.links.*</ID>
|
||||||
|
<ID>WildcardImport:Mobibot.kt$import net.thauvin.erik.mobibot.modules.*</ID>
|
||||||
|
<ID>WildcardImport:Mobibot.kt$import org.pircbotx.hooks.events.*</ID>
|
||||||
|
<ID>WildcardImport:ModuleExceptionTest.kt$import assertk.assertions.*</ID>
|
||||||
|
<ID>WildcardImport:SeenTest.kt$import assertk.assertions.*</ID>
|
||||||
|
<ID>WildcardImport:StockQuoteTest.kt$import assertk.assertions.*</ID>
|
||||||
|
<ID>WildcardImport:TellMessagesMgrTest.kt$import assertk.assertions.*</ID>
|
||||||
|
<ID>WildcardImport:Utils.kt$import java.io.*</ID>
|
||||||
|
<ID>WildcardImport:Weather2Test.kt$import assertk.assertions.*</ID>
|
||||||
</CurrentIssues>
|
</CurrentIssues>
|
||||||
</SmellBaseline>
|
</SmellBaseline>
|
||||||
|
|
|
@ -72,6 +72,12 @@ public final class War extends AbstractModule {
|
||||||
help.add(Utils.helpFormat("%c " + WAR_CMD));
|
help.add(Utils.helpFormat("%c " + WAR_CMD));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "War";
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
|
@ -99,10 +105,4 @@ public final class War extends AbstractModule {
|
||||||
|
|
||||||
} while (i == y);
|
} while (i == y);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
|
||||||
@Override
|
|
||||||
public String getName() {
|
|
||||||
return "War";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,7 +38,7 @@ import org.pircbotx.hooks.events.PrivateMessageEvent
|
||||||
import org.pircbotx.hooks.types.GenericMessageEvent
|
import org.pircbotx.hooks.types.GenericMessageEvent
|
||||||
import org.slf4j.Logger
|
import org.slf4j.Logger
|
||||||
import org.slf4j.LoggerFactory
|
import org.slf4j.LoggerFactory
|
||||||
import java.util.Properties
|
import java.util.*
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Modules and Commands addons.
|
* Modules and Commands addons.
|
||||||
|
|
|
@ -63,7 +63,7 @@ object Constants {
|
||||||
* User-Agent
|
* User-Agent
|
||||||
*/
|
*/
|
||||||
const val USER_AGENT =
|
const val USER_AGENT =
|
||||||
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36"
|
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The help command.
|
* The help command.
|
||||||
|
|
|
@ -45,67 +45,24 @@ import net.thauvin.erik.mobibot.Utils.lastOrEmpty
|
||||||
import net.thauvin.erik.mobibot.Utils.sendList
|
import net.thauvin.erik.mobibot.Utils.sendList
|
||||||
import net.thauvin.erik.mobibot.Utils.sendMessage
|
import net.thauvin.erik.mobibot.Utils.sendMessage
|
||||||
import net.thauvin.erik.mobibot.Utils.toIsoLocalDate
|
import net.thauvin.erik.mobibot.Utils.toIsoLocalDate
|
||||||
import net.thauvin.erik.mobibot.commands.ChannelFeed
|
import net.thauvin.erik.mobibot.commands.*
|
||||||
import net.thauvin.erik.mobibot.commands.Cycle
|
|
||||||
import net.thauvin.erik.mobibot.commands.Die
|
|
||||||
import net.thauvin.erik.mobibot.commands.Ignore
|
|
||||||
import net.thauvin.erik.mobibot.commands.Info
|
|
||||||
import net.thauvin.erik.mobibot.commands.Me
|
|
||||||
import net.thauvin.erik.mobibot.commands.Modules
|
|
||||||
import net.thauvin.erik.mobibot.commands.Msg
|
|
||||||
import net.thauvin.erik.mobibot.commands.Nick
|
|
||||||
import net.thauvin.erik.mobibot.commands.Recap
|
|
||||||
import net.thauvin.erik.mobibot.commands.Recap.Companion.storeRecap
|
import net.thauvin.erik.mobibot.commands.Recap.Companion.storeRecap
|
||||||
import net.thauvin.erik.mobibot.commands.Say
|
import net.thauvin.erik.mobibot.commands.links.*
|
||||||
import net.thauvin.erik.mobibot.commands.Users
|
|
||||||
import net.thauvin.erik.mobibot.commands.Versions
|
|
||||||
import net.thauvin.erik.mobibot.commands.links.Comment
|
|
||||||
import net.thauvin.erik.mobibot.commands.links.LinksManager
|
|
||||||
import net.thauvin.erik.mobibot.commands.links.Posting
|
|
||||||
import net.thauvin.erik.mobibot.commands.links.Tags
|
|
||||||
import net.thauvin.erik.mobibot.commands.links.View
|
|
||||||
import net.thauvin.erik.mobibot.commands.seen.Seen
|
import net.thauvin.erik.mobibot.commands.seen.Seen
|
||||||
import net.thauvin.erik.mobibot.commands.tell.Tell
|
import net.thauvin.erik.mobibot.commands.tell.Tell
|
||||||
import net.thauvin.erik.mobibot.modules.Calc
|
import net.thauvin.erik.mobibot.modules.*
|
||||||
import net.thauvin.erik.mobibot.modules.ChatGpt
|
|
||||||
import net.thauvin.erik.mobibot.modules.CryptoPrices
|
|
||||||
import net.thauvin.erik.mobibot.modules.CurrencyConverter
|
|
||||||
import net.thauvin.erik.mobibot.modules.Dice
|
|
||||||
import net.thauvin.erik.mobibot.modules.GoogleSearch
|
|
||||||
import net.thauvin.erik.mobibot.modules.Joke
|
|
||||||
import net.thauvin.erik.mobibot.modules.Lookup
|
|
||||||
import net.thauvin.erik.mobibot.modules.Mastodon
|
|
||||||
import net.thauvin.erik.mobibot.modules.Ping
|
|
||||||
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 net.thauvin.erik.semver.Version
|
||||||
import org.pircbotx.Configuration
|
import org.pircbotx.Configuration
|
||||||
import org.pircbotx.PircBotX
|
import org.pircbotx.PircBotX
|
||||||
import org.pircbotx.hooks.ListenerAdapter
|
import org.pircbotx.hooks.ListenerAdapter
|
||||||
import org.pircbotx.hooks.events.ActionEvent
|
import org.pircbotx.hooks.events.*
|
||||||
import org.pircbotx.hooks.events.DisconnectEvent
|
|
||||||
import org.pircbotx.hooks.events.JoinEvent
|
|
||||||
import org.pircbotx.hooks.events.MessageEvent
|
|
||||||
import org.pircbotx.hooks.events.NickChangeEvent
|
|
||||||
import org.pircbotx.hooks.events.PartEvent
|
|
||||||
import org.pircbotx.hooks.events.PrivateMessageEvent
|
|
||||||
import org.pircbotx.hooks.events.QuitEvent
|
|
||||||
import org.pircbotx.hooks.types.GenericMessageEvent
|
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.BufferedOutputStream
|
import java.io.*
|
||||||
import java.io.File
|
|
||||||
import java.io.FileNotFoundException
|
|
||||||
import java.io.FileOutputStream
|
|
||||||
import java.io.IOException
|
|
||||||
import java.io.PrintStream
|
|
||||||
import java.nio.file.Files
|
import java.nio.file.Files
|
||||||
import java.nio.file.Paths
|
import java.nio.file.Paths
|
||||||
import java.util.Properties
|
import java.util.*
|
||||||
import java.util.regex.Pattern
|
import java.util.regex.Pattern
|
||||||
import kotlin.system.exitProcess
|
import kotlin.system.exitProcess
|
||||||
|
|
||||||
|
@ -140,9 +97,9 @@ class Mobibot(nickname: String, val channel: String, logsDirPath: String, p: Pro
|
||||||
event.sendMessage("Type a URL on $channel to post it.")
|
event.sendMessage("Type a URL on $channel to post it.")
|
||||||
event.sendMessage("For more information on a specific command, type:")
|
event.sendMessage("For more information on a specific command, type:")
|
||||||
event.sendMessage(
|
event.sendMessage(
|
||||||
helpFormat(
|
helpFormat(
|
||||||
helpCmdSyntax("%c ${Constants.HELP_CMD} <command>", event.bot().nick, event is PrivateMessageEvent)
|
helpCmdSyntax("%c ${Constants.HELP_CMD} <command>", event.bot().nick, event is PrivateMessageEvent)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
event.sendMessage("The commands are:")
|
event.sendMessage("The commands are:")
|
||||||
event.sendList(addons.names.commands, 8, isBold = true, isIndent = true)
|
event.sendList(addons.names.commands, 8, isBold = true, isIndent = true)
|
||||||
|
@ -204,7 +161,7 @@ class Mobibot(nickname: String, val channel: String, logsDirPath: String, p: Pro
|
||||||
with(event.getBot<PircBotX>()) {
|
with(event.getBot<PircBotX>()) {
|
||||||
if (user.nick == nick) {
|
if (user.nick == nick) {
|
||||||
LinksManager.socialManager.notification(
|
LinksManager.socialManager.notification(
|
||||||
"$nick has joined ${event.channel.name} on $serverHostname"
|
"$nick has joined ${event.channel.name} on $serverHostname"
|
||||||
)
|
)
|
||||||
seen.add(userChannelDao.getChannel(channel).users)
|
seen.add(userChannelDao.getChannel(channel).users)
|
||||||
} else {
|
} else {
|
||||||
|
@ -252,7 +209,7 @@ class Mobibot(nickname: String, val channel: String, logsDirPath: String, p: Pro
|
||||||
with(event.getBot<PircBotX>()) {
|
with(event.getBot<PircBotX>()) {
|
||||||
if (user.nick == nick) {
|
if (user.nick == nick) {
|
||||||
LinksManager.socialManager.notification(
|
LinksManager.socialManager.notification(
|
||||||
"$nick has left ${event.channel.name} on $serverHostname"
|
"$nick has left ${event.channel.name} on $serverHostname"
|
||||||
)
|
)
|
||||||
seen.add(userChannelDao.getChannel(channel).users)
|
seen.add(userChannelDao.getChannel(channel).users)
|
||||||
} else {
|
} else {
|
||||||
|
@ -275,22 +232,22 @@ class Mobibot(nickname: String, val channel: String, logsDirPath: String, p: Pro
|
||||||
// Set up the command line options
|
// Set up the command line options
|
||||||
val parser = ArgParser(Constants.CLI_CMD)
|
val parser = ArgParser(Constants.CLI_CMD)
|
||||||
val debug by parser.option(
|
val debug by parser.option(
|
||||||
ArgType.Boolean,
|
ArgType.Boolean,
|
||||||
Constants.DEBUG_ARG,
|
Constants.DEBUG_ARG,
|
||||||
Constants.DEBUG_ARG.substring(0, 1),
|
Constants.DEBUG_ARG.substring(0, 1),
|
||||||
"Print debug & logging data directly to the console"
|
"Print debug & logging data directly to the console"
|
||||||
).default(false)
|
).default(false)
|
||||||
val property by parser.option(
|
val property by parser.option(
|
||||||
ArgType.String,
|
ArgType.String,
|
||||||
Constants.PROPS_ARG,
|
Constants.PROPS_ARG,
|
||||||
Constants.PROPS_ARG.substring(0, 1),
|
Constants.PROPS_ARG.substring(0, 1),
|
||||||
"Use alternate properties file"
|
"Use alternate properties file"
|
||||||
).default("./${ReleaseInfo.PROJECT}.properties")
|
).default("./${ReleaseInfo.PROJECT}.properties")
|
||||||
val version by parser.option(
|
val version by parser.option(
|
||||||
ArgType.Boolean,
|
ArgType.Boolean,
|
||||||
Constants.VERSION_ARG,
|
Constants.VERSION_ARG,
|
||||||
Constants.VERSION_ARG.substring(0, 1),
|
Constants.VERSION_ARG.substring(0, 1),
|
||||||
"Print version info"
|
"Print version info"
|
||||||
).default(false)
|
).default(false)
|
||||||
|
|
||||||
// Parse the command line
|
// Parse the command line
|
||||||
|
@ -299,8 +256,8 @@ class Mobibot(nickname: String, val channel: String, logsDirPath: String, p: Pro
|
||||||
if (version) {
|
if (version) {
|
||||||
// Output the version
|
// Output the version
|
||||||
println(
|
println(
|
||||||
"${ReleaseInfo.PROJECT.capitalise()} ${ReleaseInfo.VERSION}" +
|
"${ReleaseInfo.PROJECT.capitalise()} ${ReleaseInfo.VERSION}" +
|
||||||
" (${ReleaseInfo.BUILDDATE.toIsoLocalDate()})"
|
" (${ReleaseInfo.BUILDDATE.toIsoLocalDate()})"
|
||||||
)
|
)
|
||||||
println(ReleaseInfo.WEBSITE)
|
println(ReleaseInfo.WEBSITE)
|
||||||
} else {
|
} else {
|
||||||
|
@ -308,7 +265,7 @@ class Mobibot(nickname: String, val channel: String, logsDirPath: String, p: Pro
|
||||||
val p = Properties()
|
val p = Properties()
|
||||||
try {
|
try {
|
||||||
Files.newInputStream(
|
Files.newInputStream(
|
||||||
Paths.get(property)
|
Paths.get(property)
|
||||||
).use { fis ->
|
).use { fis ->
|
||||||
p.load(fis)
|
p.load(fis)
|
||||||
}
|
}
|
||||||
|
@ -327,11 +284,11 @@ class Mobibot(nickname: String, val channel: String, logsDirPath: String, p: Pro
|
||||||
if (!debug) {
|
if (!debug) {
|
||||||
try {
|
try {
|
||||||
val stdout = PrintStream(
|
val stdout = PrintStream(
|
||||||
BufferedOutputStream(
|
BufferedOutputStream(
|
||||||
FileOutputStream(
|
FileOutputStream(
|
||||||
logsDir + channel.substring(1) + '.' + Utils.today() + ".log", true
|
logsDir + channel.substring(1) + '.' + Utils.today() + ".log", true
|
||||||
)
|
)
|
||||||
), true
|
), true
|
||||||
)
|
)
|
||||||
System.setOut(stdout)
|
System.setOut(stdout)
|
||||||
} catch (ignore: IOException) {
|
} catch (ignore: IOException) {
|
||||||
|
@ -340,9 +297,9 @@ class Mobibot(nickname: String, val channel: String, logsDirPath: String, p: Pro
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
val stderr = PrintStream(
|
val stderr = PrintStream(
|
||||||
BufferedOutputStream(
|
BufferedOutputStream(
|
||||||
FileOutputStream("$logsDir$nickname.err", true)
|
FileOutputStream("$logsDir$nickname.err", true)
|
||||||
), true
|
), true
|
||||||
)
|
)
|
||||||
System.setErr(stderr)
|
System.setErr(stderr)
|
||||||
} catch (ignore: IOException) {
|
} catch (ignore: IOException) {
|
||||||
|
@ -367,8 +324,8 @@ class Mobibot(nickname: String, val channel: String, logsDirPath: String, p: Pro
|
||||||
login = p.getProperty("login", nickname)
|
login = p.getProperty("login", nickname)
|
||||||
realName = p.getProperty("realname", nickname)
|
realName = p.getProperty("realname", nickname)
|
||||||
addServer(
|
addServer(
|
||||||
ircServer,
|
ircServer,
|
||||||
p.getIntProperty("port", Constants.DEFAULT_PORT)
|
p.getIntProperty("port", Constants.DEFAULT_PORT)
|
||||||
)
|
)
|
||||||
addAutoJoinChannel(channel)
|
addAutoJoinChannel(channel)
|
||||||
addListener(this@Mobibot)
|
addListener(this@Mobibot)
|
||||||
|
|
|
@ -37,7 +37,7 @@ import java.time.ZoneId
|
||||||
import java.time.ZonedDateTime
|
import java.time.ZonedDateTime
|
||||||
import java.time.format.DateTimeFormatter
|
import java.time.format.DateTimeFormatter
|
||||||
import java.time.temporal.ChronoUnit
|
import java.time.temporal.ChronoUnit
|
||||||
import java.util.Date
|
import java.util.*
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles posts to pinboard.in.
|
* Handles posts to pinboard.in.
|
||||||
|
@ -92,7 +92,7 @@ class Pinboard {
|
||||||
*/
|
*/
|
||||||
private fun Date.toTimestamp(): String {
|
private fun Date.toTimestamp(): String {
|
||||||
return ZonedDateTime.ofInstant(
|
return ZonedDateTime.ofInstant(
|
||||||
toInstant().truncatedTo(ChronoUnit.SECONDS), ZoneId.systemDefault()
|
toInstant().truncatedTo(ChronoUnit.SECONDS), ZoneId.systemDefault()
|
||||||
).format(DateTimeFormatter.ISO_INSTANT)
|
).format(DateTimeFormatter.ISO_INSTANT)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -39,11 +39,7 @@ import org.pircbotx.PircBotX
|
||||||
import org.pircbotx.hooks.events.PrivateMessageEvent
|
import org.pircbotx.hooks.events.PrivateMessageEvent
|
||||||
import org.pircbotx.hooks.types.GenericMessageEvent
|
import org.pircbotx.hooks.types.GenericMessageEvent
|
||||||
import org.slf4j.Logger
|
import org.slf4j.Logger
|
||||||
import java.io.BufferedInputStream
|
import java.io.*
|
||||||
import java.io.BufferedOutputStream
|
|
||||||
import java.io.IOException
|
|
||||||
import java.io.ObjectInputStream
|
|
||||||
import java.io.ObjectOutputStream
|
|
||||||
import java.net.HttpURLConnection
|
import java.net.HttpURLConnection
|
||||||
import java.net.URL
|
import java.net.URL
|
||||||
import java.nio.file.Files
|
import java.nio.file.Files
|
||||||
|
@ -51,8 +47,7 @@ import java.nio.file.Paths
|
||||||
import java.time.LocalDateTime
|
import java.time.LocalDateTime
|
||||||
import java.time.ZoneId
|
import java.time.ZoneId
|
||||||
import java.time.format.DateTimeFormatter
|
import java.time.format.DateTimeFormatter
|
||||||
import java.util.Date
|
import java.util.*
|
||||||
import java.util.Properties
|
|
||||||
import kotlin.io.path.exists
|
import kotlin.io.path.exists
|
||||||
import kotlin.io.path.fileSize
|
import kotlin.io.path.fileSize
|
||||||
|
|
||||||
|
@ -220,7 +215,7 @@ object Utils {
|
||||||
if (serialFile.exists() && serialFile.fileSize() > 0) {
|
if (serialFile.exists() && serialFile.fileSize() > 0) {
|
||||||
try {
|
try {
|
||||||
ObjectInputStream(
|
ObjectInputStream(
|
||||||
BufferedInputStream(Files.newInputStream(serialFile))
|
BufferedInputStream(Files.newInputStream(serialFile))
|
||||||
).use { input ->
|
).use { input ->
|
||||||
if (logger.isDebugEnabled) logger.debug("Loading the ${description}.")
|
if (logger.isDebugEnabled) logger.debug("Loading the ${description}.")
|
||||||
return input.readObject()
|
return input.readObject()
|
||||||
|
@ -307,20 +302,20 @@ object Utils {
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
@JvmOverloads
|
@JvmOverloads
|
||||||
fun GenericMessageEvent.sendList(
|
fun GenericMessageEvent.sendList(
|
||||||
list: List<String>,
|
list: List<String>,
|
||||||
maxPerLine: Int,
|
maxPerLine: Int,
|
||||||
separator: String = " ",
|
separator: String = " ",
|
||||||
isBold: Boolean = false,
|
isBold: Boolean = false,
|
||||||
isIndent: Boolean = false
|
isIndent: Boolean = false
|
||||||
) {
|
) {
|
||||||
var i = 0
|
var i = 0
|
||||||
while (i < list.size) {
|
while (i < list.size) {
|
||||||
sendMessage(
|
sendMessage(
|
||||||
helpFormat(
|
helpFormat(
|
||||||
list.subList(i, list.size.coerceAtMost(i + maxPerLine)).joinToString(separator, truncated = ""),
|
list.subList(i, list.size.coerceAtMost(i + maxPerLine)).joinToString(separator, truncated = ""),
|
||||||
isBold,
|
isBold,
|
||||||
isIndent
|
isIndent
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
i += maxPerLine
|
i += maxPerLine
|
||||||
}
|
}
|
||||||
|
@ -419,8 +414,8 @@ object Utils {
|
||||||
fun URL.reader(): UrlReaderResponse {
|
fun URL.reader(): UrlReaderResponse {
|
||||||
val connection = this.openConnection() as HttpURLConnection
|
val connection = this.openConnection() as HttpURLConnection
|
||||||
connection.setRequestProperty(
|
connection.setRequestProperty(
|
||||||
"User-Agent",
|
"User-Agent",
|
||||||
"Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/109.0"
|
"Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/109.0"
|
||||||
)
|
)
|
||||||
return if (connection.responseCode.isHttpSuccess()) {
|
return if (connection.responseCode.isHttpSuccess()) {
|
||||||
UrlReaderResponse(connection.responseCode, connection.inputStream.bufferedReader().use { it.readText() })
|
UrlReaderResponse(connection.responseCode, connection.inputStream.bufferedReader().use { it.readText() })
|
||||||
|
|
|
@ -50,15 +50,15 @@ class Ignore : AbstractCommand() {
|
||||||
|
|
||||||
override val name = IGNORE_CMD
|
override val name = IGNORE_CMD
|
||||||
override val help = listOf(
|
override val help = listOf(
|
||||||
"To ignore a link posted to the channel:",
|
"To ignore a link posted to the channel:",
|
||||||
helpFormat("https://www.foo.bar %n"),
|
helpFormat("https://www.foo.bar %n"),
|
||||||
"To check your ignore status:",
|
"To check your ignore status:",
|
||||||
helpFormat("%c $name"),
|
helpFormat("%c $name"),
|
||||||
"To toggle your ignore status:",
|
"To toggle your ignore status:",
|
||||||
helpFormat("%c $name $me")
|
helpFormat("%c $name $me")
|
||||||
)
|
)
|
||||||
private val helpOp = help.plus(
|
private val helpOp = help.plus(
|
||||||
arrayOf("To add/remove nicks from the ignored list:", helpFormat("%c $name <nick> [<nick> ...]"))
|
arrayOf("To add/remove nicks from the ignored list:", helpFormat("%c $name <nick> [<nick> ...]"))
|
||||||
)
|
)
|
||||||
|
|
||||||
override val isOpOnly = false
|
override val isOpOnly = false
|
||||||
|
|
|
@ -48,8 +48,8 @@ import kotlin.time.toDuration
|
||||||
|
|
||||||
class Info(private val tell: Tell, private val seen: Seen) : AbstractCommand() {
|
class Info(private val tell: Tell, private val seen: Seen) : AbstractCommand() {
|
||||||
private val allVersions = listOf(
|
private val allVersions = listOf(
|
||||||
"${ReleaseInfo.PROJECT.capitalise()} ${ReleaseInfo.VERSION} (${ReleaseInfo.WEBSITE.green()})",
|
"${ReleaseInfo.PROJECT.capitalise()} ${ReleaseInfo.VERSION} (${ReleaseInfo.WEBSITE.green()})",
|
||||||
"Written by ${ReleaseInfo.AUTHOR} (${ReleaseInfo.AUTHOR_URL.green()})"
|
"Written by ${ReleaseInfo.AUTHOR} (${ReleaseInfo.AUTHOR_URL.green()})"
|
||||||
)
|
)
|
||||||
override val name = "info"
|
override val name = "info"
|
||||||
override val help = listOf("To view information about the bot:", helpFormat("%c $name"))
|
override val help = listOf("To view information about the bot:", helpFormat("%c $name"))
|
||||||
|
@ -104,9 +104,9 @@ class Info(private val tell: Tell, private val seen: Seen) : AbstractCommand() {
|
||||||
event.sendList(allVersions, 1)
|
event.sendList(allVersions, 1)
|
||||||
val info = StringBuilder()
|
val info = StringBuilder()
|
||||||
info.append("Uptime: ")
|
info.append("Uptime: ")
|
||||||
.append(ManagementFactory.getRuntimeMXBean().uptime.toUptime())
|
.append(ManagementFactory.getRuntimeMXBean().uptime.toUptime())
|
||||||
.append(" [Entries: ")
|
.append(" [Entries: ")
|
||||||
.append(LinksManager.entries.links.size)
|
.append(LinksManager.entries.links.size)
|
||||||
if (seen.isEnabled()) {
|
if (seen.isEnabled()) {
|
||||||
info.append(", Seen: ").append(seen.count())
|
info.append(", Seen: ").append(seen.count())
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,8 +39,8 @@ import org.pircbotx.hooks.types.GenericMessageEvent
|
||||||
class Msg : AbstractCommand() {
|
class Msg : AbstractCommand() {
|
||||||
override val name = "msg"
|
override val name = "msg"
|
||||||
override val help = listOf(
|
override val help = listOf(
|
||||||
"To have the bot send a private message to someone:",
|
"To have the bot send a private message to someone:",
|
||||||
helpFormat("%c $name <nick> <text>")
|
helpFormat("%c $name <nick> <text>")
|
||||||
)
|
)
|
||||||
override val isOpOnly = true
|
override val isOpOnly = true
|
||||||
override val isPublic = false
|
override val isPublic = false
|
||||||
|
|
|
@ -41,8 +41,8 @@ import java.time.LocalDateTime
|
||||||
class Recap : AbstractCommand() {
|
class Recap : AbstractCommand() {
|
||||||
override val name = "recap"
|
override val name = "recap"
|
||||||
override val help = listOf(
|
override val help = listOf(
|
||||||
"To list the last 10 public channel messages:",
|
"To list the last 10 public channel messages:",
|
||||||
helpFormat("%c $name")
|
helpFormat("%c $name")
|
||||||
)
|
)
|
||||||
override val isOpOnly = false
|
override val isOpOnly = false
|
||||||
override val isPublic = true
|
override val isPublic = true
|
||||||
|
@ -60,8 +60,8 @@ class Recap : AbstractCommand() {
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun storeRecap(sender: String, message: String, isAction: Boolean) {
|
fun storeRecap(sender: String, message: String, isAction: Boolean) {
|
||||||
recaps.add(
|
recaps.add(
|
||||||
LocalDateTime.now(Clock.systemUTC()).toUtcDateTime()
|
LocalDateTime.now(Clock.systemUTC()).toUtcDateTime()
|
||||||
+ " - $sender" + (if (isAction) " " else ": ") + message
|
+ " - $sender" + (if (isAction) " " else ": ") + message
|
||||||
)
|
)
|
||||||
if (recaps.size > MAX_RECAPS) {
|
if (recaps.size > MAX_RECAPS) {
|
||||||
recaps.removeFirst()
|
recaps.removeFirst()
|
||||||
|
|
|
@ -40,10 +40,10 @@ import org.pircbotx.hooks.types.GenericMessageEvent
|
||||||
|
|
||||||
class Versions : AbstractCommand() {
|
class Versions : AbstractCommand() {
|
||||||
private val allVersions = listOf(
|
private val allVersions = listOf(
|
||||||
"Version: ${ReleaseInfo.VERSION} (${ReleaseInfo.BUILDDATE.toIsoLocalDate()})",
|
"Version: ${ReleaseInfo.VERSION} (${ReleaseInfo.BUILDDATE.toIsoLocalDate()})",
|
||||||
"${System.getProperty("os.name")} ${System.getProperty("os.version")} (${System.getProperty("os.arch")})" +
|
"${System.getProperty("os.name")} ${System.getProperty("os.version")} (${System.getProperty("os.arch")})" +
|
||||||
", JVM ${System.getProperty("java.runtime.version")}",
|
", JVM ${System.getProperty("java.runtime.version")}",
|
||||||
"Kotlin ${KotlinVersion.CURRENT}, PircBotX ${PircBotX.VERSION}"
|
"Kotlin ${KotlinVersion.CURRENT}, PircBotX ${PircBotX.VERSION}"
|
||||||
)
|
)
|
||||||
override val name = "versions"
|
override val name = "versions"
|
||||||
override val help = listOf("To view the versions data (bot, platform, java, etc.):", helpFormat("%c $name"))
|
override val help = listOf("To view the versions data (bot, platform, java, etc.):", helpFormat("%c $name"))
|
||||||
|
|
|
@ -45,13 +45,13 @@ import org.pircbotx.hooks.types.GenericMessageEvent
|
||||||
class Comment : AbstractCommand() {
|
class Comment : AbstractCommand() {
|
||||||
override val name = COMMAND
|
override val name = COMMAND
|
||||||
override val help = listOf(
|
override val help = listOf(
|
||||||
"To add a comment:",
|
"To add a comment:",
|
||||||
helpFormat("${Constants.LINK_CMD}1:This is a comment"),
|
helpFormat("${Constants.LINK_CMD}1:This is a comment"),
|
||||||
"I will reply with a label, for example: ${Constants.LINK_CMD.bold()}1.1",
|
"I will reply with a label, for example: ${Constants.LINK_CMD.bold()}1.1",
|
||||||
"To edit a comment, use its label: ",
|
"To edit a comment, use its label: ",
|
||||||
helpFormat("${Constants.LINK_CMD}1.1:This is an edited comment"),
|
helpFormat("${Constants.LINK_CMD}1.1:This is an edited comment"),
|
||||||
"To delete a comment, use its label and a minus sign: ",
|
"To delete a comment, use its label and a minus sign: ",
|
||||||
helpFormat("${Constants.LINK_CMD}1.1:-")
|
helpFormat("${Constants.LINK_CMD}1.1:-")
|
||||||
)
|
)
|
||||||
override val isOpOnly = false
|
override val isOpOnly = false
|
||||||
override val isPublic = true
|
override val isPublic = true
|
||||||
|
@ -100,12 +100,12 @@ class Comment : AbstractCommand() {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun changeAuthor(
|
private fun changeAuthor(
|
||||||
channel: String,
|
channel: String,
|
||||||
cmd: String,
|
cmd: String,
|
||||||
entry: EntryLink,
|
entry: EntryLink,
|
||||||
entryIndex: Int,
|
entryIndex: Int,
|
||||||
commentIndex: Int,
|
commentIndex: Int,
|
||||||
event: GenericMessageEvent
|
event: GenericMessageEvent
|
||||||
) {
|
) {
|
||||||
if (event.isChannelOp(channel) && cmd.length > 1) {
|
if (event.isChannelOp(channel) && cmd.length > 1) {
|
||||||
val comment = entry.getComment(commentIndex)
|
val comment = entry.getComment(commentIndex)
|
||||||
|
@ -118,11 +118,11 @@ class Comment : AbstractCommand() {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun deleteComment(
|
private fun deleteComment(
|
||||||
channel: String,
|
channel: String,
|
||||||
entry: EntryLink,
|
entry: EntryLink,
|
||||||
entryIndex: Int,
|
entryIndex: Int,
|
||||||
commentIndex: Int,
|
commentIndex: Int,
|
||||||
event: GenericMessageEvent
|
event: GenericMessageEvent
|
||||||
) {
|
) {
|
||||||
if (event.isChannelOp(channel) || event.user.nick == entry.getComment(commentIndex).nick) {
|
if (event.isChannelOp(channel) || event.user.nick == entry.getComment(commentIndex).nick) {
|
||||||
entry.deleteComment(commentIndex)
|
entry.deleteComment(commentIndex)
|
||||||
|
@ -134,11 +134,11 @@ class Comment : AbstractCommand() {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setComment(
|
private fun setComment(
|
||||||
cmd: String,
|
cmd: String,
|
||||||
entry: EntryLink,
|
entry: EntryLink,
|
||||||
entryIndex: Int,
|
entryIndex: Int,
|
||||||
commentIndex: Int,
|
commentIndex: Int,
|
||||||
event: GenericMessageEvent
|
event: GenericMessageEvent
|
||||||
) {
|
) {
|
||||||
entry.setComment(commentIndex, cmd, event.user.nick)
|
entry.setComment(commentIndex, cmd, event.user.nick)
|
||||||
event.sendMessage(printComment(entryIndex, commentIndex, entry.getComment(commentIndex)))
|
event.sendMessage(printComment(entryIndex, commentIndex, entry.getComment(commentIndex)))
|
||||||
|
|
|
@ -161,8 +161,8 @@ class LinksManager : AbstractCommand() {
|
||||||
internal fun fetchTitle(link: String): String {
|
internal fun fetchTitle(link: String): String {
|
||||||
try {
|
try {
|
||||||
val html = Jsoup.connect(link)
|
val html = Jsoup.connect(link)
|
||||||
.userAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:74.0) Gecko/20100101 Firefox/74.0")
|
.userAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:74.0) Gecko/20100101 Firefox/74.0")
|
||||||
.get()
|
.get()
|
||||||
val title = html.title()
|
val title = html.title()
|
||||||
if (title.isNotBlank()) {
|
if (title.isNotBlank()) {
|
||||||
return title
|
return title
|
||||||
|
@ -178,7 +178,7 @@ class LinksManager : AbstractCommand() {
|
||||||
return try {
|
return try {
|
||||||
val match = entries.links.single { it.link == link }
|
val match = entries.links.single { it.link == link }
|
||||||
event.sendMessage(
|
event.sendMessage(
|
||||||
"Duplicate".bold() + " >> " + printLink(entries.links.indexOf(match), match)
|
"Duplicate".bold() + " >> " + printLink(entries.links.indexOf(match), match)
|
||||||
)
|
)
|
||||||
true
|
true
|
||||||
} catch (ignore: NoSuchElementException) {
|
} catch (ignore: NoSuchElementException) {
|
||||||
|
|
|
@ -47,16 +47,16 @@ import org.pircbotx.hooks.types.GenericMessageEvent
|
||||||
class Posting : AbstractCommand() {
|
class Posting : AbstractCommand() {
|
||||||
override val name = "posting"
|
override val name = "posting"
|
||||||
override val help = listOf(
|
override val help = listOf(
|
||||||
"Post a URL, by saying it on a line on its own:",
|
"Post a URL, by saying it on a line on its own:",
|
||||||
helpFormat("<url> [<title>] ${Tags.COMMAND}: <+tag> [...]]"),
|
helpFormat("<url> [<title>] ${Tags.COMMAND}: <+tag> [...]]"),
|
||||||
"I will reply with a label, for example: ${Constants.LINK_CMD.bold()}1",
|
"I will reply with a label, for example: ${Constants.LINK_CMD.bold()}1",
|
||||||
"To add a title, use its label and a pipe:",
|
"To add a title, use its label and a pipe:",
|
||||||
helpFormat("${Constants.LINK_CMD}1:|This is the title"),
|
helpFormat("${Constants.LINK_CMD}1:|This is the title"),
|
||||||
"To add a comment:",
|
"To add a comment:",
|
||||||
helpFormat("${Constants.LINK_CMD}1:This is a comment"),
|
helpFormat("${Constants.LINK_CMD}1:This is a comment"),
|
||||||
"I will reply with a label, for example: ${Constants.LINK_CMD.bold()}1.1",
|
"I will reply with a label, for example: ${Constants.LINK_CMD.bold()}1.1",
|
||||||
"To edit a comment, see: ",
|
"To edit a comment, see: ",
|
||||||
helpFormat("%c ${Constants.HELP_CMD} ${Comment.COMMAND}")
|
helpFormat("%c ${Constants.HELP_CMD} ${Comment.COMMAND}")
|
||||||
)
|
)
|
||||||
override val isOpOnly = false
|
override val isOpOnly = false
|
||||||
override val isPublic = true
|
override val isPublic = true
|
||||||
|
|
|
@ -44,8 +44,8 @@ import org.pircbotx.hooks.types.GenericMessageEvent
|
||||||
class Tags : AbstractCommand() {
|
class Tags : AbstractCommand() {
|
||||||
override val name = COMMAND
|
override val name = COMMAND
|
||||||
override val help = listOf(
|
override val help = listOf(
|
||||||
"To categorize or tag a URL, use its label and a ${Constants.TAG_CMD}:",
|
"To categorize or tag a URL, use its label and a ${Constants.TAG_CMD}:",
|
||||||
helpFormat("${Constants.LINK_CMD}1${Constants.TAG_CMD}:<+tag|-tag> [...]")
|
helpFormat("${Constants.LINK_CMD}1${Constants.TAG_CMD}:<+tag|-tag> [...]")
|
||||||
)
|
)
|
||||||
override val isOpOnly = false
|
override val isOpOnly = false
|
||||||
override val isPublic = true
|
override val isPublic = true
|
||||||
|
|
|
@ -46,8 +46,8 @@ import org.pircbotx.hooks.types.GenericMessageEvent
|
||||||
class View : AbstractCommand() {
|
class View : AbstractCommand() {
|
||||||
override val name = VIEW_CMD
|
override val name = VIEW_CMD
|
||||||
override val help = listOf(
|
override val help = listOf(
|
||||||
"To list or search the current URL posts:",
|
"To list or search the current URL posts:",
|
||||||
helpFormat("%c $name [<start>] [<query>]")
|
helpFormat("%c $name [<start>] [<query>]")
|
||||||
)
|
)
|
||||||
override val isOpOnly = false
|
override val isOpOnly = false
|
||||||
override val isPublic = true
|
override val isPublic = true
|
||||||
|
@ -107,9 +107,9 @@ class View : AbstractCommand() {
|
||||||
if (sent == MAX_ENTRIES && index < entries.links.size) {
|
if (sent == MAX_ENTRIES && index < entries.links.size) {
|
||||||
event.sendMessage("To view more, try: ")
|
event.sendMessage("To view more, try: ")
|
||||||
event.sendMessage(
|
event.sendMessage(
|
||||||
helpFormat(
|
helpFormat(
|
||||||
helpCmdSyntax("%c $name ${index + 1} $query", event.bot().nick, event is PrivateMessageEvent)
|
helpCmdSyntax("%c $name ${index + 1} $query", event.bot().nick, event is PrivateMessageEvent)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,7 +58,7 @@ class Seen(private val serialObject: String) : AbstractCommand() {
|
||||||
override val name = "seen"
|
override val name = "seen"
|
||||||
override val help = listOf("To view when a nickname was last seen:", helpFormat("%c $name <nick>"))
|
override val help = listOf("To view when a nickname was last seen:", helpFormat("%c $name <nick>"))
|
||||||
private val helpOp = help.plus(
|
private val helpOp = help.plus(
|
||||||
arrayOf("To view all ${"seen".bold()} nicks:", helpFormat("%c $name $allKeyword"))
|
arrayOf("To view all ${"seen".bold()} nicks:", helpFormat("%c $name $allKeyword"))
|
||||||
)
|
)
|
||||||
override val isOpOnly = false
|
override val isOpOnly = false
|
||||||
override val isPublic = true
|
override val isPublic = true
|
||||||
|
@ -130,12 +130,12 @@ class Seen(private val serialObject: String) : AbstractCommand() {
|
||||||
if (isEnabled()) {
|
if (isEnabled()) {
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
seenNicks.putAll(
|
seenNicks.putAll(
|
||||||
loadSerialData(
|
loadSerialData(
|
||||||
serialObject,
|
serialObject,
|
||||||
TreeMap<String, SeenNick>(),
|
TreeMap<String, SeenNick>(),
|
||||||
logger,
|
logger,
|
||||||
"seen nicknames"
|
"seen nicknames"
|
||||||
) as TreeMap<String, SeenNick>
|
) as TreeMap<String, SeenNick>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,11 +66,11 @@ class Tell(private val serialObject: String) : AbstractCommand() {
|
||||||
override val name = "tell"
|
override val name = "tell"
|
||||||
|
|
||||||
override val help = listOf(
|
override val help = listOf(
|
||||||
"To send a message to someone when they join the channel:",
|
"To send a message to someone when they join the channel:",
|
||||||
helpFormat("%c $name <nick> <message>"),
|
helpFormat("%c $name <nick> <message>"),
|
||||||
"To view queued and sent messages:",
|
"To view queued and sent messages:",
|
||||||
helpFormat("%c $name ${View.VIEW_CMD}"),
|
helpFormat("%c $name ${View.VIEW_CMD}"),
|
||||||
"Messages are kept for ${maxDays.bold()}" + " day".plural(maxDays.toLong()) + '.'
|
"Messages are kept for ${maxDays.bold()}" + " day".plural(maxDays.toLong()) + '.'
|
||||||
)
|
)
|
||||||
override val isOpOnly: Boolean = false
|
override val isOpOnly: Boolean = false
|
||||||
override val isPublic: Boolean = isEnabled()
|
override val isPublic: Boolean = isEnabled()
|
||||||
|
@ -118,9 +118,9 @@ class Tell(private val serialObject: String) : AbstractCommand() {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (messages.removeIf {
|
if (messages.removeIf {
|
||||||
it.id == id &&
|
it.id == id &&
|
||||||
(it.sender.equals(event.user.nick, true) || event.isChannelOp(channel))
|
(it.sender.equals(event.user.nick, true) || event.isChannelOp(channel))
|
||||||
}) {
|
}) {
|
||||||
save()
|
save()
|
||||||
event.sendMessage("The message was deleted from the queue.")
|
event.sendMessage("The message was deleted from the queue.")
|
||||||
} else {
|
} else {
|
||||||
|
@ -180,7 +180,7 @@ class Tell(private val serialObject: String) : AbstractCommand() {
|
||||||
if (message.sender == nickname) {
|
if (message.sender == nickname) {
|
||||||
if (event !is MessageEvent) {
|
if (event !is MessageEvent) {
|
||||||
event.user.send().message(
|
event.user.send().message(
|
||||||
"${"You".bold()} wanted me to remind you: ${message.message.reverseColor()}"
|
"${"You".bold()} wanted me to remind you: ${message.message.reverseColor()}"
|
||||||
)
|
)
|
||||||
message.isReceived = true
|
message.isReceived = true
|
||||||
message.isNotified = true
|
message.isNotified = true
|
||||||
|
@ -188,17 +188,17 @@ class Tell(private val serialObject: String) : AbstractCommand() {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
event.user.send().message(
|
event.user.send().message(
|
||||||
"${message.sender} wanted me to tell you: ${message.message.reverseColor()}"
|
"${message.sender} wanted me to tell you: ${message.message.reverseColor()}"
|
||||||
)
|
)
|
||||||
message.isReceived = true
|
message.isReceived = true
|
||||||
save()
|
save()
|
||||||
}
|
}
|
||||||
} else if (message.sender.equals(nickname, ignoreCase = true) && message.isReceived
|
} else if (message.sender.equals(nickname, ignoreCase = true) && message.isReceived
|
||||||
&& !message.isNotified
|
&& !message.isNotified
|
||||||
) {
|
) {
|
||||||
event.user.send().message(
|
event.user.send().message(
|
||||||
"Your message ${"[ID ${message.id}]".reverseColor()} was sent to "
|
"Your message ${"[ID ${message.id}]".reverseColor()} was sent to "
|
||||||
+ "${message.recipient.bold()} on ${message.receptionDate}"
|
+ "${message.recipient.bold()} on ${message.receptionDate}"
|
||||||
)
|
)
|
||||||
message.isNotified = true
|
message.isNotified = true
|
||||||
save()
|
save()
|
||||||
|
@ -219,8 +219,8 @@ class Tell(private val serialObject: String) : AbstractCommand() {
|
||||||
if (messages.isNotEmpty()) {
|
if (messages.isNotEmpty()) {
|
||||||
for (message in messages) {
|
for (message in messages) {
|
||||||
event.sendMessage(
|
event.sendMessage(
|
||||||
"${message.sender.bold()}$ARROW${message.recipient.bold()} [ID: ${message.id}, " +
|
"${message.sender.bold()}$ARROW${message.recipient.bold()} [ID: ${message.id}, " +
|
||||||
(if (message.isReceived) "DELIVERED]" else "QUEUED]")
|
(if (message.isReceived) "DELIVERED]" else "QUEUED]")
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -238,13 +238,13 @@ class Tell(private val serialObject: String) : AbstractCommand() {
|
||||||
}
|
}
|
||||||
if (message.isReceived) {
|
if (message.isReceived) {
|
||||||
event.sendMessage(
|
event.sendMessage(
|
||||||
message.sender.bold() + ARROW + message.recipient.bold() +
|
message.sender.bold() + ARROW + message.recipient.bold() +
|
||||||
" [${message.receptionDate.toUtcDateTime()}, ID: ${message.id.bold()}, DELIVERED]"
|
" [${message.receptionDate.toUtcDateTime()}, ID: ${message.id.bold()}, DELIVERED]"
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
event.sendMessage(
|
event.sendMessage(
|
||||||
message.sender.bold() + ARROW + message.recipient.bold() +
|
message.sender.bold() + ARROW + message.recipient.bold() +
|
||||||
" [${message.queued.toUtcDateTime()}, ID: ${message.id.bold()}, QUEUED]"
|
" [${message.queued.toUtcDateTime()}, ID: ${message.id.bold()}, QUEUED]"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
event.sendMessage(helpFormat(message.message))
|
event.sendMessage(helpFormat(message.message))
|
||||||
|
@ -254,9 +254,9 @@ class Tell(private val serialObject: String) : AbstractCommand() {
|
||||||
} else {
|
} else {
|
||||||
event.sendMessage("To delete one or all delivered messages:")
|
event.sendMessage("To delete one or all delivered messages:")
|
||||||
event.sendMessage(
|
event.sendMessage(
|
||||||
helpFormat(
|
helpFormat(
|
||||||
helpCmdSyntax("%c $name $TELL_DEL_KEYWORD <id|$TELL_ALL_KEYWORD>", event.bot().nick, true)
|
helpCmdSyntax("%c $name $TELL_DEL_KEYWORD <id|$TELL_ALL_KEYWORD>", event.bot().nick, true)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
event.sendMessage(help.last())
|
event.sendMessage(help.last())
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,20 +39,20 @@ import java.time.format.DateTimeFormatter
|
||||||
* Tell Message.
|
* Tell Message.
|
||||||
*/
|
*/
|
||||||
class TellMessage(
|
class TellMessage(
|
||||||
/**
|
/**
|
||||||
* Returns the message's sender.
|
* Returns the message's sender.
|
||||||
*/
|
*/
|
||||||
val sender: String,
|
val sender: String,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the message's recipient.
|
* Returns the message's recipient.
|
||||||
*/
|
*/
|
||||||
val recipient: String,
|
val recipient: String,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the message text.
|
* Returns the message text.
|
||||||
*/
|
*/
|
||||||
val message: String
|
val message: String
|
||||||
) : Serializable {
|
) : Serializable {
|
||||||
/**
|
/**
|
||||||
* Returns the queued date/time.
|
* Returns the queued date/time.
|
||||||
|
|
|
@ -34,10 +34,10 @@ package net.thauvin.erik.mobibot.entries
|
||||||
import net.thauvin.erik.mobibot.Utils.today
|
import net.thauvin.erik.mobibot.Utils.today
|
||||||
|
|
||||||
class Entries(
|
class Entries(
|
||||||
var channel: String = "",
|
var channel: String = "",
|
||||||
var ircServer: String = "",
|
var ircServer: String = "",
|
||||||
var logsDir: String = "",
|
var logsDir: String = "",
|
||||||
var backlogs: String = ""
|
var backlogs: String = ""
|
||||||
) {
|
) {
|
||||||
val links = mutableListOf<EntryLink>()
|
val links = mutableListOf<EntryLink>()
|
||||||
|
|
||||||
|
|
|
@ -43,7 +43,7 @@ object EntriesUtils {
|
||||||
*/
|
*/
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun printComment(entryIndex: Int, commentIndex: Int, comment: EntryComment): String =
|
fun printComment(entryIndex: Int, commentIndex: Int, comment: EntryComment): String =
|
||||||
("${entryIndex.toLinkLabel()}.${commentIndex + 1}: [${comment.nick}] ${comment.comment}")
|
("${entryIndex.toLinkLabel()}.${commentIndex + 1}: [${comment.nick}] ${comment.comment}")
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prints an entry's link for display on the channel.
|
* Prints an entry's link for display on the channel.
|
||||||
|
@ -52,7 +52,7 @@ object EntriesUtils {
|
||||||
@JvmOverloads
|
@JvmOverloads
|
||||||
fun printLink(entryIndex: Int, entry: EntryLink, isView: Boolean = false): String {
|
fun printLink(entryIndex: Int, entry: EntryLink, isView: Boolean = false): String {
|
||||||
val buff = StringBuilder().append(entryIndex.toLinkLabel()).append(": ")
|
val buff = StringBuilder().append(entryIndex.toLinkLabel()).append(": ")
|
||||||
.append('[').append(entry.nick).append(']')
|
.append('[').append(entry.nick).append(']')
|
||||||
if (isView && entry.comments.isNotEmpty()) {
|
if (isView && entry.comments.isNotEmpty()) {
|
||||||
buff.append("[+").append(entry.comments.size).append(']')
|
buff.append("[+").append(entry.comments.size).append(']')
|
||||||
}
|
}
|
||||||
|
@ -73,7 +73,7 @@ object EntriesUtils {
|
||||||
*/
|
*/
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun printTags(entryIndex: Int, entry: EntryLink): String =
|
fun printTags(entryIndex: Int, entry: EntryLink): String =
|
||||||
entryIndex.toLinkLabel() + "${Constants.TAG_CMD}: " + entry.formatTags(", ")
|
entryIndex.toLinkLabel() + "${Constants.TAG_CMD}: " + entry.formatTags(", ")
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Builds link label based on its index. e.g: L1
|
* Builds link label based on its index. e.g: L1
|
||||||
|
|
|
@ -34,47 +34,46 @@ import com.rometools.rome.feed.synd.SyndCategory
|
||||||
import com.rometools.rome.feed.synd.SyndCategoryImpl
|
import com.rometools.rome.feed.synd.SyndCategoryImpl
|
||||||
import net.thauvin.erik.mobibot.commands.links.LinksManager
|
import net.thauvin.erik.mobibot.commands.links.LinksManager
|
||||||
import java.io.Serializable
|
import java.io.Serializable
|
||||||
import java.util.Calendar
|
import java.util.*
|
||||||
import java.util.Date
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The class used to store link entries.
|
* The class used to store link entries.
|
||||||
*/
|
*/
|
||||||
class EntryLink(
|
class EntryLink(
|
||||||
// Link's comments
|
// Link's comments
|
||||||
val comments: MutableList<EntryComment> = mutableListOf(),
|
val comments: MutableList<EntryComment> = mutableListOf(),
|
||||||
|
|
||||||
// Tags/categories
|
// Tags/categories
|
||||||
val tags: MutableList<SyndCategory> = mutableListOf(),
|
val tags: MutableList<SyndCategory> = mutableListOf(),
|
||||||
|
|
||||||
// Channel
|
// Channel
|
||||||
var channel: String,
|
var channel: String,
|
||||||
|
|
||||||
// Creation date
|
// Creation date
|
||||||
var date: Date = Calendar.getInstance().time,
|
var date: Date = Calendar.getInstance().time,
|
||||||
|
|
||||||
// Link's URL
|
// Link's URL
|
||||||
var link: String,
|
var link: String,
|
||||||
|
|
||||||
// Author's login
|
// Author's login
|
||||||
var login: String = "",
|
var login: String = "",
|
||||||
|
|
||||||
// Author's nickname
|
// Author's nickname
|
||||||
var nick: String,
|
var nick: String,
|
||||||
|
|
||||||
// Link's title
|
// Link's title
|
||||||
var title: String
|
var title: String
|
||||||
) : Serializable {
|
) : Serializable {
|
||||||
/**
|
/**
|
||||||
* Creates a new entry.
|
* Creates a new entry.
|
||||||
*/
|
*/
|
||||||
constructor(
|
constructor(
|
||||||
link: String,
|
link: String,
|
||||||
title: String,
|
title: String,
|
||||||
nick: String,
|
nick: String,
|
||||||
login: String,
|
login: String,
|
||||||
channel: String,
|
channel: String,
|
||||||
tags: List<String?>
|
tags: List<String?>
|
||||||
) : this(link = link, title = title, nick = nick, login = login, channel = channel) {
|
) : this(link = link, title = title, nick = nick, login = login, channel = channel) {
|
||||||
setTags(tags)
|
setTags(tags)
|
||||||
}
|
}
|
||||||
|
@ -83,12 +82,12 @@ class EntryLink(
|
||||||
* Creates a new entry.
|
* Creates a new entry.
|
||||||
*/
|
*/
|
||||||
constructor(
|
constructor(
|
||||||
link: String,
|
link: String,
|
||||||
title: String,
|
title: String,
|
||||||
nick: String,
|
nick: String,
|
||||||
channel: String,
|
channel: String,
|
||||||
date: Date,
|
date: Date,
|
||||||
tags: List<SyndCategory>
|
tags: List<SyndCategory>
|
||||||
) : this(link = link, title = title, nick = nick, channel = channel, date = Date(date.time)) {
|
) : this(link = link, title = title, nick = nick, channel = channel, date = Date(date.time)) {
|
||||||
this.tags.addAll(tags)
|
this.tags.addAll(tags)
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,11 +30,7 @@
|
||||||
*/
|
*/
|
||||||
package net.thauvin.erik.mobibot.entries
|
package net.thauvin.erik.mobibot.entries
|
||||||
|
|
||||||
import com.rometools.rome.feed.synd.SyndContentImpl
|
import com.rometools.rome.feed.synd.*
|
||||||
import com.rometools.rome.feed.synd.SyndEntry
|
|
||||||
import com.rometools.rome.feed.synd.SyndEntryImpl
|
|
||||||
import com.rometools.rome.feed.synd.SyndFeed
|
|
||||||
import com.rometools.rome.feed.synd.SyndFeedImpl
|
|
||||||
import com.rometools.rome.io.FeedException
|
import com.rometools.rome.io.FeedException
|
||||||
import com.rometools.rome.io.SyndFeedInput
|
import com.rometools.rome.io.SyndFeedInput
|
||||||
import com.rometools.rome.io.SyndFeedOutput
|
import com.rometools.rome.io.SyndFeedOutput
|
||||||
|
@ -48,7 +44,7 @@ import java.io.OutputStreamWriter
|
||||||
import java.nio.charset.StandardCharsets
|
import java.nio.charset.StandardCharsets
|
||||||
import java.nio.file.Files
|
import java.nio.file.Files
|
||||||
import java.nio.file.Paths
|
import java.nio.file.Paths
|
||||||
import java.util.Calendar
|
import java.util.*
|
||||||
import kotlin.io.path.exists
|
import kotlin.io.path.exists
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -76,7 +72,7 @@ class FeedsManager private constructor() {
|
||||||
if (xml.exists()) {
|
if (xml.exists()) {
|
||||||
val input = SyndFeedInput()
|
val input = SyndFeedInput()
|
||||||
InputStreamReader(
|
InputStreamReader(
|
||||||
Files.newInputStream(xml), StandardCharsets.UTF_8
|
Files.newInputStream(xml), StandardCharsets.UTF_8
|
||||||
).use { reader ->
|
).use { reader ->
|
||||||
val feed = input.build(reader)
|
val feed = input.build(reader)
|
||||||
pubDate = feed.publishedDate.toIsoLocalDate()
|
pubDate = feed.publishedDate.toIsoLocalDate()
|
||||||
|
@ -85,12 +81,12 @@ class FeedsManager private constructor() {
|
||||||
for (i in items.indices.reversed()) {
|
for (i in items.indices.reversed()) {
|
||||||
with(items[i]) {
|
with(items[i]) {
|
||||||
entry = EntryLink(
|
entry = EntryLink(
|
||||||
link,
|
link,
|
||||||
title,
|
title,
|
||||||
author.substring(author.lastIndexOf('(') + 1, author.length - 1),
|
author.substring(author.lastIndexOf('(') + 1, author.length - 1),
|
||||||
entries.channel,
|
entries.channel,
|
||||||
publishedDate,
|
publishedDate,
|
||||||
categories
|
categories
|
||||||
)
|
)
|
||||||
var split: List<String>
|
var split: List<String>
|
||||||
for (comment in description.value.split("<br/>")) {
|
for (comment in description.value.split("<br/>")) {
|
||||||
|
@ -123,7 +119,7 @@ class FeedsManager private constructor() {
|
||||||
val items: MutableList<SyndEntry> = mutableListOf()
|
val items: MutableList<SyndEntry> = mutableListOf()
|
||||||
var item: SyndEntry
|
var item: SyndEntry
|
||||||
OutputStreamWriter(
|
OutputStreamWriter(
|
||||||
Files.newOutputStream(Paths.get("${entries.logsDir}${currentFile}")), StandardCharsets.UTF_8
|
Files.newOutputStream(Paths.get("${entries.logsDir}${currentFile}")), StandardCharsets.UTF_8
|
||||||
).use { fw ->
|
).use { fw ->
|
||||||
with(rss) {
|
with(rss) {
|
||||||
feedType = "rss_2.0"
|
feedType = "rss_2.0"
|
||||||
|
@ -138,13 +134,13 @@ class FeedsManager private constructor() {
|
||||||
with(entries.links[i]) {
|
with(entries.links[i]) {
|
||||||
buff.setLength(0)
|
buff.setLength(0)
|
||||||
buff.append("Posted by <b>")
|
buff.append("Posted by <b>")
|
||||||
.append(nick)
|
.append(nick)
|
||||||
.append("</b> on <a href=\"irc://")
|
.append("</b> on <a href=\"irc://")
|
||||||
.append(entries.ircServer).append('/')
|
.append(entries.ircServer).append('/')
|
||||||
.append(channel)
|
.append(channel)
|
||||||
.append("\"><b>")
|
.append("\"><b>")
|
||||||
.append(channel)
|
.append(channel)
|
||||||
.append("</b></a>")
|
.append("</b></a>")
|
||||||
if (comments.size > 0) {
|
if (comments.size > 0) {
|
||||||
buff.append(" <br/><br/>")
|
buff.append(" <br/><br/>")
|
||||||
for (j in comments.indices) {
|
for (j in comments.indices) {
|
||||||
|
@ -169,11 +165,11 @@ class FeedsManager private constructor() {
|
||||||
output.output(rss, fw)
|
output.output(rss, fw)
|
||||||
}
|
}
|
||||||
OutputStreamWriter(
|
OutputStreamWriter(
|
||||||
Files.newOutputStream(
|
Files.newOutputStream(
|
||||||
Paths.get(
|
Paths.get(
|
||||||
entries.logsDir + today() + dotXml
|
entries.logsDir + today() + dotXml
|
||||||
)
|
)
|
||||||
), StandardCharsets.UTF_8
|
), StandardCharsets.UTF_8
|
||||||
).use { fw -> output.output(rss, fw) }
|
).use { fw -> output.output(rss, fw) }
|
||||||
} catch (e: FeedException) {
|
} catch (e: FeedException) {
|
||||||
if (logger.isWarnEnabled) logger.warn("Unable to generate the entries feed.", e)
|
if (logger.isWarnEnabled) logger.warn("Unable to generate the entries feed.", e)
|
||||||
|
|
|
@ -55,8 +55,10 @@ class ChatGpt : AbstractModule() {
|
||||||
override fun commandResponse(channel: String, cmd: String, args: String, event: GenericMessageEvent) {
|
override fun commandResponse(channel: String, cmd: String, args: String, event: GenericMessageEvent) {
|
||||||
if (args.isNotBlank()) {
|
if (args.isNotBlank()) {
|
||||||
try {
|
try {
|
||||||
val answer = chat(args.trim(), properties[API_KEY_PROP],
|
val answer = chat(
|
||||||
properties.getOrDefault(MAX_TOKENS_PROP, "1024").toInt())
|
args.trim(), properties[API_KEY_PROP],
|
||||||
|
properties.getOrDefault(MAX_TOKENS_PROP, "1024").toInt()
|
||||||
|
)
|
||||||
if (answer.isNotBlank()) {
|
if (answer.isNotBlank()) {
|
||||||
event.sendMessage(WordUtils.wrap(answer, 400))
|
event.sendMessage(WordUtils.wrap(answer, 400))
|
||||||
} else {
|
} else {
|
||||||
|
@ -105,13 +107,13 @@ class ChatGpt : AbstractModule() {
|
||||||
if (!apiKey.isNullOrEmpty()) {
|
if (!apiKey.isNullOrEmpty()) {
|
||||||
val prompt = JSONWriter.valueToString("Q:$query\nA:")
|
val prompt = JSONWriter.valueToString("Q:$query\nA:")
|
||||||
val request = HttpRequest.newBuilder()
|
val request = HttpRequest.newBuilder()
|
||||||
.uri(URI.create(API_URL))
|
.uri(URI.create(API_URL))
|
||||||
.header("Content-Type", "application/json")
|
.header("Content-Type", "application/json")
|
||||||
.header("Authorization", "Bearer $apiKey")
|
.header("Authorization", "Bearer $apiKey")
|
||||||
.header("User-Agent", Constants.USER_AGENT)
|
.header("User-Agent", Constants.USER_AGENT)
|
||||||
.POST(
|
.POST(
|
||||||
HttpRequest.BodyPublishers.ofString(
|
HttpRequest.BodyPublishers.ofString(
|
||||||
"""{
|
"""{
|
||||||
"model": "text-davinci-003",
|
"model": "text-davinci-003",
|
||||||
"prompt": $prompt,
|
"prompt": $prompt,
|
||||||
"temperature": 0,
|
"temperature": 0,
|
||||||
|
@ -120,9 +122,9 @@ class ChatGpt : AbstractModule() {
|
||||||
"frequency_penalty": 0,
|
"frequency_penalty": 0,
|
||||||
"presence_penalty": 0
|
"presence_penalty": 0
|
||||||
}""".trimIndent()
|
}""".trimIndent()
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
.build()
|
||||||
.build()
|
|
||||||
try {
|
try {
|
||||||
val response = HttpClient.newHttpClient().send(request, HttpResponse.BodyHandlers.ofString())
|
val response = HttpClient.newHttpClient().send(request, HttpResponse.BodyHandlers.ofString())
|
||||||
if (response.statusCode() == 200) {
|
if (response.statusCode() == 200) {
|
||||||
|
@ -132,16 +134,16 @@ class ChatGpt : AbstractModule() {
|
||||||
return choices.getJSONObject(0).getString("text").trim()
|
return choices.getJSONObject(0).getString("text").trim()
|
||||||
} catch (e: JSONException) {
|
} catch (e: JSONException) {
|
||||||
throw ModuleException(
|
throw ModuleException(
|
||||||
"$CHATGPT_CMD($query): JSON",
|
"$CHATGPT_CMD($query): JSON",
|
||||||
"A JSON error has occurred while conversing with $CHATGPT_NAME.",
|
"A JSON error has occurred while conversing with $CHATGPT_NAME.",
|
||||||
e
|
e
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (response.statusCode() == 429) {
|
if (response.statusCode() == 429) {
|
||||||
throw ModuleException(
|
throw ModuleException(
|
||||||
"$CHATGPT_CMD($query): Rate limit reached",
|
"$CHATGPT_CMD($query): Rate limit reached",
|
||||||
"Rate limit reached. Please try again later."
|
"Rate limit reached. Please try again later."
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
throw IOException("HTTP Status Code: " + response.statusCode())
|
throw IOException("HTTP Status Code: " + response.statusCode())
|
||||||
|
@ -149,9 +151,9 @@ class ChatGpt : AbstractModule() {
|
||||||
}
|
}
|
||||||
} catch (e: IOException) {
|
} catch (e: IOException) {
|
||||||
throw ModuleException(
|
throw ModuleException(
|
||||||
"$CHATGPT_CMD($query): IO",
|
"$CHATGPT_CMD($query): IO",
|
||||||
"An IO error has occurred while conversing with $CHATGPT_NAME.",
|
"An IO error has occurred while conversing with $CHATGPT_NAME.",
|
||||||
e
|
e
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -134,9 +134,9 @@ class CryptoPrices : AbstractModule() {
|
||||||
}
|
}
|
||||||
} catch (e: CryptoException) {
|
} catch (e: CryptoException) {
|
||||||
throw ModuleException(
|
throw ModuleException(
|
||||||
"loadCurrencies(): CE",
|
"loadCurrencies(): CE",
|
||||||
"An error has occurred while retrieving the currencies table.",
|
"An error has occurred while retrieving the currencies table.",
|
||||||
e
|
e
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,7 +45,7 @@ import org.slf4j.Logger
|
||||||
import org.slf4j.LoggerFactory
|
import org.slf4j.LoggerFactory
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import java.net.URL
|
import java.net.URL
|
||||||
import java.util.TreeMap
|
import java.util.*
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -99,15 +99,15 @@ class CurrencyConverter : AbstractModule() {
|
||||||
event.sendMessage("To convert from one currency to another:")
|
event.sendMessage("To convert from one currency to another:")
|
||||||
event.sendMessage(helpFormat(helpCmdSyntax("%c $CURRENCY_CMD 100 USD to EUR", nick, isPrivateMsgEnabled)))
|
event.sendMessage(helpFormat(helpCmdSyntax("%c $CURRENCY_CMD 100 USD to EUR", nick, isPrivateMsgEnabled)))
|
||||||
event.sendMessage(
|
event.sendMessage(
|
||||||
helpFormat(
|
helpFormat(
|
||||||
helpCmdSyntax("%c $CURRENCY_CMD 50,000 GBP to BTC", nick, isPrivateMsgEnabled)
|
helpCmdSyntax("%c $CURRENCY_CMD 50,000 GBP to BTC", nick, isPrivateMsgEnabled)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
event.sendMessage("To list the supported currency codes:")
|
event.sendMessage("To list the supported currency codes:")
|
||||||
event.sendMessage(
|
event.sendMessage(
|
||||||
helpFormat(
|
helpFormat(
|
||||||
helpCmdSyntax("%c $CURRENCY_CMD $CODES_KEYWORD", nick, isPrivateMsgEnabled)
|
helpCmdSyntax("%c $CURRENCY_CMD $CODES_KEYWORD", nick, isPrivateMsgEnabled)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
|
@ -146,7 +146,7 @@ class CurrencyConverter : AbstractModule() {
|
||||||
|
|
||||||
if (json.getBoolean("success")) {
|
if (json.getBoolean("success")) {
|
||||||
PublicMessage(
|
PublicMessage(
|
||||||
"${cmds[0]} ${SYMBOLS[to]} = ${json.get("result")} ${SYMBOLS[from]}"
|
"${cmds[0]} ${SYMBOLS[to]} = ${json.get("result")} ${SYMBOLS[from]}"
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
ErrorMessage("Sorry, an error occurred while converting the currencies.")
|
ErrorMessage("Sorry, an error occurred while converting the currencies.")
|
||||||
|
@ -178,9 +178,9 @@ class CurrencyConverter : AbstractModule() {
|
||||||
}
|
}
|
||||||
} catch (e: IOException) {
|
} catch (e: IOException) {
|
||||||
throw ModuleException(
|
throw ModuleException(
|
||||||
"loadCodes(): IOE",
|
"loadCodes(): IOE",
|
||||||
"An IO error has occurred while retrieving the currencies.",
|
"An IO error has occurred while retrieving the currencies.",
|
||||||
e
|
e
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,10 +65,10 @@ class GoogleSearch : AbstractModule() {
|
||||||
if (args.isNotBlank()) {
|
if (args.isNotBlank()) {
|
||||||
try {
|
try {
|
||||||
val results = searchGoogle(
|
val results = searchGoogle(
|
||||||
args,
|
args,
|
||||||
properties[API_KEY_PROP],
|
properties[API_KEY_PROP],
|
||||||
properties[CSE_KEY_PROP],
|
properties[CSE_KEY_PROP],
|
||||||
event.user.nick
|
event.user.nick
|
||||||
)
|
)
|
||||||
for (msg in results) {
|
for (msg in results) {
|
||||||
if (msg.isError) {
|
if (msg.isError) {
|
||||||
|
@ -104,23 +104,23 @@ class GoogleSearch : AbstractModule() {
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
@Throws(ModuleException::class)
|
@Throws(ModuleException::class)
|
||||||
fun searchGoogle(
|
fun searchGoogle(
|
||||||
query: String,
|
query: String,
|
||||||
apiKey: String?,
|
apiKey: String?,
|
||||||
cseKey: String?,
|
cseKey: String?,
|
||||||
quotaUser: String = ReleaseInfo.PROJECT
|
quotaUser: String = ReleaseInfo.PROJECT
|
||||||
): List<Message> {
|
): List<Message> {
|
||||||
if (apiKey.isNullOrBlank() || cseKey.isNullOrBlank()) {
|
if (apiKey.isNullOrBlank() || cseKey.isNullOrBlank()) {
|
||||||
throw ModuleException(
|
throw ModuleException(
|
||||||
"${GoogleSearch::class.java.name} is disabled.",
|
"${GoogleSearch::class.java.name} is disabled.",
|
||||||
"${GOOGLE_CMD.capitalise()} is disabled. The API keys are missing."
|
"${GOOGLE_CMD.capitalise()} is disabled. The API keys are missing."
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
val results = mutableListOf<Message>()
|
val results = mutableListOf<Message>()
|
||||||
if (query.isNotBlank()) {
|
if (query.isNotBlank()) {
|
||||||
try {
|
try {
|
||||||
val url = URL(
|
val url = URL(
|
||||||
"https://www.googleapis.com/customsearch/v1?key=$apiKey&cx=$cseKey" +
|
"https://www.googleapis.com/customsearch/v1?key=$apiKey&cx=$cseKey" +
|
||||||
""aUser=${quotaUser}&q=${query.encodeUrl()}&filter=1&num=5&alt=json"
|
""aUser=${quotaUser}&q=${query.encodeUrl()}&filter=1&num=5&alt=json"
|
||||||
)
|
)
|
||||||
val json = JSONObject(url.reader().body)
|
val json = JSONObject(url.reader().body)
|
||||||
if (json.has("items")) {
|
if (json.has("items")) {
|
||||||
|
@ -141,9 +141,9 @@ class GoogleSearch : AbstractModule() {
|
||||||
throw ModuleException("searchGoogle($query): IOE", "An IO error has occurred searching Google.", e)
|
throw ModuleException("searchGoogle($query): IOE", "An IO error has occurred searching Google.", e)
|
||||||
} catch (e: JSONException) {
|
} catch (e: JSONException) {
|
||||||
throw ModuleException(
|
throw ModuleException(
|
||||||
"searchGoogle($query): JSON",
|
"searchGoogle($query): JSON",
|
||||||
"A JSON error has occurred searching Google.",
|
"A JSON error has occurred searching Google.",
|
||||||
e
|
e
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -55,9 +55,9 @@ class Lookup : AbstractModule() {
|
||||||
event.respondWith(nslookup(args).prependIndent())
|
event.respondWith(nslookup(args).prependIndent())
|
||||||
} catch (ignore: UnknownHostException) {
|
} catch (ignore: UnknownHostException) {
|
||||||
if (args.matches(
|
if (args.matches(
|
||||||
("(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)")
|
("(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)")
|
||||||
.toRegex()
|
.toRegex()
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
try {
|
try {
|
||||||
val lines = whois(args)
|
val lines = whois(args)
|
||||||
|
|
|
@ -65,7 +65,7 @@ class Mastodon : SocialModule() {
|
||||||
|
|
||||||
private fun formatTags(entry: EntryLink): String {
|
private fun formatTags(entry: EntryLink): String {
|
||||||
return entry.tags.filter { !it.name.equals(entry.channel.removePrefix("#"), true) }
|
return entry.tags.filter { !it.name.equals(entry.channel.removePrefix("#"), true) }
|
||||||
.joinToString(separator = " ", prefix = "\n\n") { "#${it.name}" }
|
.joinToString(separator = " ", prefix = "\n\n") { "#${it.name}" }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -74,11 +74,11 @@ class Mastodon : SocialModule() {
|
||||||
@Throws(ModuleException::class)
|
@Throws(ModuleException::class)
|
||||||
override fun post(message: String, isDm: Boolean): String {
|
override fun post(message: String, isDm: Boolean): String {
|
||||||
return toot(
|
return toot(
|
||||||
apiKey = properties[ACCESS_TOKEN_PROP],
|
apiKey = properties[ACCESS_TOKEN_PROP],
|
||||||
instance = properties[INSTANCE_PROP],
|
instance = properties[INSTANCE_PROP],
|
||||||
handle = handle,
|
handle = handle,
|
||||||
message = message,
|
message = message,
|
||||||
isDm = isDm
|
isDm = isDm
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,21 +99,21 @@ class Mastodon : SocialModule() {
|
||||||
@Throws(ModuleException::class)
|
@Throws(ModuleException::class)
|
||||||
fun toot(apiKey: String?, instance: String?, handle: String?, message: String, isDm: Boolean): String {
|
fun toot(apiKey: String?, instance: String?, handle: String?, message: String, isDm: Boolean): String {
|
||||||
val request = HttpRequest.newBuilder()
|
val request = HttpRequest.newBuilder()
|
||||||
.uri(URI.create("https://$instance/api/v1/statuses"))
|
.uri(URI.create("https://$instance/api/v1/statuses"))
|
||||||
.header("Content-Type", "application/json")
|
.header("Content-Type", "application/json")
|
||||||
.header("Authorization", "Bearer $apiKey")
|
.header("Authorization", "Bearer $apiKey")
|
||||||
.POST(
|
.POST(
|
||||||
HttpRequest.BodyPublishers.ofString(
|
HttpRequest.BodyPublishers.ofString(
|
||||||
JSONWriter.valueToString(
|
JSONWriter.valueToString(
|
||||||
if (isDm) {
|
if (isDm) {
|
||||||
mapOf("status" to "${handle?.prefixIfMissing('@')} $message", "visibility" to "direct")
|
mapOf("status" to "${handle?.prefixIfMissing('@')} $message", "visibility" to "direct")
|
||||||
} else {
|
} else {
|
||||||
mapOf("status" to message)
|
mapOf("status" to message)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
.build()
|
||||||
.build()
|
|
||||||
try {
|
try {
|
||||||
val response = HttpClient.newHttpClient().send(request, HttpResponse.BodyHandlers.ofString())
|
val response = HttpClient.newHttpClient().send(request, HttpResponse.BodyHandlers.ofString())
|
||||||
if (response.statusCode() == 200) {
|
if (response.statusCode() == 200) {
|
||||||
|
|
|
@ -34,9 +34,9 @@ package net.thauvin.erik.mobibot.modules
|
||||||
* The `ModuleException` class.
|
* The `ModuleException` class.
|
||||||
*/
|
*/
|
||||||
class ModuleException @JvmOverloads constructor(
|
class ModuleException @JvmOverloads constructor(
|
||||||
val debugMessage: String,
|
val debugMessage: String,
|
||||||
message: String? = null,
|
message: String? = null,
|
||||||
cause: Throwable? = null
|
cause: Throwable? = null
|
||||||
) : Exception(message, cause) {
|
) : Exception(message, cause) {
|
||||||
companion object {
|
companion object {
|
||||||
private const val serialVersionUID = 1L
|
private const val serialVersionUID = 1L
|
||||||
|
|
|
@ -50,18 +50,18 @@ class Ping : AbstractModule() {
|
||||||
*/
|
*/
|
||||||
@JvmField
|
@JvmField
|
||||||
val PINGS = listOf(
|
val PINGS = listOf(
|
||||||
"is barely alive.",
|
"is barely alive.",
|
||||||
"is trying to stay awake.",
|
"is trying to stay awake.",
|
||||||
"has gone fishing.",
|
"has gone fishing.",
|
||||||
"is somewhere over the rainbow.",
|
"is somewhere over the rainbow.",
|
||||||
"has fallen and can't get up.",
|
"has fallen and can't get up.",
|
||||||
"is running. You better go chase it.",
|
"is running. You better go chase it.",
|
||||||
"has just spontaneously combusted.",
|
"has just spontaneously combusted.",
|
||||||
"is talking to itself... don't interrupt. That's rude.",
|
"is talking to itself... don't interrupt. That's rude.",
|
||||||
"is bartending at an AA meeting.",
|
"is bartending at an AA meeting.",
|
||||||
"is hibernating.",
|
"is hibernating.",
|
||||||
"is saving energy: apathetic mode activated.",
|
"is saving energy: apathetic mode activated.",
|
||||||
"is busy. Go away!"
|
"is busy. Go away!"
|
||||||
)
|
)
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
|
|
|
@ -52,10 +52,10 @@ class RockPaperScissors : AbstractModule() {
|
||||||
with(help) {
|
with(help) {
|
||||||
add("To play Rock Paper Scissors:")
|
add("To play Rock Paper Scissors:")
|
||||||
add(
|
add(
|
||||||
helpFormat(
|
helpFormat(
|
||||||
"%c ${Hands.ROCK.name.lowercase()} | ${Hands.PAPER.name.lowercase()}"
|
"%c ${Hands.ROCK.name.lowercase()} | ${Hands.PAPER.name.lowercase()}"
|
||||||
+ " | ${Hands.SCISSORS.name.lowercase()}"
|
+ " | ${Hands.SCISSORS.name.lowercase()}"
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -96,7 +96,7 @@ class RockPaperScissors : AbstractModule() {
|
||||||
|
|
||||||
override fun commandResponse(channel: String, cmd: String, args: String, event: GenericMessageEvent) {
|
override fun commandResponse(channel: String, cmd: String, args: String, event: GenericMessageEvent) {
|
||||||
val hand = Hands.valueOf(cmd.uppercase())
|
val hand = Hands.valueOf(cmd.uppercase())
|
||||||
val botHand = Hands.values()[(0..Hands.values().size).random()]
|
val botHand = Hands.entries[(0..Hands.entries.size).random()]
|
||||||
when {
|
when {
|
||||||
hand == botHand -> {
|
hand == botHand -> {
|
||||||
event.respond("${hand.name} vs. ${botHand.name} » You ${"tie".bold()}.")
|
event.respond("${hand.name} vs. ${botHand.name} » You ${"tie".bold()}.")
|
||||||
|
|
|
@ -132,8 +132,8 @@ class StockQuote : AbstractModule() {
|
||||||
fun getQuote(symbol: String, apiKey: String?): List<Message> {
|
fun getQuote(symbol: String, apiKey: String?): List<Message> {
|
||||||
if (apiKey.isNullOrBlank()) {
|
if (apiKey.isNullOrBlank()) {
|
||||||
throw ModuleException(
|
throw ModuleException(
|
||||||
"${StockQuote::class.java.name} is disabled.",
|
"${StockQuote::class.java.name} is disabled.",
|
||||||
"${STOCK_CMD.capitalise()} is disabled. The API key is missing."
|
"${STOCK_CMD.capitalise()} is disabled. The API key is missing."
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
val messages = mutableListOf<Message>()
|
val messages = mutableListOf<Message>()
|
||||||
|
@ -144,8 +144,8 @@ class StockQuote : AbstractModule() {
|
||||||
with(messages) {
|
with(messages) {
|
||||||
// Search for symbol/keywords
|
// Search for symbol/keywords
|
||||||
response = URL(
|
response = URL(
|
||||||
"${API_URL}SYMBOL_SEARCH&keywords=" + symbol.encodeUrl() + "&apikey="
|
"${API_URL}SYMBOL_SEARCH&keywords=" + symbol.encodeUrl() + "&apikey="
|
||||||
+ apiKey.encodeUrl()
|
+ apiKey.encodeUrl()
|
||||||
).reader().body
|
).reader().body
|
||||||
var json = getJsonResponse(response, debugMessage)
|
var json = getJsonResponse(response, debugMessage)
|
||||||
val symbols = json.getJSONArray("bestMatches")
|
val symbols = json.getJSONArray("bestMatches")
|
||||||
|
@ -156,9 +156,9 @@ class StockQuote : AbstractModule() {
|
||||||
|
|
||||||
// Get quote for symbol
|
// Get quote for symbol
|
||||||
response = URL(
|
response = URL(
|
||||||
"${API_URL}GLOBAL_QUOTE&symbol="
|
"${API_URL}GLOBAL_QUOTE&symbol="
|
||||||
+ symbolInfo.getString("1. symbol").encodeUrl() + "&apikey="
|
+ symbolInfo.getString("1. symbol").encodeUrl() + "&apikey="
|
||||||
+ apiKey.encodeUrl()
|
+ apiKey.encodeUrl()
|
||||||
).reader().body
|
).reader().body
|
||||||
json = getJsonResponse(response, debugMessage)
|
json = getJsonResponse(response, debugMessage)
|
||||||
val quote = json.getJSONObject("Global Quote")
|
val quote = json.getJSONObject("Global Quote")
|
||||||
|
@ -167,50 +167,50 @@ class StockQuote : AbstractModule() {
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
add(
|
add(
|
||||||
PublicMessage(
|
PublicMessage(
|
||||||
"Symbol: " + quote.getString("01. symbol").unescapeXml()
|
"Symbol: " + quote.getString("01. symbol").unescapeXml()
|
||||||
+ " [" + symbolInfo.getString("2. name").unescapeXml() + ']'
|
+ " [" + symbolInfo.getString("2. name").unescapeXml() + ']'
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
val pad = 10
|
val pad = 10
|
||||||
|
|
||||||
add(
|
add(
|
||||||
PublicMessage(
|
PublicMessage(
|
||||||
"Price:".padEnd(pad).prependIndent()
|
"Price:".padEnd(pad).prependIndent()
|
||||||
+ quote.getString("05. price").unescapeXml()
|
+ quote.getString("05. price").unescapeXml()
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
add(
|
add(
|
||||||
PublicMessage(
|
PublicMessage(
|
||||||
"Previous:".padEnd(pad).prependIndent()
|
"Previous:".padEnd(pad).prependIndent()
|
||||||
+ quote.getString("08. previous close").unescapeXml()
|
+ quote.getString("08. previous close").unescapeXml()
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
val data = arrayOf(
|
val data = arrayOf(
|
||||||
"Open" to "02. open",
|
"Open" to "02. open",
|
||||||
"High" to "03. high",
|
"High" to "03. high",
|
||||||
"Low" to "04. low",
|
"Low" to "04. low",
|
||||||
"Volume" to "06. volume",
|
"Volume" to "06. volume",
|
||||||
"Latest" to "07. latest trading day"
|
"Latest" to "07. latest trading day"
|
||||||
)
|
)
|
||||||
|
|
||||||
data.forEach {
|
data.forEach {
|
||||||
add(
|
add(
|
||||||
NoticeMessage(
|
NoticeMessage(
|
||||||
"${it.first}:".padEnd(pad).prependIndent()
|
"${it.first}:".padEnd(pad).prependIndent()
|
||||||
+ quote.getString(it.second).unescapeXml()
|
+ quote.getString(it.second).unescapeXml()
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
add(
|
add(
|
||||||
NoticeMessage(
|
NoticeMessage(
|
||||||
"Change:".padEnd(pad).prependIndent()
|
"Change:".padEnd(pad).prependIndent()
|
||||||
+ quote.getString("09. change").unescapeXml()
|
+ quote.getString("09. change").unescapeXml()
|
||||||
+ " [" + quote.getString("10. change percent").unescapeXml() + ']'
|
+ " [" + quote.getString("10. change percent").unescapeXml() + ']'
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -104,7 +104,7 @@ class Weather2 : AbstractModule() {
|
||||||
* Returns a country based on its country code. Defaults to [Country.UNITED_STATES] if not found.
|
* Returns a country based on its country code. Defaults to [Country.UNITED_STATES] if not found.
|
||||||
*/
|
*/
|
||||||
fun getCountry(countryCode: String): Country {
|
fun getCountry(countryCode: String): Country {
|
||||||
for (c in Country.values()) {
|
for (c in Country.entries) {
|
||||||
if (c.value.equals(countryCode, ignoreCase = true)) {
|
if (c.value.equals(countryCode, ignoreCase = true)) {
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
@ -120,8 +120,8 @@ class Weather2 : AbstractModule() {
|
||||||
fun getWeather(query: String, apiKey: String?): List<Message> {
|
fun getWeather(query: String, apiKey: String?): List<Message> {
|
||||||
if (apiKey.isNullOrBlank()) {
|
if (apiKey.isNullOrBlank()) {
|
||||||
throw ModuleException(
|
throw ModuleException(
|
||||||
"${Weather2::class.java.name} is disabled.",
|
"${Weather2::class.java.name} is disabled.",
|
||||||
"${WEATHER_CMD.capitalise()} is disabled. The API key is missing."
|
"${WEATHER_CMD.capitalise()} is disabled. The API key is missing."
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
val owm = OWM(apiKey)
|
val owm = OWM(apiKey)
|
||||||
|
@ -145,10 +145,10 @@ class Weather2 : AbstractModule() {
|
||||||
}
|
}
|
||||||
if (cwd.hasCityName()) {
|
if (cwd.hasCityName()) {
|
||||||
messages.add(
|
messages.add(
|
||||||
PublicMessage(
|
PublicMessage(
|
||||||
"City: ${cwd.cityName}, " +
|
"City: ${cwd.cityName}, " +
|
||||||
country.name.replace('_', ' ').capitalizeWords() + " [${country.value}]"
|
country.name.replace('_', ' ').capitalizeWords() + " [${country.value}]"
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
cwd.mainData?.let {
|
cwd.mainData?.let {
|
||||||
with(it) {
|
with(it) {
|
||||||
|
@ -181,8 +181,8 @@ class Weather2 : AbstractModule() {
|
||||||
for (w in it) {
|
for (w in it) {
|
||||||
w?.let {
|
w?.let {
|
||||||
condition.append(' ')
|
condition.append(' ')
|
||||||
.append(w.getDescription().capitalise())
|
.append(w.getDescription().capitalise())
|
||||||
.append('.')
|
.append('.')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
messages.add(NoticeMessage(condition.toString()))
|
messages.add(NoticeMessage(condition.toString()))
|
||||||
|
@ -192,15 +192,15 @@ class Weather2 : AbstractModule() {
|
||||||
cwd.cityId?.let {
|
cwd.cityId?.let {
|
||||||
if (it > 0) {
|
if (it > 0) {
|
||||||
messages.add(
|
messages.add(
|
||||||
NoticeMessage("https://openweathermap.org/city/$it", Colors.GREEN)
|
NoticeMessage("https://openweathermap.org/city/$it", Colors.GREEN)
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
messages.add(
|
messages.add(
|
||||||
NoticeMessage(
|
NoticeMessage(
|
||||||
"https://openweathermap.org/find?q="
|
"https://openweathermap.org/find?q="
|
||||||
+ "$city,${code.uppercase()}".encodeUrl(),
|
+ "$city,${code.uppercase()}".encodeUrl(),
|
||||||
Colors.GREEN
|
Colors.GREEN
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -209,9 +209,9 @@ class Weather2 : AbstractModule() {
|
||||||
} catch (e: APIException) {
|
} catch (e: APIException) {
|
||||||
if (e.code == 404) {
|
if (e.code == 404) {
|
||||||
throw ModuleException(
|
throw ModuleException(
|
||||||
"getWeather($query): API ${e.code}",
|
"getWeather($query): API ${e.code}",
|
||||||
"The requested city was not found.",
|
"The requested city was not found.",
|
||||||
e
|
e
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
throw ModuleException("getWeather($query): API ${e.code}", e.message, e)
|
throw ModuleException("getWeather($query): API ${e.code}", e.message, e)
|
||||||
|
|
|
@ -60,15 +60,15 @@ class WolframAlpha : AbstractModule() {
|
||||||
try {
|
try {
|
||||||
val query = args.trim().split("units=", limit = 2, ignoreCase = true)
|
val query = args.trim().split("units=", limit = 2, ignoreCase = true)
|
||||||
event.sendMessage(
|
event.sendMessage(
|
||||||
queryWolfram(
|
queryWolfram(
|
||||||
query[0].trim(),
|
query[0].trim(),
|
||||||
units = if (query.size == 2) {
|
units = if (query.size == 2) {
|
||||||
getUnits(query[1].trim())
|
getUnits(query[1].trim())
|
||||||
} else {
|
} else {
|
||||||
getUnits(properties[UNITS_PROP])
|
getUnits(properties[UNITS_PROP])
|
||||||
},
|
},
|
||||||
appId = properties[APPID_KEY_PROP]
|
appId = properties[APPID_KEY_PROP]
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
} catch (e: ModuleException) {
|
} catch (e: ModuleException) {
|
||||||
if (logger.isWarnEnabled) logger.warn(e.debugMessage, e)
|
if (logger.isWarnEnabled) logger.warn(e.debugMessage, e)
|
||||||
|
@ -111,15 +111,15 @@ class WolframAlpha : AbstractModule() {
|
||||||
return urlReader.body
|
return urlReader.body
|
||||||
} else {
|
} else {
|
||||||
throw ModuleException(
|
throw ModuleException(
|
||||||
"wolfram($query): ${urlReader.responseCode} : ${urlReader.body} ",
|
"wolfram($query): ${urlReader.responseCode} : ${urlReader.body} ",
|
||||||
urlReader.body.ifEmpty {
|
urlReader.body.ifEmpty {
|
||||||
"Looks like Wolfram Alpha isn't able to answer that. (${urlReader.responseCode})"
|
"Looks like Wolfram Alpha isn't able to answer that. (${urlReader.responseCode})"
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
} catch (ioe: IOException) {
|
} catch (ioe: IOException) {
|
||||||
throw ModuleException(
|
throw ModuleException(
|
||||||
"wolfram($query): IOE", "An IO Error occurred while querying Wolfram Alpha.", ioe
|
"wolfram($query): IOE", "An IO Error occurred while querying Wolfram Alpha.", ioe
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -322,7 +322,7 @@ class WorldTime : AbstractModule() {
|
||||||
put("ZULU", "Zulu")
|
put("ZULU", "Zulu")
|
||||||
put("ZW", "Africa/Harare")
|
put("ZW", "Africa/Harare")
|
||||||
ZoneId.getAvailableZoneIds().filter { it.length <= 3 && !containsKey(it) }
|
ZoneId.getAvailableZoneIds().filter { it.length <= 3 && !containsKey(it) }
|
||||||
.forEach { tz -> put(tz, tz) }
|
.forEach { tz -> put(tz, tz) }
|
||||||
}
|
}
|
||||||
|
|
||||||
// The Time command
|
// The Time command
|
||||||
|
@ -336,7 +336,7 @@ class WorldTime : AbstractModule() {
|
||||||
|
|
||||||
// Date/Time Format
|
// Date/Time Format
|
||||||
private var dtf =
|
private var dtf =
|
||||||
DateTimeFormatter.ofPattern("'The time is ${"'HH:mm'".bold()} on ${"'EEEE, d MMMM yyyy'".bold()} in '")
|
DateTimeFormatter.ofPattern("'The time is ${"'HH:mm'".bold()} on ${"'EEEE, d MMMM yyyy'".bold()} in '")
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the current Internet (beat) Time.
|
* Returns the current Internet (beat) Time.
|
||||||
|
|
|
@ -34,4 +34,4 @@ package net.thauvin.erik.mobibot.msg
|
||||||
* The `ErrorMessage` class.
|
* The `ErrorMessage` class.
|
||||||
*/
|
*/
|
||||||
class ErrorMessage @JvmOverloads constructor(msg: String, color: String = DEFAULT_COLOR) :
|
class ErrorMessage @JvmOverloads constructor(msg: String, color: String = DEFAULT_COLOR) :
|
||||||
Message(msg, color, isError = true)
|
Message(msg, color, isError = true)
|
||||||
|
|
|
@ -36,11 +36,11 @@ import net.thauvin.erik.semver.Constants
|
||||||
* The `Message` class.
|
* The `Message` class.
|
||||||
*/
|
*/
|
||||||
open class Message @JvmOverloads constructor(
|
open class Message @JvmOverloads constructor(
|
||||||
var msg: String,
|
var msg: String,
|
||||||
var color: String = DEFAULT_COLOR,
|
var color: String = DEFAULT_COLOR,
|
||||||
var isNotice: Boolean = false,
|
var isNotice: Boolean = false,
|
||||||
isError: Boolean = false,
|
isError: Boolean = false,
|
||||||
var isPrivate: Boolean = false
|
var isPrivate: Boolean = false
|
||||||
) {
|
) {
|
||||||
companion object {
|
companion object {
|
||||||
var DEFAULT_COLOR = Constants.EMPTY
|
var DEFAULT_COLOR = Constants.EMPTY
|
||||||
|
|
|
@ -34,5 +34,5 @@ package net.thauvin.erik.mobibot.msg
|
||||||
* The `NoticeMessage` class.
|
* The `NoticeMessage` class.
|
||||||
*/
|
*/
|
||||||
class NoticeMessage @JvmOverloads constructor(msg: String, color: String = DEFAULT_COLOR) :
|
class NoticeMessage @JvmOverloads constructor(msg: String, color: String = DEFAULT_COLOR) :
|
||||||
Message(msg, color, isNotice = true)
|
Message(msg, color, isNotice = true)
|
||||||
|
|
||||||
|
|
|
@ -33,6 +33,5 @@ package net.thauvin.erik.mobibot.msg
|
||||||
/**
|
/**
|
||||||
* The `PrivateMessage` class.
|
* The `PrivateMessage` class.
|
||||||
*/
|
*/
|
||||||
@Suppress("unused")
|
|
||||||
class PrivateMessage @JvmOverloads constructor(msg: String, color: String = DEFAULT_COLOR) :
|
class PrivateMessage @JvmOverloads constructor(msg: String, color: String = DEFAULT_COLOR) :
|
||||||
Message(msg, color, isPrivate = true)
|
Message(msg, color, isPrivate = true)
|
||||||
|
|
|
@ -36,7 +36,7 @@ import net.thauvin.erik.mobibot.Constants
|
||||||
import net.thauvin.erik.mobibot.entries.EntriesUtils.toLinkLabel
|
import net.thauvin.erik.mobibot.entries.EntriesUtils.toLinkLabel
|
||||||
import org.slf4j.Logger
|
import org.slf4j.Logger
|
||||||
import org.slf4j.LoggerFactory
|
import org.slf4j.LoggerFactory
|
||||||
import java.util.Timer
|
import java.util.*
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Social Manager.
|
* Social Manager.
|
||||||
|
|
|
@ -76,8 +76,8 @@ abstract class SocialModule : AbstractModule() {
|
||||||
post(message = formatEntry(LinksManager.entries.links[index]), isDm = false)
|
post(message = formatEntry(LinksManager.entries.links[index]), isDm = false)
|
||||||
} catch (e: ModuleException) {
|
} catch (e: ModuleException) {
|
||||||
if (logger.isWarnEnabled) logger.warn(
|
if (logger.isWarnEnabled) logger.warn(
|
||||||
"Failed to post entry ${index.toLinkLabel()} on $name.",
|
"Failed to post entry ${index.toLinkLabel()} on $name.",
|
||||||
e
|
e
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,7 @@
|
||||||
|
|
||||||
package net.thauvin.erik.mobibot.social
|
package net.thauvin.erik.mobibot.social
|
||||||
|
|
||||||
import java.util.TimerTask
|
import java.util.*
|
||||||
|
|
||||||
class SocialTimer(private var socialManager: SocialManager, private var index: Int) : TimerTask() {
|
class SocialTimer(private var socialManager: SocialManager, private var index: Int) : TimerTask() {
|
||||||
override fun run() {
|
override fun run() {
|
||||||
|
|
|
@ -41,13 +41,9 @@ import net.thauvin.erik.mobibot.commands.Die
|
||||||
import net.thauvin.erik.mobibot.commands.Ignore
|
import net.thauvin.erik.mobibot.commands.Ignore
|
||||||
import net.thauvin.erik.mobibot.commands.links.Comment
|
import net.thauvin.erik.mobibot.commands.links.Comment
|
||||||
import net.thauvin.erik.mobibot.commands.links.View
|
import net.thauvin.erik.mobibot.commands.links.View
|
||||||
import net.thauvin.erik.mobibot.modules.Dice
|
import net.thauvin.erik.mobibot.modules.*
|
||||||
import net.thauvin.erik.mobibot.modules.Joke
|
|
||||||
import net.thauvin.erik.mobibot.modules.Lookup
|
|
||||||
import net.thauvin.erik.mobibot.modules.RockPaperScissors
|
|
||||||
import net.thauvin.erik.mobibot.modules.War
|
|
||||||
import org.testng.annotations.Test
|
import org.testng.annotations.Test
|
||||||
import java.util.Properties
|
import java.util.*
|
||||||
|
|
||||||
class AddonsTest {
|
class AddonsTest {
|
||||||
private val p = Properties().apply {
|
private val p = Properties().apply {
|
||||||
|
@ -80,11 +76,11 @@ class AddonsTest {
|
||||||
assertThat(addons.names.ops, "names.ops").containsExactly("cycle")
|
assertThat(addons.names.ops, "names.ops").containsExactly("cycle")
|
||||||
|
|
||||||
assertThat(addons.names.commands, "names.command").containsExactly(
|
assertThat(addons.names.commands, "names.command").containsExactly(
|
||||||
"joke",
|
"joke",
|
||||||
"rock",
|
"rock",
|
||||||
"paper",
|
"paper",
|
||||||
"scissors",
|
"scissors",
|
||||||
"ignore"
|
"ignore"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,9 +46,9 @@ object ExceptionSanitizer {
|
||||||
with(this) {
|
with(this) {
|
||||||
if (!cause?.message.isNullOrBlank()) {
|
if (!cause?.message.isNullOrBlank()) {
|
||||||
return ModuleException(
|
return ModuleException(
|
||||||
debugMessage,
|
debugMessage,
|
||||||
cause?.javaClass?.name + ": " + cause?.message?.replaceEach(search, obfuscate),
|
cause?.javaClass?.name + ": " + cause?.message?.replaceEach(search, obfuscate),
|
||||||
this
|
this
|
||||||
)
|
)
|
||||||
} else if (!message.isNullOrBlank()) {
|
} else if (!message.isNullOrBlank()) {
|
||||||
return ModuleException(debugMessage, message?.replaceEach(search, obfuscate), this)
|
return ModuleException(debugMessage, message?.replaceEach(search, obfuscate), this)
|
||||||
|
|
|
@ -68,6 +68,6 @@ class FeedReaderTest {
|
||||||
assertFailure { readFeed("https://www.thauvin.net/foo") }.isInstanceOf(IOException::class.java)
|
assertFailure { readFeed("https://www.thauvin.net/foo") }.isInstanceOf(IOException::class.java)
|
||||||
|
|
||||||
assertFailure { readFeed("https://www.examplesfoo.com/") }
|
assertFailure { readFeed("https://www.examplesfoo.com/") }
|
||||||
.isInstanceOf(UnknownHostException::class.java)
|
.isInstanceOf(UnknownHostException::class.java)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,7 +36,7 @@ import java.net.InetAddress
|
||||||
import java.net.UnknownHostException
|
import java.net.UnknownHostException
|
||||||
import java.nio.file.Files
|
import java.nio.file.Files
|
||||||
import java.nio.file.Paths
|
import java.nio.file.Paths
|
||||||
import java.util.Properties
|
import java.util.*
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Access to `local.properties`.
|
* Access to `local.properties`.
|
||||||
|
|
|
@ -68,7 +68,7 @@ class PinboardTest : LocalProperties() {
|
||||||
|
|
||||||
private fun validatePin(apiToken: String, url: String, vararg matches: String): Boolean {
|
private fun validatePin(apiToken: String, url: String, vararg matches: String): Boolean {
|
||||||
val response =
|
val response =
|
||||||
URL("https://api.pinboard.in/v1/posts/get?auth_token=${apiToken}&tag=test&" + url.encodeUrl()).reader().body
|
URL("https://api.pinboard.in/v1/posts/get?auth_token=${apiToken}&tag=test&" + url.encodeUrl()).reader().body
|
||||||
|
|
||||||
matches.forEach {
|
matches.forEach {
|
||||||
if (!response.contains(it)) {
|
if (!response.contains(it)) {
|
||||||
|
|
|
@ -66,15 +66,14 @@ import java.io.File
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import java.net.URL
|
import java.net.URL
|
||||||
import java.time.LocalDateTime
|
import java.time.LocalDateTime
|
||||||
import java.util.Calendar
|
import java.util.*
|
||||||
import java.util.Properties
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The `Utils Test` class.
|
* The `Utils Test` class.
|
||||||
*/
|
*/
|
||||||
class UtilsTest {
|
class UtilsTest {
|
||||||
private val ascii =
|
private val ascii =
|
||||||
" !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"
|
" !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"
|
||||||
private val cal = Calendar.getInstance()
|
private val cal = Calendar.getInstance()
|
||||||
private val localDateTime = LocalDateTime.of(1952, 2, 17, 12, 30, 0)
|
private val localDateTime = LocalDateTime.of(1952, 2, 17, 12, 30, 0)
|
||||||
private val test = "This is a test."
|
private val test = "This is a test."
|
||||||
|
@ -90,7 +89,7 @@ class UtilsTest {
|
||||||
val sep = '/'
|
val sep = '/'
|
||||||
val url = "https://erik.thauvin.net"
|
val url = "https://erik.thauvin.net"
|
||||||
assertThat(dir.appendIfMissing(File.separatorChar), "appendIfMissing(dir)")
|
assertThat(dir.appendIfMissing(File.separatorChar), "appendIfMissing(dir)")
|
||||||
.isEqualTo(dir + File.separatorChar)
|
.isEqualTo(dir + File.separatorChar)
|
||||||
assertThat(url.appendIfMissing(sep), "appendIfMissing(url)").isEqualTo("$url$sep")
|
assertThat(url.appendIfMissing(sep), "appendIfMissing(url)").isEqualTo("$url$sep")
|
||||||
assertThat("$url$sep".appendIfMissing(sep), "appendIfMissing($url$sep)").isEqualTo("$url$sep")
|
assertThat("$url$sep".appendIfMissing(sep), "appendIfMissing($url$sep)").isEqualTo("$url$sep")
|
||||||
}
|
}
|
||||||
|
@ -116,24 +115,24 @@ class UtilsTest {
|
||||||
fun textCapitaliseWords() {
|
fun textCapitaliseWords() {
|
||||||
assertThat(test.capitalizeWords(), "captiatlizeWords(test)").isEqualTo("This Is A Test.")
|
assertThat(test.capitalizeWords(), "captiatlizeWords(test)").isEqualTo("This Is A Test.")
|
||||||
assertThat("Already Capitalized".capitalizeWords(), "already capitalized")
|
assertThat("Already Capitalized".capitalizeWords(), "already capitalized")
|
||||||
.isEqualTo("Already Capitalized")
|
.isEqualTo("Already Capitalized")
|
||||||
assertThat(" a test ".capitalizeWords(), "with spaces").isEqualTo(" A Test ")
|
assertThat(" a test ".capitalizeWords(), "with spaces").isEqualTo(" A Test ")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testColorize() {
|
fun testColorize() {
|
||||||
assertThat(ascii.colorize(Colors.REVERSE), "reverse.colorize()").isEqualTo(
|
assertThat(ascii.colorize(Colors.REVERSE), "reverse.colorize()").isEqualTo(
|
||||||
Colors.REVERSE + ascii + Colors.REVERSE
|
Colors.REVERSE + ascii + Colors.REVERSE
|
||||||
)
|
)
|
||||||
assertThat(ascii.colorize(Colors.RED), "red.colorize()")
|
assertThat(ascii.colorize(Colors.RED), "red.colorize()")
|
||||||
.isEqualTo(Colors.RED + ascii + Colors.NORMAL)
|
.isEqualTo(Colors.RED + ascii + Colors.NORMAL)
|
||||||
assertThat(ascii.colorize(Colors.BOLD), "colorized(bold)")
|
assertThat(ascii.colorize(Colors.BOLD), "colorized(bold)")
|
||||||
.isEqualTo(Colors.BOLD + ascii + Colors.BOLD)
|
.isEqualTo(Colors.BOLD + ascii + Colors.BOLD)
|
||||||
assertThat(null.colorize(Colors.RED), "null.colorize()").isEqualTo("")
|
assertThat(null.colorize(Colors.RED), "null.colorize()").isEqualTo("")
|
||||||
assertThat("".colorize(Colors.RED), "colorize()").isEqualTo("")
|
assertThat("".colorize(Colors.RED), "colorize()").isEqualTo("")
|
||||||
assertThat(ascii.colorize(DEFAULT_COLOR), "ascii.colorize()").isEqualTo(ascii)
|
assertThat(ascii.colorize(DEFAULT_COLOR), "ascii.colorize()").isEqualTo(ascii)
|
||||||
assertThat(" ".colorize(Colors.NORMAL), "blank.colorize()")
|
assertThat(" ".colorize(Colors.NORMAL), "blank.colorize()")
|
||||||
.isEqualTo(Colors.NORMAL + " " + Colors.NORMAL)
|
.isEqualTo(Colors.NORMAL + " " + Colors.NORMAL)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -165,19 +164,19 @@ class UtilsTest {
|
||||||
fun testHelpCmdSyntax() {
|
fun testHelpCmdSyntax() {
|
||||||
val bot = "mobibot"
|
val bot = "mobibot"
|
||||||
assertThat(helpCmdSyntax("%c $test %n $test", bot, false), "helpCmdSyntax(private)")
|
assertThat(helpCmdSyntax("%c $test %n $test", bot, false), "helpCmdSyntax(private)")
|
||||||
.isEqualTo("$bot: $test $bot $test")
|
.isEqualTo("$bot: $test $bot $test")
|
||||||
assertThat(helpCmdSyntax("%c %n $test %c $test %n", bot, true), "helpCmdSyntax(public)")
|
assertThat(helpCmdSyntax("%c %n $test %c $test %n", bot, true), "helpCmdSyntax(public)")
|
||||||
.isEqualTo("/msg $bot $bot $test /msg $bot $test $bot")
|
.isEqualTo("/msg $bot $bot $test /msg $bot $test $bot")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testHelpFormat() {
|
fun testHelpFormat() {
|
||||||
assertThat(helpFormat(test, isBold = true, isIndent = false), "helpFormat(bold)")
|
assertThat(helpFormat(test, isBold = true, isIndent = false), "helpFormat(bold)")
|
||||||
.isEqualTo("${Colors.BOLD}$test${Colors.BOLD}")
|
.isEqualTo("${Colors.BOLD}$test${Colors.BOLD}")
|
||||||
assertThat(helpFormat(test, isBold = false, isIndent = true), "helpFormat(indent)")
|
assertThat(helpFormat(test, isBold = false, isIndent = true), "helpFormat(indent)")
|
||||||
.isEqualTo(test.prependIndent())
|
.isEqualTo(test.prependIndent())
|
||||||
assertThat(helpFormat(test, isBold = true, isIndent = true), "helpFormat(bold,indent)")
|
assertThat(helpFormat(test, isBold = true, isIndent = true), "helpFormat(bold,indent)")
|
||||||
.isEqualTo(test.colorize(Colors.BOLD).prependIndent())
|
.isEqualTo(test.colorize(Colors.BOLD).prependIndent())
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -219,15 +218,15 @@ class UtilsTest {
|
||||||
val search = arrayOf("one", "two", "three")
|
val search = arrayOf("one", "two", "three")
|
||||||
val replace = arrayOf("1", "2", "3")
|
val replace = arrayOf("1", "2", "3")
|
||||||
assertThat(search.joinToString(",").replaceEach(search, replace), "replaceEach(1,2,3")
|
assertThat(search.joinToString(",").replaceEach(search, replace), "replaceEach(1,2,3")
|
||||||
.isEqualTo(replace.joinToString(","))
|
.isEqualTo(replace.joinToString(","))
|
||||||
|
|
||||||
assertThat(test.replaceEach(search, replace), "replaceEach(nothing)").isEqualTo(test)
|
assertThat(test.replaceEach(search, replace), "replaceEach(nothing)").isEqualTo(test)
|
||||||
|
|
||||||
assertThat(test.replaceEach(arrayOf("t", "e"), arrayOf("", "E")), "replaceEach($test)")
|
assertThat(test.replaceEach(arrayOf("t", "e"), arrayOf("", "E")), "replaceEach($test)")
|
||||||
.isEqualTo(test.replace("t", "").replace("e", "E"))
|
.isEqualTo(test.replace("t", "").replace("e", "E"))
|
||||||
|
|
||||||
assertThat(test.replaceEach(search, emptyArray()), "replaceEach(search, empty)")
|
assertThat(test.replaceEach(search, emptyArray()), "replaceEach(search, empty)")
|
||||||
.isEqualTo(test)
|
.isEqualTo(test)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -259,7 +258,7 @@ class UtilsTest {
|
||||||
@Test
|
@Test
|
||||||
fun testUnescapeXml() {
|
fun testUnescapeXml() {
|
||||||
assertThat("<a name="test & ''">".unescapeXml()).isEqualTo(
|
assertThat("<a name="test & ''">".unescapeXml()).isEqualTo(
|
||||||
"<a name=\"test & ''\">"
|
"<a name=\"test & ''\">"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -40,14 +40,14 @@ class InfoTest {
|
||||||
@Test(groups = ["commands"])
|
@Test(groups = ["commands"])
|
||||||
fun testToUptime() {
|
fun testToUptime() {
|
||||||
assertThat(
|
assertThat(
|
||||||
547800300076L.toUptime(),
|
547800300076L.toUptime(),
|
||||||
"upTime(full)"
|
"upTime(full)"
|
||||||
).isEqualTo("17 years 4 months 2 weeks 1 day 6 hours 45 minutes")
|
).isEqualTo("17 years 4 months 2 weeks 1 day 6 hours 45 minutes")
|
||||||
assertThat(24300000L.toUptime(), "upTime(hours minutes)").isEqualTo("6 hours 45 minutes")
|
assertThat(24300000L.toUptime(), "upTime(hours minutes)").isEqualTo("6 hours 45 minutes")
|
||||||
assertThat(110700000L.toUptime(), "upTime(days hours minutes)").isEqualTo("1 day 6 hours 45 minutes")
|
assertThat(110700000L.toUptime(), "upTime(days hours minutes)").isEqualTo("1 day 6 hours 45 minutes")
|
||||||
assertThat(
|
assertThat(
|
||||||
1320300000L.toUptime(),
|
1320300000L.toUptime(),
|
||||||
"upTime(weeks days hours minutes)"
|
"upTime(weeks days hours minutes)"
|
||||||
).isEqualTo("2 weeks 1 day 6 hours 45 minutes")
|
).isEqualTo("2 weeks 1 day 6 hours 45 minutes")
|
||||||
assertThat(2700000L.toUptime(), "upTime(45 minutes)").isEqualTo("45 minutes")
|
assertThat(2700000L.toUptime(), "upTime(45 minutes)").isEqualTo("45 minutes")
|
||||||
assertThat(60000L.toUptime(), "upTime(1 minute)").isEqualTo("1 minute")
|
assertThat(60000L.toUptime(), "upTime(1 minute)").isEqualTo("1 minute")
|
||||||
|
|
|
@ -48,13 +48,13 @@ class RecapTest {
|
||||||
assertThat(Recap.recaps, "Recap.recaps").all {
|
assertThat(Recap.recaps, "Recap.recaps").all {
|
||||||
size().isEqualTo(Recap.MAX_RECAPS)
|
size().isEqualTo(Recap.MAX_RECAPS)
|
||||||
prop(MutableList<String>::first)
|
prop(MutableList<String>::first)
|
||||||
.matches("[1-2]\\d{3}-[01]\\d-[0-3]\\d [0-2]\\d:[0-6]\\d - sender11: test 11".toRegex())
|
.matches("[1-2]\\d{3}-[01]\\d-[0-3]\\d [0-2]\\d:[0-6]\\d - sender11: test 11".toRegex())
|
||||||
prop(MutableList<String>::last)
|
prop(MutableList<String>::last)
|
||||||
.matches("[1-2]\\d{3}-[01]\\d-[0-3]\\d [0-2]\\d:[0-6]\\d - sender20: test 20".toRegex())
|
.matches("[1-2]\\d{3}-[01]\\d-[0-3]\\d [0-2]\\d:[0-6]\\d - sender20: test 20".toRegex())
|
||||||
}
|
}
|
||||||
|
|
||||||
Recap.storeRecap("sender", "test action", true)
|
Recap.storeRecap("sender", "test action", true)
|
||||||
assertThat(Recap.recaps.last())
|
assertThat(Recap.recaps.last())
|
||||||
.matches("[1-2]\\d{3}-[01]\\d-[0-3]\\d [0-2]\\d:[0-6]\\d - sender test action".toRegex())
|
.matches("[1-2]\\d{3}-[01]\\d-[0-3]\\d [0-2]\\d:[0-6]\\d - sender test action".toRegex())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,8 +47,8 @@ class LinksManagerTest {
|
||||||
fun fetchTitle() {
|
fun fetchTitle() {
|
||||||
assertThat(linksManager.fetchTitle("https://erik.thauvin.net/"), "fetchTitle(Erik)").contains("Erik's Weblog")
|
assertThat(linksManager.fetchTitle("https://erik.thauvin.net/"), "fetchTitle(Erik)").contains("Erik's Weblog")
|
||||||
assertThat(
|
assertThat(
|
||||||
linksManager.fetchTitle("https://www.google.com/foo"),
|
linksManager.fetchTitle("https://www.google.com/foo"),
|
||||||
"fetchTitle(Foo)"
|
"fetchTitle(Foo)"
|
||||||
).isEqualTo(Constants.NO_TITLE)
|
).isEqualTo(Constants.NO_TITLE)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -45,14 +45,14 @@ class ViewTest {
|
||||||
|
|
||||||
for (i in 1..10) {
|
for (i in 1..10) {
|
||||||
LinksManager.entries.links.add(
|
LinksManager.entries.links.add(
|
||||||
EntryLink(
|
EntryLink(
|
||||||
"https://www.example.com/$i",
|
"https://www.example.com/$i",
|
||||||
"Example $i",
|
"Example $i",
|
||||||
"nick$i",
|
"nick$i",
|
||||||
"login$i",
|
"login$i",
|
||||||
"#channel",
|
"#channel",
|
||||||
emptyList()
|
emptyList()
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -33,14 +33,7 @@ package net.thauvin.erik.mobibot.commands.seen
|
||||||
|
|
||||||
import assertk.all
|
import assertk.all
|
||||||
import assertk.assertThat
|
import assertk.assertThat
|
||||||
import assertk.assertions.isEmpty
|
import assertk.assertions.*
|
||||||
import assertk.assertions.isEqualTo
|
|
||||||
import assertk.assertions.isGreaterThan
|
|
||||||
import assertk.assertions.isNotEqualTo
|
|
||||||
import assertk.assertions.isNotNull
|
|
||||||
import assertk.assertions.key
|
|
||||||
import assertk.assertions.prop
|
|
||||||
import assertk.assertions.size
|
|
||||||
import org.testng.annotations.AfterClass
|
import org.testng.annotations.AfterClass
|
||||||
import org.testng.annotations.BeforeClass
|
import org.testng.annotations.BeforeClass
|
||||||
import org.testng.annotations.Test
|
import org.testng.annotations.Test
|
||||||
|
|
|
@ -33,13 +33,7 @@ package net.thauvin.erik.mobibot.commands.tell
|
||||||
|
|
||||||
import assertk.all
|
import assertk.all
|
||||||
import assertk.assertThat
|
import assertk.assertThat
|
||||||
import assertk.assertions.index
|
import assertk.assertions.*
|
||||||
import assertk.assertions.isEqualTo
|
|
||||||
import assertk.assertions.isFalse
|
|
||||||
import assertk.assertions.isGreaterThan
|
|
||||||
import assertk.assertions.isTrue
|
|
||||||
import assertk.assertions.prop
|
|
||||||
import assertk.assertions.size
|
|
||||||
import org.testng.annotations.AfterClass
|
import org.testng.annotations.AfterClass
|
||||||
import org.testng.annotations.BeforeClass
|
import org.testng.annotations.BeforeClass
|
||||||
import org.testng.annotations.Test
|
import org.testng.annotations.Test
|
||||||
|
|
|
@ -46,14 +46,14 @@ class EntriesUtilsTest {
|
||||||
private val links = buildList {
|
private val links = buildList {
|
||||||
for (i in 0..5) {
|
for (i in 0..5) {
|
||||||
add(
|
add(
|
||||||
EntryLink(
|
EntryLink(
|
||||||
"https://www.mobitopia.org/$i",
|
"https://www.mobitopia.org/$i",
|
||||||
"Mobitopia$i",
|
"Mobitopia$i",
|
||||||
"Skynx$i",
|
"Skynx$i",
|
||||||
"JimH$i",
|
"JimH$i",
|
||||||
"#mobitopia$i",
|
"#mobitopia$i",
|
||||||
listOf("tag1", "tag2", "tag3", "TAG4", "Tag5")
|
listOf("tag1", "tag2", "tag3", "TAG4", "Tag5")
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -67,7 +67,7 @@ class EntriesUtilsTest {
|
||||||
fun printLinkTest() {
|
fun printLinkTest() {
|
||||||
for (i in links.indices) {
|
for (i in links.indices) {
|
||||||
assertThat(
|
assertThat(
|
||||||
printLink(i - 1, links[i]), "link $i"
|
printLink(i - 1, links[i]), "link $i"
|
||||||
).isEqualTo("L$i: [Skynx$i] \u0002Mobitopia$i\u0002 ( \u000303https://www.mobitopia.org/$i\u000F )")
|
).isEqualTo("L$i: [Skynx$i] \u0002Mobitopia$i\u0002 ( \u000303https://www.mobitopia.org/$i\u000F )")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,7 +79,7 @@ class EntriesUtilsTest {
|
||||||
fun printTagsTest() {
|
fun printTagsTest() {
|
||||||
for (i in links.indices) {
|
for (i in links.indices) {
|
||||||
assertThat(
|
assertThat(
|
||||||
printTags(i - 1, links[i]), "tag $i"
|
printTags(i - 1, links[i]), "tag $i"
|
||||||
).isEqualTo("L${i}T: tag1, tag2, tag3, tag4, tag5")
|
).isEqualTo("L${i}T: tag1, tag2, tag3, tag4, tag5")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,18 +32,12 @@ package net.thauvin.erik.mobibot.entries
|
||||||
|
|
||||||
import assertk.all
|
import assertk.all
|
||||||
import assertk.assertThat
|
import assertk.assertThat
|
||||||
import assertk.assertions.index
|
import assertk.assertions.*
|
||||||
import assertk.assertions.isEmpty
|
|
||||||
import assertk.assertions.isEqualTo
|
|
||||||
import assertk.assertions.isFalse
|
|
||||||
import assertk.assertions.isTrue
|
|
||||||
import assertk.assertions.prop
|
|
||||||
import assertk.assertions.size
|
|
||||||
import com.rometools.rome.feed.synd.SyndCategory
|
import com.rometools.rome.feed.synd.SyndCategory
|
||||||
import com.rometools.rome.feed.synd.SyndCategoryImpl
|
import com.rometools.rome.feed.synd.SyndCategoryImpl
|
||||||
import org.testng.annotations.Test
|
import org.testng.annotations.Test
|
||||||
import java.security.SecureRandom
|
import java.security.SecureRandom
|
||||||
import java.util.Date
|
import java.util.*
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The `EntryUtilsTest` class.
|
* The `EntryUtilsTest` class.
|
||||||
|
@ -54,8 +48,8 @@ import java.util.Date
|
||||||
*/
|
*/
|
||||||
class EntryLinkTest {
|
class EntryLinkTest {
|
||||||
private val entryLink = EntryLink(
|
private val entryLink = EntryLink(
|
||||||
"https://www.mobitopia.org/", "Mobitopia", "Skynx", "JimH", "#mobitopia",
|
"https://www.mobitopia.org/", "Mobitopia", "Skynx", "JimH", "#mobitopia",
|
||||||
listOf("tag1", "tag2", "tag3", "TAG4", "Tag5")
|
listOf("tag1", "tag2", "tag3", "TAG4", "Tag5")
|
||||||
)
|
)
|
||||||
|
|
||||||
@Test(groups = ["entries"])
|
@Test(groups = ["entries"])
|
||||||
|
@ -123,12 +117,12 @@ class EntryLinkTest {
|
||||||
entryLink.setTags("+mobitopia")
|
entryLink.setTags("+mobitopia")
|
||||||
entryLink.setTags("-mobitopia")
|
entryLink.setTags("-mobitopia")
|
||||||
assertThat(
|
assertThat(
|
||||||
entryLink.formatTags(","),
|
entryLink.formatTags(","),
|
||||||
"formatTags(',')"
|
"formatTags(',')"
|
||||||
).isEqualTo("tag1,tag2,tag3,tag4,mobitopia")
|
).isEqualTo("tag1,tag2,tag3,tag4,mobitopia")
|
||||||
entryLink.setTags("-tag4 tag5")
|
entryLink.setTags("-tag4 tag5")
|
||||||
assertThat(
|
assertThat(
|
||||||
entryLink.formatTags(" ", ","), "formatTag(' ',',')"
|
entryLink.formatTags(" ", ","), "formatTag(' ',',')"
|
||||||
).isEqualTo(",tag1 tag2 tag3 mobitopia tag5")
|
).isEqualTo(",tag1 tag2 tag3 mobitopia tag5")
|
||||||
val size = entryLink.tags.size
|
val size = entryLink.tags.size
|
||||||
entryLink.setTags("")
|
entryLink.setTags("")
|
||||||
|
|
|
@ -33,18 +33,12 @@ package net.thauvin.erik.mobibot.entries
|
||||||
|
|
||||||
import assertk.all
|
import assertk.all
|
||||||
import assertk.assertThat
|
import assertk.assertThat
|
||||||
import assertk.assertions.endsWith
|
import assertk.assertions.*
|
||||||
import assertk.assertions.exists
|
|
||||||
import assertk.assertions.index
|
|
||||||
import assertk.assertions.isEqualTo
|
|
||||||
import assertk.assertions.isTrue
|
|
||||||
import assertk.assertions.prop
|
|
||||||
import assertk.assertions.size
|
|
||||||
import net.thauvin.erik.mobibot.Utils.today
|
import net.thauvin.erik.mobibot.Utils.today
|
||||||
import org.testng.annotations.BeforeSuite
|
import org.testng.annotations.BeforeSuite
|
||||||
import org.testng.annotations.Test
|
import org.testng.annotations.Test
|
||||||
import java.nio.file.Paths
|
import java.nio.file.Paths
|
||||||
import java.util.Date
|
import java.util.*
|
||||||
import kotlin.io.path.deleteIfExists
|
import kotlin.io.path.deleteIfExists
|
||||||
import kotlin.io.path.fileSize
|
import kotlin.io.path.fileSize
|
||||||
import kotlin.io.path.name
|
import kotlin.io.path.name
|
||||||
|
|
|
@ -33,7 +33,6 @@ package net.thauvin.erik.mobibot.modules
|
||||||
import assertk.assertFailure
|
import assertk.assertFailure
|
||||||
import assertk.assertThat
|
import assertk.assertThat
|
||||||
import assertk.assertions.isEqualTo
|
import assertk.assertions.isEqualTo
|
||||||
import assertk.assertions.isFailure
|
|
||||||
import assertk.assertions.isInstanceOf
|
import assertk.assertions.isInstanceOf
|
||||||
import net.objecthunter.exp4j.tokenizer.UnknownFunctionOrVariableException
|
import net.objecthunter.exp4j.tokenizer.UnknownFunctionOrVariableException
|
||||||
import net.thauvin.erik.mobibot.Utils.bold
|
import net.thauvin.erik.mobibot.Utils.bold
|
||||||
|
|
|
@ -34,7 +34,6 @@ import assertk.assertFailure
|
||||||
import assertk.assertThat
|
import assertk.assertThat
|
||||||
import assertk.assertions.contains
|
import assertk.assertions.contains
|
||||||
import assertk.assertions.hasNoCause
|
import assertk.assertions.hasNoCause
|
||||||
import assertk.assertions.isFailure
|
|
||||||
import assertk.assertions.isInstanceOf
|
import assertk.assertions.isInstanceOf
|
||||||
import net.thauvin.erik.mobibot.LocalProperties
|
import net.thauvin.erik.mobibot.LocalProperties
|
||||||
import org.testng.annotations.Test
|
import org.testng.annotations.Test
|
||||||
|
@ -43,21 +42,21 @@ class ChatGptTest : LocalProperties() {
|
||||||
@Test(groups = ["modules"])
|
@Test(groups = ["modules"])
|
||||||
fun testApiKey() {
|
fun testApiKey() {
|
||||||
assertFailure { ChatGpt.chat("1 gallon to liter", "", 0) }
|
assertFailure { ChatGpt.chat("1 gallon to liter", "", 0) }
|
||||||
.isInstanceOf(ModuleException::class.java)
|
.isInstanceOf(ModuleException::class.java)
|
||||||
.hasNoCause()
|
.hasNoCause()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(groups = ["modules", "no-ci"])
|
@Test(groups = ["modules", "no-ci"])
|
||||||
fun testChat() {
|
fun testChat() {
|
||||||
val apiKey = getProperty(ChatGpt.API_KEY_PROP)
|
val apiKey = getProperty(ChatGpt.API_KEY_PROP)
|
||||||
assertThat(
|
assertThat(
|
||||||
ChatGpt.chat("how do I make an HTTP request in Javascript?", apiKey, 100)
|
ChatGpt.chat("how do I make an HTTP request in Javascript?", apiKey, 100)
|
||||||
).contains("XMLHttpRequest")
|
).contains("XMLHttpRequest")
|
||||||
assertThat(
|
assertThat(
|
||||||
ChatGpt.chat("how do I encode a URL in java?", apiKey, 60)
|
ChatGpt.chat("how do I encode a URL in java?", apiKey, 60)
|
||||||
).contains("URLEncoder")
|
).contains("URLEncoder")
|
||||||
|
|
||||||
assertFailure { ChatGpt.chat("1 liter to gallon", apiKey, 0) }
|
assertFailure { ChatGpt.chat("1 liter to gallon", apiKey, 0) }
|
||||||
.isInstanceOf(ModuleException::class.java)
|
.isInstanceOf(ModuleException::class.java)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,16 +58,16 @@ class CurrencyConverterTest {
|
||||||
@Test(groups = ["modules"])
|
@Test(groups = ["modules"])
|
||||||
fun testConvertCurrency() {
|
fun testConvertCurrency() {
|
||||||
assertThat(
|
assertThat(
|
||||||
convertCurrency("100 USD to EUR").msg,
|
convertCurrency("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("1 USD to BTC").msg,
|
||||||
"convertCurrency(1 USD to BTC)"
|
"convertCurrency(1 USD to BTC)"
|
||||||
).matches("1 United States Dollar = 0\\.\\d+ Bitcoin".toRegex())
|
).matches("1 United States Dollar = 0\\.\\d+ Bitcoin".toRegex())
|
||||||
assertThat(
|
assertThat(
|
||||||
convertCurrency("100,000.00 GBP to BTC").msg,
|
convertCurrency("100,000.00 GBP to BTC").msg,
|
||||||
"convertCurrency(100,000.00 GBP to BTC)"
|
"convertCurrency(100,000.00 GBP to BTC)"
|
||||||
).matches("100,000.00 British Pound Sterling = \\d{1,2}\\.\\d+ Bitcoin".toRegex())
|
).matches("100,000.00 British Pound Sterling = \\d{1,2}\\.\\d+ Bitcoin".toRegex())
|
||||||
assertThat(convertCurrency("100 USD to USD"), "convertCurrency(100 USD to USD)").all {
|
assertThat(convertCurrency("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?")
|
||||||
|
|
|
@ -42,12 +42,12 @@ class DiceTest {
|
||||||
fun testRoll() {
|
fun testRoll() {
|
||||||
assertThat(Dice.roll(1, 1), "roll(1d1)").isEqualTo("\u00021\u0002")
|
assertThat(Dice.roll(1, 1), "roll(1d1)").isEqualTo("\u00021\u0002")
|
||||||
assertThat(Dice.roll(2, 1), "roll(2d1)")
|
assertThat(Dice.roll(2, 1), "roll(2d1)")
|
||||||
.isEqualTo("\u00021\u0002 + \u00021\u0002 = \u00022\u0002")
|
.isEqualTo("\u00021\u0002 + \u00021\u0002 = \u00022\u0002")
|
||||||
assertThat(Dice.roll(5, 1), "roll(5d1)")
|
assertThat(Dice.roll(5, 1), "roll(5d1)")
|
||||||
.isEqualTo("\u00021\u0002 + \u00021\u0002 + \u00021\u0002 + \u00021\u0002 + \u00021\u0002 = \u00025\u0002")
|
.isEqualTo("\u00021\u0002 + \u00021\u0002 + \u00021\u0002 + \u00021\u0002 + \u00021\u0002 = \u00025\u0002")
|
||||||
assertThat(Dice.roll(2, 6), "roll(2d6)")
|
assertThat(Dice.roll(2, 6), "roll(2d6)")
|
||||||
.matches("\u0002[1-6]\u0002 \\+ \u0002[1-6]\u0002 = \u0002[1-9][0-2]?\u0002".toRegex())
|
.matches("\u0002[1-6]\u0002 \\+ \u0002[1-6]\u0002 = \u0002[1-9][0-2]?\u0002".toRegex())
|
||||||
assertThat(Dice.roll(3, 7), "roll(3d7)")
|
assertThat(Dice.roll(3, 7), "roll(3d7)")
|
||||||
.matches("\u0002[1-7]\u0002 \\+ \u0002[1-7]\u0002 \\+ \u0002[1-7]\u0002 = \u0002\\d{1,2}\u0002".toRegex())
|
.matches("\u0002[1-7]\u0002 \\+ \u0002[1-7]\u0002 \\+ \u0002[1-7]\u0002 = \u0002\\d{1,2}\u0002".toRegex())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,15 +33,7 @@ package net.thauvin.erik.mobibot.modules
|
||||||
import assertk.all
|
import assertk.all
|
||||||
import assertk.assertFailure
|
import assertk.assertFailure
|
||||||
import assertk.assertThat
|
import assertk.assertThat
|
||||||
import assertk.assertions.contains
|
import assertk.assertions.*
|
||||||
import assertk.assertions.hasMessage
|
|
||||||
import assertk.assertions.hasNoCause
|
|
||||||
import assertk.assertions.index
|
|
||||||
import assertk.assertions.isEqualTo
|
|
||||||
import assertk.assertions.isFailure
|
|
||||||
import assertk.assertions.isInstanceOf
|
|
||||||
import assertk.assertions.isNotEmpty
|
|
||||||
import assertk.assertions.prop
|
|
||||||
import net.thauvin.erik.mobibot.ExceptionSanitizer.sanitize
|
import net.thauvin.erik.mobibot.ExceptionSanitizer.sanitize
|
||||||
import net.thauvin.erik.mobibot.LocalProperties
|
import net.thauvin.erik.mobibot.LocalProperties
|
||||||
import net.thauvin.erik.mobibot.modules.GoogleSearch.Companion.searchGoogle
|
import net.thauvin.erik.mobibot.modules.GoogleSearch.Companion.searchGoogle
|
||||||
|
@ -56,19 +48,19 @@ class GoogleSearchTest : LocalProperties() {
|
||||||
@Test(groups = ["modules"])
|
@Test(groups = ["modules"])
|
||||||
fun testAPIKeys() {
|
fun testAPIKeys() {
|
||||||
assertThat(
|
assertThat(
|
||||||
searchGoogle("", "apikey", "cssKey").first(),
|
searchGoogle("", "apikey", "cssKey").first(),
|
||||||
"searchGoogle(empty)"
|
"searchGoogle(empty)"
|
||||||
).isInstanceOf(ErrorMessage::class.java)
|
).isInstanceOf(ErrorMessage::class.java)
|
||||||
|
|
||||||
assertFailure { searchGoogle("test", "", "apiKey") }
|
assertFailure { searchGoogle("test", "", "apiKey") }
|
||||||
.isInstanceOf(ModuleException::class.java).hasNoCause()
|
.isInstanceOf(ModuleException::class.java).hasNoCause()
|
||||||
|
|
||||||
assertFailure { searchGoogle("test", "apiKey", "") }
|
assertFailure { searchGoogle("test", "apiKey", "") }
|
||||||
.isInstanceOf(ModuleException::class.java).hasNoCause()
|
.isInstanceOf(ModuleException::class.java).hasNoCause()
|
||||||
|
|
||||||
assertFailure { searchGoogle("test", "apiKey", "cssKey") }
|
assertFailure { searchGoogle("test", "apiKey", "cssKey") }
|
||||||
.isInstanceOf(ModuleException::class.java)
|
.isInstanceOf(ModuleException::class.java)
|
||||||
.hasMessage("API key not valid. Please pass a valid API key.")
|
.hasMessage("API key not valid. Please pass a valid API key.")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(groups = ["no-ci", "modules"])
|
@Test(groups = ["no-ci", "modules"])
|
||||||
|
|
|
@ -32,12 +32,7 @@ package net.thauvin.erik.mobibot.modules
|
||||||
|
|
||||||
import assertk.all
|
import assertk.all
|
||||||
import assertk.assertThat
|
import assertk.assertThat
|
||||||
import assertk.assertions.doesNotContain
|
import assertk.assertions.*
|
||||||
import assertk.assertions.each
|
|
||||||
import assertk.assertions.isGreaterThan
|
|
||||||
import assertk.assertions.isInstanceOf
|
|
||||||
import assertk.assertions.prop
|
|
||||||
import assertk.assertions.size
|
|
||||||
import net.thauvin.erik.mobibot.modules.Joke.Companion.randomJoke
|
import net.thauvin.erik.mobibot.modules.Joke.Companion.randomJoke
|
||||||
import net.thauvin.erik.mobibot.msg.Message
|
import net.thauvin.erik.mobibot.msg.Message
|
||||||
import net.thauvin.erik.mobibot.msg.PublicMessage
|
import net.thauvin.erik.mobibot.msg.PublicMessage
|
||||||
|
|
|
@ -42,13 +42,13 @@ class MastodonTest : LocalProperties() {
|
||||||
fun testToot() {
|
fun testToot() {
|
||||||
val msg = "Testing Mastodon API from ${getHostName()}"
|
val msg = "Testing Mastodon API from ${getHostName()}"
|
||||||
assertThat(
|
assertThat(
|
||||||
toot(
|
toot(
|
||||||
getProperty(Mastodon.ACCESS_TOKEN_PROP),
|
getProperty(Mastodon.ACCESS_TOKEN_PROP),
|
||||||
getProperty(Mastodon.INSTANCE_PROP),
|
getProperty(Mastodon.INSTANCE_PROP),
|
||||||
getProperty(Mastodon.HANDLE_PROP),
|
getProperty(Mastodon.HANDLE_PROP),
|
||||||
msg,
|
msg,
|
||||||
true
|
true
|
||||||
)
|
)
|
||||||
).contains(msg)
|
).contains(msg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,13 +32,7 @@ package net.thauvin.erik.mobibot.modules
|
||||||
|
|
||||||
import assertk.all
|
import assertk.all
|
||||||
import assertk.assertThat
|
import assertk.assertThat
|
||||||
import assertk.assertions.contains
|
import assertk.assertions.*
|
||||||
import assertk.assertions.doesNotContain
|
|
||||||
import assertk.assertions.endsWith
|
|
||||||
import assertk.assertions.hasMessage
|
|
||||||
import assertk.assertions.isEqualTo
|
|
||||||
import assertk.assertions.isNotNull
|
|
||||||
import assertk.assertions.isNull
|
|
||||||
import net.thauvin.erik.mobibot.ExceptionSanitizer.sanitize
|
import net.thauvin.erik.mobibot.ExceptionSanitizer.sanitize
|
||||||
import org.testng.annotations.DataProvider
|
import org.testng.annotations.DataProvider
|
||||||
import org.testng.annotations.Test
|
import org.testng.annotations.Test
|
||||||
|
@ -57,9 +51,9 @@ class ModuleExceptionTest {
|
||||||
@DataProvider(name = "dp")
|
@DataProvider(name = "dp")
|
||||||
fun createData(@Suppress("UNUSED_PARAMETER") m: Method?): Array<Array<Any>> {
|
fun createData(@Suppress("UNUSED_PARAMETER") m: Method?): Array<Array<Any>> {
|
||||||
return arrayOf(
|
return arrayOf(
|
||||||
arrayOf(ModuleException(debugMessage, message, IOException("URL http://foobar.com"))),
|
arrayOf(ModuleException(debugMessage, message, IOException("URL http://foobar.com"))),
|
||||||
arrayOf(ModuleException(debugMessage, message, IOException("URL http://foobar.com?"))),
|
arrayOf(ModuleException(debugMessage, message, IOException("URL http://foobar.com?"))),
|
||||||
arrayOf(ModuleException(debugMessage, message))
|
arrayOf(ModuleException(debugMessage, message))
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,7 +72,7 @@ class ModuleExceptionTest {
|
||||||
val apiKey = "1234567890"
|
val apiKey = "1234567890"
|
||||||
var e = ModuleException(debugMessage, message, IOException("URL http://foo.com?apiKey=$apiKey&userID=me"))
|
var e = ModuleException(debugMessage, message, IOException("URL http://foo.com?apiKey=$apiKey&userID=me"))
|
||||||
assertThat(
|
assertThat(
|
||||||
e.sanitize(apiKey, "", "me").message, "ModuleException(debugMessage, message, IOException(url))"
|
e.sanitize(apiKey, "", "me").message, "ModuleException(debugMessage, message, IOException(url))"
|
||||||
).isNotNull().all {
|
).isNotNull().all {
|
||||||
contains("xxxxxxxxxx", "userID=xx", "java.io.IOException")
|
contains("xxxxxxxxxx", "userID=xx", "java.io.IOException")
|
||||||
doesNotContain(apiKey, "me")
|
doesNotContain(apiKey, "me")
|
||||||
|
@ -92,7 +86,7 @@ class ModuleExceptionTest {
|
||||||
|
|
||||||
e = ModuleException(debugMessage, apiKey)
|
e = ModuleException(debugMessage, apiKey)
|
||||||
assertThat(e.sanitize(apiKey).message, "ModuleException(debugMessage, apiKey)").isNotNull()
|
assertThat(e.sanitize(apiKey).message, "ModuleException(debugMessage, apiKey)").isNotNull()
|
||||||
.doesNotContain(apiKey)
|
.doesNotContain(apiKey)
|
||||||
|
|
||||||
val msg: String? = null
|
val msg: String? = null
|
||||||
e = ModuleException(debugMessage, msg, IOException(msg))
|
e = ModuleException(debugMessage, msg, IOException(msg))
|
||||||
|
@ -100,8 +94,8 @@ class ModuleExceptionTest {
|
||||||
|
|
||||||
e = ModuleException(debugMessage, msg, IOException("foo is $apiKey"))
|
e = ModuleException(debugMessage, msg, IOException("foo is $apiKey"))
|
||||||
assertThat(
|
assertThat(
|
||||||
e.sanitize(" ", apiKey, "foo").message,
|
e.sanitize(" ", apiKey, "foo").message,
|
||||||
"ModuleException(debugMessage, msg, IOException(foo is $apiKey))"
|
"ModuleException(debugMessage, msg, IOException(foo is $apiKey))"
|
||||||
).isNotNull().all {
|
).isNotNull().all {
|
||||||
doesNotContain(apiKey)
|
doesNotContain(apiKey)
|
||||||
endsWith("xxx is xxxxxxxxxx")
|
endsWith("xxx is xxxxxxxxxx")
|
||||||
|
|
|
@ -33,14 +33,7 @@ package net.thauvin.erik.mobibot.modules
|
||||||
import assertk.all
|
import assertk.all
|
||||||
import assertk.assertFailure
|
import assertk.assertFailure
|
||||||
import assertk.assertThat
|
import assertk.assertThat
|
||||||
import assertk.assertions.hasNoCause
|
import assertk.assertions.*
|
||||||
import assertk.assertions.index
|
|
||||||
import assertk.assertions.isEqualTo
|
|
||||||
import assertk.assertions.isFailure
|
|
||||||
import assertk.assertions.isInstanceOf
|
|
||||||
import assertk.assertions.isNotEmpty
|
|
||||||
import assertk.assertions.matches
|
|
||||||
import assertk.assertions.prop
|
|
||||||
import net.thauvin.erik.mobibot.ExceptionSanitizer.sanitize
|
import net.thauvin.erik.mobibot.ExceptionSanitizer.sanitize
|
||||||
import net.thauvin.erik.mobibot.LocalProperties
|
import net.thauvin.erik.mobibot.LocalProperties
|
||||||
import net.thauvin.erik.mobibot.modules.StockQuote.Companion.getQuote
|
import net.thauvin.erik.mobibot.modules.StockQuote.Companion.getQuote
|
||||||
|
@ -67,7 +60,7 @@ class StockQuoteTest : LocalProperties() {
|
||||||
assertThat(messages, "getQuote($symbol)").index(0).prop(Message::msg).matches("Symbol: AAPL .*".toRegex())
|
assertThat(messages, "getQuote($symbol)").index(0).prop(Message::msg).matches("Symbol: AAPL .*".toRegex())
|
||||||
assertThat(messages, "getQuote($symbol)").index(1).prop(Message::msg).matches(buildMatch("Price").toRegex())
|
assertThat(messages, "getQuote($symbol)").index(1).prop(Message::msg).matches(buildMatch("Price").toRegex())
|
||||||
assertThat(messages, "getQuote($symbol)").index(2).prop(Message::msg)
|
assertThat(messages, "getQuote($symbol)").index(2).prop(Message::msg)
|
||||||
.matches(buildMatch("Previous").toRegex())
|
.matches(buildMatch("Previous").toRegex())
|
||||||
assertThat(messages, "getQuote($symbol)").index(3).prop(Message::msg).matches(buildMatch("Open").toRegex())
|
assertThat(messages, "getQuote($symbol)").index(3).prop(Message::msg).matches(buildMatch("Open").toRegex())
|
||||||
|
|
||||||
symbol = "blahfoo"
|
symbol = "blahfoo"
|
||||||
|
|
|
@ -33,16 +33,7 @@ package net.thauvin.erik.mobibot.modules
|
||||||
import assertk.all
|
import assertk.all
|
||||||
import assertk.assertFailure
|
import assertk.assertFailure
|
||||||
import assertk.assertThat
|
import assertk.assertThat
|
||||||
import assertk.assertions.contains
|
import assertk.assertions.*
|
||||||
import assertk.assertions.endsWith
|
|
||||||
import assertk.assertions.hasNoCause
|
|
||||||
import assertk.assertions.index
|
|
||||||
import assertk.assertions.isEqualTo
|
|
||||||
import assertk.assertions.isFailure
|
|
||||||
import assertk.assertions.isInstanceOf
|
|
||||||
import assertk.assertions.isNotNull
|
|
||||||
import assertk.assertions.isTrue
|
|
||||||
import assertk.assertions.prop
|
|
||||||
import net.aksingh.owmjapis.api.APIException
|
import net.aksingh.owmjapis.api.APIException
|
||||||
import net.aksingh.owmjapis.core.OWM
|
import net.aksingh.owmjapis.core.OWM
|
||||||
import net.thauvin.erik.mobibot.LocalProperties
|
import net.thauvin.erik.mobibot.LocalProperties
|
||||||
|
@ -69,7 +60,7 @@ class Weather2Test : LocalProperties() {
|
||||||
assertThat(getCountry("foo"), "foo is not a valid country").isEqualTo(OWM.Country.UNITED_STATES)
|
assertThat(getCountry("foo"), "foo is not a valid country").isEqualTo(OWM.Country.UNITED_STATES)
|
||||||
assertThat(getCountry("fr"), "country should France").isEqualTo(OWM.Country.FRANCE)
|
assertThat(getCountry("fr"), "country should France").isEqualTo(OWM.Country.FRANCE)
|
||||||
|
|
||||||
val country = OWM.Country.values()
|
val country = OWM.Country.entries.toTypedArray()
|
||||||
repeat(3) {
|
repeat(3) {
|
||||||
val rand = country[(country.indices).random()]
|
val rand = country[(country.indices).random()]
|
||||||
assertThat(getCountry(rand.value), rand.name).isEqualTo(rand)
|
assertThat(getCountry(rand.value), rand.name).isEqualTo(rand)
|
||||||
|
|
|
@ -45,11 +45,11 @@ class WolframAlphaTest : LocalProperties() {
|
||||||
@Test(groups = ["modules"])
|
@Test(groups = ["modules"])
|
||||||
fun testAppId() {
|
fun testAppId() {
|
||||||
assertFailure { queryWolfram("1 gallon to liter", appId = "DEMO") }
|
assertFailure { queryWolfram("1 gallon to liter", appId = "DEMO") }
|
||||||
.isInstanceOf(ModuleException::class.java)
|
.isInstanceOf(ModuleException::class.java)
|
||||||
.hasMessage("Error 1: Invalid appid")
|
.hasMessage("Error 1: Invalid appid")
|
||||||
|
|
||||||
assertFailure { queryWolfram("1 gallon to liter", appId = "") }
|
assertFailure { queryWolfram("1 gallon to liter", appId = "") }
|
||||||
.isInstanceOf(ModuleException::class.java)
|
.isInstanceOf(ModuleException::class.java)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(groups = ["modules", "no-ci"])
|
@Test(groups = ["modules", "no-ci"])
|
||||||
|
@ -62,8 +62,8 @@ class WolframAlphaTest : LocalProperties() {
|
||||||
|
|
||||||
query = "SFO to LAX"
|
query = "SFO to LAX"
|
||||||
assertThat(
|
assertThat(
|
||||||
queryWolfram(query, WolframAlpha.METRIC, apiKey),
|
queryWolfram(query, WolframAlpha.METRIC, apiKey),
|
||||||
"queryWolfram($query)"
|
"queryWolfram($query)"
|
||||||
).contains("kilometers")
|
).contains("kilometers")
|
||||||
} catch (e: ModuleException) {
|
} catch (e: ModuleException) {
|
||||||
// Avoid displaying api key in CI logs
|
// Avoid displaying api key in CI logs
|
||||||
|
|
|
@ -30,10 +30,8 @@
|
||||||
*/
|
*/
|
||||||
package net.thauvin.erik.mobibot.modules
|
package net.thauvin.erik.mobibot.modules
|
||||||
|
|
||||||
import assertk.assertFailure
|
|
||||||
import assertk.assertThat
|
import assertk.assertThat
|
||||||
import assertk.assertions.endsWith
|
import assertk.assertions.endsWith
|
||||||
import assertk.assertions.isSuccess
|
|
||||||
import assertk.assertions.matches
|
import assertk.assertions.matches
|
||||||
import assertk.assertions.startsWith
|
import assertk.assertions.startsWith
|
||||||
import net.thauvin.erik.mobibot.Utils.bold
|
import net.thauvin.erik.mobibot.Utils.bold
|
||||||
|
@ -51,9 +49,9 @@ class WordTimeTest {
|
||||||
@Test(groups = ["modules"])
|
@Test(groups = ["modules"])
|
||||||
fun testTime() {
|
fun testTime() {
|
||||||
assertThat(time(), "time()").matches(
|
assertThat(time(), "time()").matches(
|
||||||
("The time is ${Colors.BOLD}\\d{1,2}:\\d{2}${Colors.BOLD} " +
|
("The time is ${Colors.BOLD}\\d{1,2}:\\d{2}${Colors.BOLD} " +
|
||||||
"on ${Colors.BOLD}\\w+, \\d{1,2} \\w+ \\d{4}${Colors.BOLD} " +
|
"on ${Colors.BOLD}\\w+, \\d{1,2} \\w+ \\d{4}${Colors.BOLD} " +
|
||||||
"in ${Colors.BOLD}Los Angeles${Colors.BOLD}").toRegex()
|
"in ${Colors.BOLD}Los Angeles${Colors.BOLD}").toRegex()
|
||||||
)
|
)
|
||||||
assertThat(time(""), "time()").endsWith("Los Angeles".bold())
|
assertThat(time(""), "time()").endsWith("Los Angeles".bold())
|
||||||
assertThat(time("PST"), "time(PST)").endsWith("Los Angeles".bold())
|
assertThat(time("PST"), "time(PST)").endsWith("Los Angeles".bold())
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
#Generated by the Semver Plugin for Gradle
|
#Generated by the Semver Plugin for Gradle
|
||||||
#Sun Jul 02 02:19:45 PDT 2023
|
#Thu Jul 06 10:21:40 PDT 2023
|
||||||
version.buildmeta=20230702021945
|
version.buildmeta=20230706102140
|
||||||
version.major=0
|
version.major=0
|
||||||
version.minor=8
|
version.minor=8
|
||||||
version.patch=0
|
version.patch=0
|
||||||
version.prerelease=rc
|
version.prerelease=rc
|
||||||
version.project=mobibot
|
version.project=mobibot
|
||||||
version.semver=0.8.0-rc+20230702021945
|
version.semver=0.8.0-rc+20230706102140
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue