Cleaned up code

This commit is contained in:
Erik C. Thauvin 2023-11-01 22:02:54 -07:00
parent d700aa06df
commit 4c90870f4a
61 changed files with 496 additions and 481 deletions

View file

@ -63,7 +63,7 @@ object Constants {
* 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.

View file

@ -97,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("For more information on a specific command, type:")
event.sendMessage(
helpFormat(
helpCmdSyntax("%c ${Constants.HELP_CMD} <command>", event.bot().nick, event is PrivateMessageEvent)
)
helpFormat(
helpCmdSyntax("%c ${Constants.HELP_CMD} <command>", event.bot().nick, event is PrivateMessageEvent)
)
)
event.sendMessage("The commands are:")
event.sendList(addons.names.commands, 8, isBold = true, isIndent = true)
@ -161,7 +161,7 @@ class Mobibot(nickname: String, val channel: String, logsDirPath: String, p: Pro
with(event.getBot<PircBotX>()) {
if (user.nick == nick) {
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)
} else {
@ -209,7 +209,7 @@ class Mobibot(nickname: String, val channel: String, logsDirPath: String, p: Pro
with(event.getBot<PircBotX>()) {
if (user.nick == nick) {
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)
} else {
@ -232,22 +232,22 @@ class Mobibot(nickname: String, val channel: String, logsDirPath: String, p: Pro
// Set up the command line options
val parser = ArgParser(Constants.CLI_CMD)
val debug by parser.option(
ArgType.Boolean,
Constants.DEBUG_ARG,
Constants.DEBUG_ARG.substring(0, 1),
"Print debug & logging data directly to the console"
ArgType.Boolean,
Constants.DEBUG_ARG,
Constants.DEBUG_ARG.substring(0, 1),
"Print debug & logging data directly to the console"
).default(false)
val property by parser.option(
ArgType.String,
Constants.PROPS_ARG,
Constants.PROPS_ARG.substring(0, 1),
"Use alternate properties file"
ArgType.String,
Constants.PROPS_ARG,
Constants.PROPS_ARG.substring(0, 1),
"Use alternate properties file"
).default("./${ReleaseInfo.PROJECT}.properties")
val version by parser.option(
ArgType.Boolean,
Constants.VERSION_ARG,
Constants.VERSION_ARG.substring(0, 1),
"Print version info"
ArgType.Boolean,
Constants.VERSION_ARG,
Constants.VERSION_ARG.substring(0, 1),
"Print version info"
).default(false)
// Parse the command line
@ -256,8 +256,8 @@ class Mobibot(nickname: String, val channel: String, logsDirPath: String, p: Pro
if (version) {
// Output the version
println(
"${ReleaseInfo.PROJECT.capitalise()} ${ReleaseInfo.VERSION}" +
" (${ReleaseInfo.BUILDDATE.toIsoLocalDate()})"
"${ReleaseInfo.PROJECT.capitalise()} ${ReleaseInfo.VERSION}" +
" (${ReleaseInfo.BUILDDATE.toIsoLocalDate()})"
)
println(ReleaseInfo.WEBSITE)
} else {
@ -265,7 +265,7 @@ class Mobibot(nickname: String, val channel: String, logsDirPath: String, p: Pro
val p = Properties()
try {
Files.newInputStream(
Paths.get(property)
Paths.get(property)
).use { fis ->
p.load(fis)
}
@ -284,11 +284,11 @@ class Mobibot(nickname: String, val channel: String, logsDirPath: String, p: Pro
if (!debug) {
try {
val stdout = PrintStream(
BufferedOutputStream(
FileOutputStream(
logsDir + channel.substring(1) + '.' + Utils.today() + ".log", true
)
), true
BufferedOutputStream(
FileOutputStream(
logsDir + channel.substring(1) + '.' + Utils.today() + ".log", true
)
), true
)
System.setOut(stdout)
} catch (ignore: IOException) {
@ -297,9 +297,9 @@ class Mobibot(nickname: String, val channel: String, logsDirPath: String, p: Pro
}
try {
val stderr = PrintStream(
BufferedOutputStream(
FileOutputStream("$logsDir$nickname.err", true)
), true
BufferedOutputStream(
FileOutputStream("$logsDir$nickname.err", true)
), true
)
System.setErr(stderr)
} catch (ignore: IOException) {
@ -324,8 +324,8 @@ class Mobibot(nickname: String, val channel: String, logsDirPath: String, p: Pro
login = p.getProperty("login", nickname)
realName = p.getProperty("realname", nickname)
addServer(
ircServer,
p.getIntProperty("port", Constants.DEFAULT_PORT)
ircServer,
p.getIntProperty("port", Constants.DEFAULT_PORT)
)
addAutoJoinChannel(channel)
addListener(this@Mobibot)

View file

@ -92,7 +92,7 @@ class Pinboard {
*/
private fun Date.toTimestamp(): String {
return ZonedDateTime.ofInstant(
toInstant().truncatedTo(ChronoUnit.SECONDS), ZoneId.systemDefault()
toInstant().truncatedTo(ChronoUnit.SECONDS), ZoneId.systemDefault()
).format(DateTimeFormatter.ISO_INSTANT)
}

View file

@ -128,12 +128,15 @@ object Utils {
isNullOrEmpty() -> {
""
}
color == DEFAULT_COLOR -> {
this
}
Colors.BOLD == color || Colors.REVERSE == color -> {
color + this + color
}
else -> {
color + this + Colors.NORMAL
}
@ -220,7 +223,7 @@ object Utils {
if (serialFile.exists() && serialFile.fileSize() > 0) {
try {
ObjectInputStream(
BufferedInputStream(Files.newInputStream(serialFile))
BufferedInputStream(Files.newInputStream(serialFile))
).use { input ->
if (logger.isDebugEnabled) logger.debug("Loading the ${description}.")
return input.readObject()
@ -307,20 +310,20 @@ object Utils {
@JvmStatic
@JvmOverloads
fun GenericMessageEvent.sendList(
list: List<String>,
maxPerLine: Int,
separator: String = " ",
isBold: Boolean = false,
isIndent: Boolean = false
list: List<String>,
maxPerLine: Int,
separator: String = " ",
isBold: Boolean = false,
isIndent: Boolean = false
) {
var i = 0
while (i < list.size) {
sendMessage(
helpFormat(
list.subList(i, list.size.coerceAtMost(i + maxPerLine)).joinToString(separator, truncated = ""),
isBold,
isIndent
),
helpFormat(
list.subList(i, list.size.coerceAtMost(i + maxPerLine)).joinToString(separator, truncated = ""),
isBold,
isIndent
),
)
i += maxPerLine
}
@ -419,8 +422,8 @@ object Utils {
fun URL.reader(): UrlReaderResponse {
val connection = this.openConnection() as HttpURLConnection
connection.setRequestProperty(
"User-Agent",
"Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/109.0"
"User-Agent",
"Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/109.0"
)
return if (connection.responseCode.isHttpSuccess()) {
UrlReaderResponse(connection.responseCode, connection.inputStream.bufferedReader().use { it.readText() })

View file

@ -50,15 +50,15 @@ class Ignore : AbstractCommand() {
override val name = IGNORE_CMD
override val help = listOf(
"To ignore a link posted to the channel:",
helpFormat("https://www.foo.bar %n"),
"To check your ignore status:",
helpFormat("%c $name"),
"To toggle your ignore status:",
helpFormat("%c $name $me")
"To ignore a link posted to the channel:",
helpFormat("https://www.foo.bar %n"),
"To check your ignore status:",
helpFormat("%c $name"),
"To toggle your ignore status:",
helpFormat("%c $name $me")
)
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

View file

@ -48,8 +48,8 @@ import kotlin.time.toDuration
class Info(private val tell: Tell, private val seen: Seen) : AbstractCommand() {
private val allVersions = listOf(
"${ReleaseInfo.PROJECT.capitalise()} ${ReleaseInfo.VERSION} (${ReleaseInfo.WEBSITE.green()})",
"Written by ${ReleaseInfo.AUTHOR} (${ReleaseInfo.AUTHOR_URL.green()})"
"${ReleaseInfo.PROJECT.capitalise()} ${ReleaseInfo.VERSION} (${ReleaseInfo.WEBSITE.green()})",
"Written by ${ReleaseInfo.AUTHOR} (${ReleaseInfo.AUTHOR_URL.green()})"
)
override val name = "info"
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)
val info = StringBuilder()
info.append("Uptime: ")
.append(ManagementFactory.getRuntimeMXBean().uptime.toUptime())
.append(" [Entries: ")
.append(LinksManager.entries.links.size)
.append(ManagementFactory.getRuntimeMXBean().uptime.toUptime())
.append(" [Entries: ")
.append(LinksManager.entries.links.size)
if (seen.isEnabled()) {
info.append(", Seen: ").append(seen.count())
}

View file

@ -39,8 +39,8 @@ import org.pircbotx.hooks.types.GenericMessageEvent
class Msg : AbstractCommand() {
override val name = "msg"
override val help = listOf(
"To have the bot send a private message to someone:",
helpFormat("%c $name <nick> <text>")
"To have the bot send a private message to someone:",
helpFormat("%c $name <nick> <text>")
)
override val isOpOnly = true
override val isPublic = false

View file

@ -41,8 +41,8 @@ import java.time.LocalDateTime
class Recap : AbstractCommand() {
override val name = "recap"
override val help = listOf(
"To list the last 10 public channel messages:",
helpFormat("%c $name")
"To list the last 10 public channel messages:",
helpFormat("%c $name")
)
override val isOpOnly = false
override val isPublic = true
@ -60,8 +60,8 @@ class Recap : AbstractCommand() {
@JvmStatic
fun storeRecap(sender: String, message: String, isAction: Boolean) {
recaps.add(
LocalDateTime.now(Clock.systemUTC()).toUtcDateTime()
+ " - $sender" + (if (isAction) " " else ": ") + message
LocalDateTime.now(Clock.systemUTC()).toUtcDateTime()
+ " - $sender" + (if (isAction) " " else ": ") + message
)
if (recaps.size > MAX_RECAPS) {
recaps.removeFirst()

View file

@ -40,10 +40,10 @@ import org.pircbotx.hooks.types.GenericMessageEvent
class Versions : AbstractCommand() {
private val allVersions = listOf(
"Version: ${ReleaseInfo.VERSION} (${ReleaseInfo.BUILDDATE.toIsoLocalDate()})",
"${System.getProperty("os.name")} ${System.getProperty("os.version")} (${System.getProperty("os.arch")})" +
", JVM ${System.getProperty("java.runtime.version")}",
"Kotlin ${KotlinVersion.CURRENT}, PircBotX ${PircBotX.VERSION}"
"Version: ${ReleaseInfo.VERSION} (${ReleaseInfo.BUILDDATE.toIsoLocalDate()})",
"${System.getProperty("os.name")} ${System.getProperty("os.version")} (${System.getProperty("os.arch")})" +
", JVM ${System.getProperty("java.runtime.version")}",
"Kotlin ${KotlinVersion.CURRENT}, PircBotX ${PircBotX.VERSION}"
)
override val name = "versions"
override val help = listOf("To view the versions data (bot, platform, java, etc.):", helpFormat("%c $name"))

View file

@ -45,13 +45,13 @@ import org.pircbotx.hooks.types.GenericMessageEvent
class Comment : AbstractCommand() {
override val name = COMMAND
override val help = listOf(
"To add 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",
"To edit a comment, use its label: ",
helpFormat("${Constants.LINK_CMD}1.1:This is an edited comment"),
"To delete a comment, use its label and a minus sign: ",
helpFormat("${Constants.LINK_CMD}1.1:-")
"To add 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",
"To edit a comment, use its label: ",
helpFormat("${Constants.LINK_CMD}1.1:This is an edited comment"),
"To delete a comment, use its label and a minus sign: ",
helpFormat("${Constants.LINK_CMD}1.1:-")
)
override val isOpOnly = false
override val isPublic = true
@ -100,12 +100,12 @@ class Comment : AbstractCommand() {
}
private fun changeAuthor(
channel: String,
cmd: String,
entry: EntryLink,
entryIndex: Int,
commentIndex: Int,
event: GenericMessageEvent
channel: String,
cmd: String,
entry: EntryLink,
entryIndex: Int,
commentIndex: Int,
event: GenericMessageEvent
) {
if (event.isChannelOp(channel) && cmd.length > 1) {
val comment = entry.getComment(commentIndex)
@ -118,11 +118,11 @@ class Comment : AbstractCommand() {
}
private fun deleteComment(
channel: String,
entry: EntryLink,
entryIndex: Int,
commentIndex: Int,
event: GenericMessageEvent
channel: String,
entry: EntryLink,
entryIndex: Int,
commentIndex: Int,
event: GenericMessageEvent
) {
if (event.isChannelOp(channel) || event.user.nick == entry.getComment(commentIndex).nick) {
entry.deleteComment(commentIndex)
@ -134,11 +134,11 @@ class Comment : AbstractCommand() {
}
private fun setComment(
cmd: String,
entry: EntryLink,
entryIndex: Int,
commentIndex: Int,
event: GenericMessageEvent
cmd: String,
entry: EntryLink,
entryIndex: Int,
commentIndex: Int,
event: GenericMessageEvent
) {
entry.setComment(commentIndex, cmd, event.user.nick)
event.sendMessage(printComment(entryIndex, commentIndex, entry.getComment(commentIndex)))

View file

@ -161,8 +161,8 @@ class LinksManager : AbstractCommand() {
internal fun fetchTitle(link: String): String {
try {
val html = Jsoup.connect(link)
.userAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:74.0) Gecko/20100101 Firefox/74.0")
.get()
.userAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:74.0) Gecko/20100101 Firefox/74.0")
.get()
val title = html.title()
if (title.isNotBlank()) {
return title
@ -178,7 +178,7 @@ class LinksManager : AbstractCommand() {
return try {
val match = entries.links.single { it.link == link }
event.sendMessage(
"Duplicate".bold() + " >> " + printLink(entries.links.indexOf(match), match)
"Duplicate".bold() + " >> " + printLink(entries.links.indexOf(match), match)
)
true
} catch (ignore: NoSuchElementException) {

View file

@ -47,16 +47,16 @@ import org.pircbotx.hooks.types.GenericMessageEvent
class Posting : AbstractCommand() {
override val name = "posting"
override val help = listOf(
"Post a URL, by saying it on a line on its own:",
helpFormat("<url> [<title>] ${Tags.COMMAND}: <+tag> [...]]"),
"I will reply with a label, for example: ${Constants.LINK_CMD.bold()}1",
"To add a title, use its label and a pipe:",
helpFormat("${Constants.LINK_CMD}1:|This is the title"),
"To add 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",
"To edit a comment, see: ",
helpFormat("%c ${Constants.HELP_CMD} ${Comment.COMMAND}")
"Post a URL, by saying it on a line on its own:",
helpFormat("<url> [<title>] ${Tags.COMMAND}: <+tag> [...]]"),
"I will reply with a label, for example: ${Constants.LINK_CMD.bold()}1",
"To add a title, use its label and a pipe:",
helpFormat("${Constants.LINK_CMD}1:|This is the title"),
"To add 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",
"To edit a comment, see: ",
helpFormat("%c ${Constants.HELP_CMD} ${Comment.COMMAND}")
)
override val isOpOnly = false
override val isPublic = true

View file

@ -44,8 +44,8 @@ import org.pircbotx.hooks.types.GenericMessageEvent
class Tags : AbstractCommand() {
override val name = COMMAND
override val help = listOf(
"To categorize or tag a URL, use its label and a ${Constants.TAG_CMD}:",
helpFormat("${Constants.LINK_CMD}1${Constants.TAG_CMD}:<+tag|-tag> [...]")
"To categorize or tag a URL, use its label and a ${Constants.TAG_CMD}:",
helpFormat("${Constants.LINK_CMD}1${Constants.TAG_CMD}:<+tag|-tag> [...]")
)
override val isOpOnly = false
override val isPublic = true

View file

@ -46,8 +46,8 @@ import org.pircbotx.hooks.types.GenericMessageEvent
class View : AbstractCommand() {
override val name = VIEW_CMD
override val help = listOf(
"To list or search the current URL posts:",
helpFormat("%c $name [<start>] [<query>]")
"To list or search the current URL posts:",
helpFormat("%c $name [<start>] [<query>]")
)
override val isOpOnly = false
override val isPublic = true
@ -107,9 +107,9 @@ class View : AbstractCommand() {
if (sent == MAX_ENTRIES && index < entries.links.size) {
event.sendMessage("To view more, try: ")
event.sendMessage(
helpFormat(
helpCmdSyntax("%c $name ${index + 1} $query", event.bot().nick, event is PrivateMessageEvent)
)
helpFormat(
helpCmdSyntax("%c $name ${index + 1} $query", event.bot().nick, event is PrivateMessageEvent)
)
)
}
}

View file

@ -39,6 +39,7 @@ class NickComparator : Comparator<String>, Serializable {
}
companion object {
@Suppress("ConstPropertyName")
private const val serialVersionUID = 1L
}
}

View file

@ -58,7 +58,7 @@ class Seen(private val serialObject: String) : AbstractCommand() {
override val name = "seen"
override val help = listOf("To view when a nickname was last seen:", helpFormat("%c $name <nick>"))
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 isPublic = true
@ -130,12 +130,12 @@ class Seen(private val serialObject: String) : AbstractCommand() {
if (isEnabled()) {
@Suppress("UNCHECKED_CAST")
seenNicks.putAll(
loadSerialData(
serialObject,
TreeMap<String, SeenNick>(),
logger,
"seen nicknames"
) as TreeMap<String, SeenNick>
loadSerialData(
serialObject,
TreeMap<String, SeenNick>(),
logger,
"seen nicknames"
) as TreeMap<String, SeenNick>
)
}
}

View file

@ -35,6 +35,7 @@ import java.io.Serializable
data class SeenNick(val nick: String, val lastSeen: Long) : Serializable {
companion object {
@Suppress("ConstPropertyName")
private const val serialVersionUID = 1L
}
}

View file

@ -66,11 +66,11 @@ class Tell(private val serialObject: String) : AbstractCommand() {
override val name = "tell"
override val help = listOf(
"To send a message to someone when they join the channel:",
helpFormat("%c $name <nick> <message>"),
"To view queued and sent messages:",
helpFormat("%c $name ${View.VIEW_CMD}"),
"Messages are kept for ${maxDays.bold()}" + " day".plural(maxDays.toLong()) + '.'
"To send a message to someone when they join the channel:",
helpFormat("%c $name <nick> <message>"),
"To view queued and sent messages:",
helpFormat("%c $name ${View.VIEW_CMD}"),
"Messages are kept for ${maxDays.bold()}" + " day".plural(maxDays.toLong()) + '.'
)
override val isOpOnly: Boolean = false
override val isPublic: Boolean = isEnabled()
@ -89,6 +89,7 @@ class Tell(private val serialObject: String) : AbstractCommand() {
args.isBlank() -> {
helpResponse(channel, args, event)
}
args.startsWith(View.VIEW_CMD) -> {
if (event.isChannelOp(channel) && "${View.VIEW_CMD} $TELL_ALL_KEYWORD" == args) {
viewAll(event)
@ -96,9 +97,11 @@ class Tell(private val serialObject: String) : AbstractCommand() {
viewMessages(event)
}
}
args.startsWith("$TELL_DEL_KEYWORD ") -> {
deleteMessage(channel, args, event)
}
else -> {
newMessage(channel, args, event)
}
@ -123,9 +126,9 @@ class Tell(private val serialObject: String) : AbstractCommand() {
}
} else {
if (messages.removeIf {
it.id == id &&
(it.sender.equals(event.user.nick, true) || event.isChannelOp(channel))
}) {
it.id == id &&
(it.sender.equals(event.user.nick, true) || event.isChannelOp(channel))
}) {
save()
event.sendMessage("The message was deleted from the queue.")
} else {
@ -185,7 +188,7 @@ class Tell(private val serialObject: String) : AbstractCommand() {
if (message.sender == nickname) {
if (event !is MessageEvent) {
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.isNotified = true
@ -193,17 +196,17 @@ class Tell(private val serialObject: String) : AbstractCommand() {
}
} else {
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
save()
}
} else if (message.sender.equals(nickname, ignoreCase = true) && message.isReceived
&& !message.isNotified
&& !message.isNotified
) {
event.user.send().message(
"Your message ${"[ID ${message.id}]".reverseColor()} was sent to "
+ "${message.recipient.bold()} on ${message.receptionDate}"
"Your message ${"[ID ${message.id}]".reverseColor()} was sent to "
+ "${message.recipient.bold()} on ${message.receptionDate}"
)
message.isNotified = true
save()
@ -224,8 +227,8 @@ class Tell(private val serialObject: String) : AbstractCommand() {
if (messages.isNotEmpty()) {
for (message in messages) {
event.sendMessage(
"${message.sender.bold()}$ARROW${message.recipient.bold()} [ID: ${message.id}, " +
(if (message.isReceived) "DELIVERED]" else "QUEUED]")
"${message.sender.bold()}$ARROW${message.recipient.bold()} [ID: ${message.id}, " +
(if (message.isReceived) "DELIVERED]" else "QUEUED]")
)
}
} else {
@ -243,13 +246,13 @@ class Tell(private val serialObject: String) : AbstractCommand() {
}
if (message.isReceived) {
event.sendMessage(
message.sender.bold() + ARROW + message.recipient.bold() +
" [${message.receptionDate.toUtcDateTime()}, ID: ${message.id.bold()}, DELIVERED]"
message.sender.bold() + ARROW + message.recipient.bold() +
" [${message.receptionDate.toUtcDateTime()}, ID: ${message.id.bold()}, DELIVERED]"
)
} else {
event.sendMessage(
message.sender.bold() + ARROW + message.recipient.bold() +
" [${message.queued.toUtcDateTime()}, ID: ${message.id.bold()}, QUEUED]"
message.sender.bold() + ARROW + message.recipient.bold() +
" [${message.queued.toUtcDateTime()}, ID: ${message.id.bold()}, QUEUED]"
)
}
event.sendMessage(helpFormat(message.message))
@ -259,9 +262,9 @@ class Tell(private val serialObject: String) : AbstractCommand() {
} else {
event.sendMessage("To delete one or all delivered messages:")
event.sendMessage(
helpFormat(
helpCmdSyntax("%c $name $TELL_DEL_KEYWORD <id|$TELL_ALL_KEYWORD>", event.bot().nick, true)
)
helpFormat(
helpCmdSyntax("%c $name $TELL_DEL_KEYWORD <id|$TELL_ALL_KEYWORD>", event.bot().nick, true)
)
)
event.sendMessage(help.last())
}

View file

@ -39,20 +39,20 @@ import java.time.format.DateTimeFormatter
* Tell Message.
*/
class TellMessage(
/**
* Returns the message's sender.
*/
val sender: String,
/**
* Returns the message's sender.
*/
val sender: String,
/**
* Returns the message's recipient.
*/
val recipient: String,
/**
* Returns the message's recipient.
*/
val recipient: String,
/**
* Returns the message text.
*/
val message: String
/**
* Returns the message text.
*/
val message: String
) : Serializable {
/**
* Returns the queued date/time.
@ -98,6 +98,7 @@ class TellMessage(
}
companion object {
@Suppress("ConstPropertyName")
private const val serialVersionUID = 2L
}
}

View file

@ -34,10 +34,10 @@ package net.thauvin.erik.mobibot.entries
import net.thauvin.erik.mobibot.Utils.today
class Entries(
var channel: String = "",
var ircServer: String = "",
var logsDir: String = "",
var backlogs: String = ""
var channel: String = "",
var ircServer: String = "",
var logsDir: String = "",
var backlogs: String = ""
) {
val links = mutableListOf<EntryLink>()

View file

@ -43,7 +43,7 @@ object EntriesUtils {
*/
@JvmStatic
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.
@ -52,7 +52,7 @@ object EntriesUtils {
@JvmOverloads
fun printLink(entryIndex: Int, entry: EntryLink, isView: Boolean = false): String {
val buff = StringBuilder().append(entryIndex.toLinkLabel()).append(": ")
.append('[').append(entry.nick).append(']')
.append('[').append(entry.nick).append(']')
if (isView && entry.comments.isNotEmpty()) {
buff.append("[+").append(entry.comments.size).append(']')
}
@ -73,7 +73,7 @@ object EntriesUtils {
*/
@JvmStatic
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

View file

@ -46,6 +46,7 @@ data class EntryComment(var comment: String, var nick: String) : Serializable {
companion object {
// Serial version UID
@Suppress("ConstPropertyName")
private const val serialVersionUID: Long = 1L
}
}

View file

@ -40,40 +40,40 @@ import java.util.*
* The class used to store link entries.
*/
class EntryLink(
// Link's comments
val comments: MutableList<EntryComment> = mutableListOf(),
// Link's comments
val comments: MutableList<EntryComment> = mutableListOf(),
// Tags/categories
val tags: MutableList<SyndCategory> = mutableListOf(),
// Tags/categories
val tags: MutableList<SyndCategory> = mutableListOf(),
// Channel
var channel: String,
// Channel
var channel: String,
// Creation date
var date: Date = Calendar.getInstance().time,
// Creation date
var date: Date = Calendar.getInstance().time,
// Link's URL
var link: String,
// Link's URL
var link: String,
// Author's login
var login: String = "",
// Author's login
var login: String = "",
// Author's nickname
var nick: String,
// Author's nickname
var nick: String,
// Link's title
var title: String
// Link's title
var title: String
) : Serializable {
/**
* Creates a new entry.
*/
constructor(
link: String,
title: String,
nick: String,
login: String,
channel: String,
tags: List<String?>
link: String,
title: String,
nick: String,
login: String,
channel: String,
tags: List<String?>
) : this(link = link, title = title, nick = nick, login = login, channel = channel) {
setTags(tags)
}
@ -82,12 +82,12 @@ class EntryLink(
* Creates a new entry.
*/
constructor(
link: String,
title: String,
nick: String,
channel: String,
date: Date,
tags: List<SyndCategory>
link: String,
title: String,
nick: String,
channel: String,
date: Date,
tags: List<SyndCategory>
) : this(link = link, title = title, nick = nick, channel = channel, date = Date(date.time)) {
this.tags.addAll(tags)
}
@ -207,6 +207,7 @@ class EntryLink(
companion object {
// Serial version UID
@Suppress("ConstPropertyName")
private const val serialVersionUID: Long = 1L
}
}

View file

@ -55,24 +55,24 @@ class FeedsManager private constructor() {
private val logger: Logger = LoggerFactory.getLogger(FeedsManager::class.java)
// The file containing the current entries.
private const val currentXml = "current.xml"
private const val CURRENT_XML = "current.xml"
// The .xml extension.
private const val dotXml = ".xml"
private const val DOT_XML = ".xml"
/**
* Loads the current feed.
*/
@JvmStatic
@Throws(IOException::class, FeedException::class)
fun loadFeed(entries: Entries, currentFile: String = currentXml): String {
fun loadFeed(entries: Entries, currentFile: String = CURRENT_XML): String {
entries.links.clear()
val xml = Paths.get("${entries.logsDir}${currentFile}")
var pubDate = today()
if (xml.exists()) {
val input = SyndFeedInput()
InputStreamReader(
Files.newInputStream(xml), StandardCharsets.UTF_8
Files.newInputStream(xml), StandardCharsets.UTF_8
).use { reader ->
val feed = input.build(reader)
pubDate = feed.publishedDate.toIsoLocalDate()
@ -81,12 +81,12 @@ class FeedsManager private constructor() {
for (i in items.indices.reversed()) {
with(items[i]) {
entry = EntryLink(
link,
title,
author.substring(author.lastIndexOf('(') + 1, author.length - 1),
entries.channel,
publishedDate,
categories
link,
title,
author.substring(author.lastIndexOf('(') + 1, author.length - 1),
entries.channel,
publishedDate,
categories
)
var split: List<String>
for (comment in description.value.split("<br/>")) {
@ -110,7 +110,7 @@ class FeedsManager private constructor() {
* Saves the feeds.
*/
@JvmStatic
fun saveFeed(entries: Entries, currentFile: String = currentXml) {
fun saveFeed(entries: Entries, currentFile: String = CURRENT_XML) {
if (logger.isDebugEnabled) logger.debug("Saving the feeds...")
if (entries.logsDir.isNotBlank()) {
try {
@ -119,7 +119,7 @@ class FeedsManager private constructor() {
val items: MutableList<SyndEntry> = mutableListOf()
var item: SyndEntry
OutputStreamWriter(
Files.newOutputStream(Paths.get("${entries.logsDir}${currentFile}")), StandardCharsets.UTF_8
Files.newOutputStream(Paths.get("${entries.logsDir}${currentFile}")), StandardCharsets.UTF_8
).use { fw ->
with(rss) {
feedType = "rss_2.0"
@ -134,13 +134,13 @@ class FeedsManager private constructor() {
with(entries.links[i]) {
buff.setLength(0)
buff.append("Posted by <b>")
.append(nick)
.append("</b> on <a href=\"irc://")
.append(entries.ircServer).append('/')
.append(channel)
.append("\"><b>")
.append(channel)
.append("</b></a>")
.append(nick)
.append("</b> on <a href=\"irc://")
.append(entries.ircServer).append('/')
.append(channel)
.append("\"><b>")
.append(channel)
.append("</b></a>")
if (comments.isNotEmpty()) {
buff.append(" <br/><br/>")
for (j in comments.indices) {
@ -165,11 +165,11 @@ class FeedsManager private constructor() {
output.output(rss, fw)
}
OutputStreamWriter(
Files.newOutputStream(
Paths.get(
entries.logsDir + today() + dotXml
)
), StandardCharsets.UTF_8
Files.newOutputStream(
Paths.get(
entries.logsDir + today() + DOT_XML
)
), StandardCharsets.UTF_8
).use { fw -> output.output(rss, fw) }
} catch (e: FeedException) {
if (logger.isWarnEnabled) logger.warn("Unable to generate the entries feed.", e)

View file

@ -56,8 +56,8 @@ class ChatGpt : AbstractModule() {
if (args.isNotBlank()) {
try {
val answer = chat(
args.trim(), properties[API_KEY_PROP],
properties.getOrDefault(MAX_TOKENS_PROP, "1024").toInt()
args.trim(), properties[API_KEY_PROP],
properties.getOrDefault(MAX_TOKENS_PROP, "1024").toInt()
)
if (answer.isNotBlank()) {
event.sendMessage(WordUtils.wrap(answer, 400))
@ -107,13 +107,13 @@ class ChatGpt : AbstractModule() {
if (!apiKey.isNullOrEmpty()) {
val prompt = JSONWriter.valueToString("Q:$query\nA:")
val request = HttpRequest.newBuilder()
.uri(URI.create(API_URL))
.header("Content-Type", "application/json")
.header("Authorization", "Bearer $apiKey")
.header("User-Agent", Constants.USER_AGENT)
.POST(
HttpRequest.BodyPublishers.ofString(
"""{
.uri(URI.create(API_URL))
.header("Content-Type", "application/json")
.header("Authorization", "Bearer $apiKey")
.header("User-Agent", Constants.USER_AGENT)
.POST(
HttpRequest.BodyPublishers.ofString(
"""{
"model": "text-davinci-003",
"prompt": $prompt,
"temperature": 0,
@ -122,9 +122,9 @@ class ChatGpt : AbstractModule() {
"frequency_penalty": 0,
"presence_penalty": 0
}""".trimIndent()
)
)
.build()
)
.build()
try {
val response = HttpClient.newHttpClient().send(request, HttpResponse.BodyHandlers.ofString())
if (response.statusCode() == 200) {
@ -134,16 +134,16 @@ class ChatGpt : AbstractModule() {
return choices.getJSONObject(0).getString("text").trim()
} catch (e: JSONException) {
throw ModuleException(
"$CHATGPT_CMD($query): JSON",
"A JSON error has occurred while conversing with $CHATGPT_NAME.",
e
"$CHATGPT_CMD($query): JSON",
"A JSON error has occurred while conversing with $CHATGPT_NAME.",
e
)
}
} else {
if (response.statusCode() == 429) {
throw ModuleException(
"$CHATGPT_CMD($query): Rate limit reached",
"Rate limit reached. Please try again later."
"$CHATGPT_CMD($query): Rate limit reached",
"Rate limit reached. Please try again later."
)
} else {
throw IOException("HTTP Status Code: " + response.statusCode())
@ -151,9 +151,9 @@ class ChatGpt : AbstractModule() {
}
} catch (e: IOException) {
throw ModuleException(
"$CHATGPT_CMD($query): IO",
"An IO error has occurred while conversing with $CHATGPT_NAME.",
e
"$CHATGPT_CMD($query): IO",
"An IO error has occurred while conversing with $CHATGPT_NAME.",
e
)
}
} else {

View file

@ -134,9 +134,9 @@ class CryptoPrices : AbstractModule() {
}
} catch (e: CryptoException) {
throw ModuleException(
"loadCurrencies(): CE",
"An error has occurred while retrieving the currencies table.",
e
"loadCurrencies(): CE",
"An error has occurred while retrieving the currencies table.",
e
)
}
}

View file

@ -78,6 +78,7 @@ class CurrencyConverter : AbstractModule() {
SYMBOLS.isEmpty() -> {
event.respond(EMPTY_SYMBOLS_TABLE)
}
args.matches("\\d+([,\\d]+)?(\\.\\d+)? [a-zA-Z]{3}+ (to|in) [a-zA-Z]{3}+".toRegex()) -> {
val msg = convertCurrency(properties[API_KEY_PROP], args)
event.respond(msg.msg)
@ -85,10 +86,12 @@ class CurrencyConverter : AbstractModule() {
helpResponse(event)
}
}
args.contains(CODES_KEYWORD) -> {
event.sendMessage("The supported currency codes are:")
event.sendList(SYMBOLS.keys.toList(), 11, isIndent = true)
}
else -> {
helpResponse(event)
}

View file

@ -65,10 +65,10 @@ class GoogleSearch : AbstractModule() {
if (args.isNotBlank()) {
try {
val results = searchGoogle(
args,
properties[API_KEY_PROP],
properties[CSE_KEY_PROP],
event.user.nick
args,
properties[API_KEY_PROP],
properties[CSE_KEY_PROP],
event.user.nick
)
for (msg in results) {
if (msg.isError) {
@ -104,23 +104,23 @@ class GoogleSearch : AbstractModule() {
@JvmStatic
@Throws(ModuleException::class)
fun searchGoogle(
query: String,
apiKey: String?,
cseKey: String?,
quotaUser: String = ReleaseInfo.PROJECT
query: String,
apiKey: String?,
cseKey: String?,
quotaUser: String = ReleaseInfo.PROJECT
): List<Message> {
if (apiKey.isNullOrBlank() || cseKey.isNullOrBlank()) {
throw ModuleException(
"${GoogleSearch::class.java.name} is disabled.",
"${GOOGLE_CMD.capitalise()} is disabled. The API keys are missing."
"${GoogleSearch::class.java.name} is disabled.",
"${GOOGLE_CMD.capitalise()} is disabled. The API keys are missing."
)
}
val results = mutableListOf<Message>()
if (query.isNotBlank()) {
try {
val url = URL(
"https://www.googleapis.com/customsearch/v1?key=$apiKey&cx=$cseKey" +
"&quotaUser=${quotaUser}&q=${query.encodeUrl()}&filter=1&num=5&alt=json"
"https://www.googleapis.com/customsearch/v1?key=$apiKey&cx=$cseKey" +
"&quotaUser=${quotaUser}&q=${query.encodeUrl()}&filter=1&num=5&alt=json"
)
val json = JSONObject(url.reader().body)
if (json.has("items")) {
@ -141,9 +141,9 @@ class GoogleSearch : AbstractModule() {
throw ModuleException("searchGoogle($query): IOE", "An IO error has occurred searching Google.", e)
} catch (e: JSONException) {
throw ModuleException(
"searchGoogle($query): JSON",
"A JSON error has occurred searching Google.",
e
"searchGoogle($query): JSON",
"A JSON error has occurred searching Google.",
e
)
}
} else {

View file

@ -55,9 +55,9 @@ class Lookup : AbstractModule() {
event.respondWith(nslookup(args).prependIndent())
} catch (ignore: UnknownHostException) {
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]?)")
.toRegex()
)
("(?:(?: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()
)
) {
try {
val lines = whois(args)

View file

@ -65,7 +65,7 @@ class Mastodon : SocialModule() {
private fun formatTags(entry: EntryLink): String {
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)
override fun post(message: String, isDm: Boolean): String {
return toot(
apiKey = properties[ACCESS_TOKEN_PROP],
instance = properties[INSTANCE_PROP],
handle = handle,
message = message,
isDm = isDm
apiKey = properties[ACCESS_TOKEN_PROP],
instance = properties[INSTANCE_PROP],
handle = handle,
message = message,
isDm = isDm
)
}
@ -99,21 +99,21 @@ class Mastodon : SocialModule() {
@Throws(ModuleException::class)
fun toot(apiKey: String?, instance: String?, handle: String?, message: String, isDm: Boolean): String {
val request = HttpRequest.newBuilder()
.uri(URI.create("https://$instance/api/v1/statuses"))
.header("Content-Type", "application/json")
.header("Authorization", "Bearer $apiKey")
.POST(
HttpRequest.BodyPublishers.ofString(
JSONWriter.valueToString(
if (isDm) {
mapOf("status" to "${handle?.prefixIfMissing('@')} $message", "visibility" to "direct")
} else {
mapOf("status" to message)
}
)
)
.uri(URI.create("https://$instance/api/v1/statuses"))
.header("Content-Type", "application/json")
.header("Authorization", "Bearer $apiKey")
.POST(
HttpRequest.BodyPublishers.ofString(
JSONWriter.valueToString(
if (isDm) {
mapOf("status" to "${handle?.prefixIfMissing('@')} $message", "visibility" to "direct")
} else {
mapOf("status" to message)
}
)
)
.build()
)
.build()
try {
val response = HttpClient.newHttpClient().send(request, HttpResponse.BodyHandlers.ofString())
if (response.statusCode() == 200) {

View file

@ -34,11 +34,12 @@ package net.thauvin.erik.mobibot.modules
* The `ModuleException` class.
*/
class ModuleException @JvmOverloads constructor(
val debugMessage: String,
message: String? = null,
cause: Throwable? = null
val debugMessage: String,
message: String? = null,
cause: Throwable? = null
) : Exception(message, cause) {
companion object {
@Suppress("ConstPropertyName")
private const val serialVersionUID = 1L
}
}

View file

@ -50,18 +50,18 @@ class Ping : AbstractModule() {
*/
@JvmField
val PINGS = listOf(
"is barely alive.",
"is trying to stay awake.",
"has gone fishing.",
"is somewhere over the rainbow.",
"has fallen and can't get up.",
"is running. You better go chase it.",
"has just spontaneously combusted.",
"is talking to itself... don't interrupt. That's rude.",
"is bartending at an AA meeting.",
"is hibernating.",
"is saving energy: apathetic mode activated.",
"is busy. Go away!"
"is barely alive.",
"is trying to stay awake.",
"has gone fishing.",
"is somewhere over the rainbow.",
"has fallen and can't get up.",
"is running. You better go chase it.",
"has just spontaneously combusted.",
"is talking to itself... don't interrupt. That's rude.",
"is bartending at an AA meeting.",
"is hibernating.",
"is saving energy: apathetic mode activated.",
"is busy. Go away!"
)
@JvmStatic

View file

@ -52,10 +52,10 @@ class RockPaperScissors : AbstractModule() {
with(help) {
add("To play Rock Paper Scissors:")
add(
helpFormat(
"%c ${Hands.ROCK.name.lowercase()} | ${Hands.PAPER.name.lowercase()}"
+ " | ${Hands.SCISSORS.name.lowercase()}"
)
helpFormat(
"%c ${Hands.ROCK.name.lowercase()} | ${Hands.PAPER.name.lowercase()}"
+ " | ${Hands.SCISSORS.name.lowercase()}"
)
)
}
}

View file

@ -132,8 +132,8 @@ class StockQuote : AbstractModule() {
fun getQuote(symbol: String, apiKey: String?): List<Message> {
if (apiKey.isNullOrBlank()) {
throw ModuleException(
"${StockQuote::class.java.name} is disabled.",
"${STOCK_CMD.capitalise()} is disabled. The API key is missing."
"${StockQuote::class.java.name} is disabled.",
"${STOCK_CMD.capitalise()} is disabled. The API key is missing."
)
}
val messages = mutableListOf<Message>()
@ -144,8 +144,8 @@ class StockQuote : AbstractModule() {
with(messages) {
// Search for symbol/keywords
response = URL(
"${API_URL}SYMBOL_SEARCH&keywords=" + symbol.encodeUrl() + "&apikey="
+ apiKey.encodeUrl()
"${API_URL}SYMBOL_SEARCH&keywords=" + symbol.encodeUrl() + "&apikey="
+ apiKey.encodeUrl()
).reader().body
var json = getJsonResponse(response, debugMessage)
val symbols = json.getJSONArray("bestMatches")
@ -156,9 +156,9 @@ class StockQuote : AbstractModule() {
// Get quote for symbol
response = URL(
"${API_URL}GLOBAL_QUOTE&symbol="
+ symbolInfo.getString("1. symbol").encodeUrl() + "&apikey="
+ apiKey.encodeUrl()
"${API_URL}GLOBAL_QUOTE&symbol="
+ symbolInfo.getString("1. symbol").encodeUrl() + "&apikey="
+ apiKey.encodeUrl()
).reader().body
json = getJsonResponse(response, debugMessage)
val quote = json.getJSONObject("Global Quote")
@ -167,50 +167,50 @@ class StockQuote : AbstractModule() {
} else {
add(
PublicMessage(
"Symbol: " + quote.getString("01. symbol").unescapeXml()
+ " [" + symbolInfo.getString("2. name").unescapeXml() + ']'
)
PublicMessage(
"Symbol: " + quote.getString("01. symbol").unescapeXml()
+ " [" + symbolInfo.getString("2. name").unescapeXml() + ']'
)
)
val pad = 10
add(
PublicMessage(
"Price:".padEnd(pad).prependIndent()
+ quote.getString("05. price").unescapeXml()
)
PublicMessage(
"Price:".padEnd(pad).prependIndent()
+ quote.getString("05. price").unescapeXml()
)
)
add(
PublicMessage(
"Previous:".padEnd(pad).prependIndent()
+ quote.getString("08. previous close").unescapeXml()
)
PublicMessage(
"Previous:".padEnd(pad).prependIndent()
+ quote.getString("08. previous close").unescapeXml()
)
)
val data = arrayOf(
"Open" to "02. open",
"High" to "03. high",
"Low" to "04. low",
"Volume" to "06. volume",
"Latest" to "07. latest trading day"
"Open" to "02. open",
"High" to "03. high",
"Low" to "04. low",
"Volume" to "06. volume",
"Latest" to "07. latest trading day"
)
data.forEach {
add(
NoticeMessage(
"${it.first}:".padEnd(pad).prependIndent()
+ quote.getString(it.second).unescapeXml()
)
NoticeMessage(
"${it.first}:".padEnd(pad).prependIndent()
+ quote.getString(it.second).unescapeXml()
)
)
}
add(
NoticeMessage(
"Change:".padEnd(pad).prependIndent()
+ quote.getString("09. change").unescapeXml()
+ " [" + quote.getString("10. change percent").unescapeXml() + ']'
)
NoticeMessage(
"Change:".padEnd(pad).prependIndent()
+ quote.getString("09. change").unescapeXml()
+ " [" + quote.getString("10. change percent").unescapeXml() + ']'
)
)
}
}

View file

@ -120,8 +120,8 @@ class Weather2 : AbstractModule() {
fun getWeather(query: String, apiKey: String?): List<Message> {
if (apiKey.isNullOrBlank()) {
throw ModuleException(
"${Weather2::class.java.name} is disabled.",
"${WEATHER_CMD.capitalise()} is disabled. The API key is missing."
"${Weather2::class.java.name} is disabled.",
"${WEATHER_CMD.capitalise()} is disabled. The API key is missing."
)
}
val owm = OWM(apiKey)
@ -145,10 +145,10 @@ class Weather2 : AbstractModule() {
}
if (cwd.hasCityName()) {
messages.add(
PublicMessage(
"City: ${cwd.cityName}, " +
country.name.replace('_', ' ').capitalizeWords() + " [${country.value}]"
)
PublicMessage(
"City: ${cwd.cityName}, " +
country.name.replace('_', ' ').capitalizeWords() + " [${country.value}]"
)
)
cwd.mainData?.let {
with(it) {
@ -181,8 +181,8 @@ class Weather2 : AbstractModule() {
for (w in it) {
w?.let {
condition.append(' ')
.append(w.getDescription().capitalise())
.append('.')
.append(w.getDescription().capitalise())
.append('.')
}
}
messages.add(NoticeMessage(condition.toString()))
@ -192,15 +192,15 @@ class Weather2 : AbstractModule() {
cwd.cityId?.let {
if (it > 0) {
messages.add(
NoticeMessage("https://openweathermap.org/city/$it", Colors.GREEN)
NoticeMessage("https://openweathermap.org/city/$it", Colors.GREEN)
)
} else {
messages.add(
NoticeMessage(
"https://openweathermap.org/find?q="
+ "$city,${code.uppercase()}".encodeUrl(),
Colors.GREEN
)
NoticeMessage(
"https://openweathermap.org/find?q="
+ "$city,${code.uppercase()}".encodeUrl(),
Colors.GREEN
)
)
}
}
@ -209,9 +209,9 @@ class Weather2 : AbstractModule() {
} catch (e: APIException) {
if (e.code == 404) {
throw ModuleException(
"getWeather($query): API ${e.code}",
"The requested city was not found.",
e
"getWeather($query): API ${e.code}",
"The requested city was not found.",
e
)
} else {
throw ModuleException("getWeather($query): API ${e.code}", e.message, e)

View file

@ -60,15 +60,15 @@ class WolframAlpha : AbstractModule() {
try {
val query = args.trim().split("units=", limit = 2, ignoreCase = true)
event.sendMessage(
queryWolfram(
query[0].trim(),
units = if (query.size == 2) {
getUnits(query[1].trim())
} else {
getUnits(properties[UNITS_PROP])
},
appId = properties[APPID_KEY_PROP]
)
queryWolfram(
query[0].trim(),
units = if (query.size == 2) {
getUnits(query[1].trim())
} else {
getUnits(properties[UNITS_PROP])
},
appId = properties[APPID_KEY_PROP]
)
)
} catch (e: ModuleException) {
if (logger.isWarnEnabled) logger.warn(e.debugMessage, e)
@ -111,15 +111,15 @@ class WolframAlpha : AbstractModule() {
return urlReader.body
} else {
throw ModuleException(
"wolfram($query): ${urlReader.responseCode} : ${urlReader.body} ",
urlReader.body.ifEmpty {
"Looks like Wolfram Alpha isn't able to answer that. (${urlReader.responseCode})"
}
"wolfram($query): ${urlReader.responseCode} : ${urlReader.body} ",
urlReader.body.ifEmpty {
"Looks like Wolfram Alpha isn't able to answer that. (${urlReader.responseCode})"
}
)
}
} catch (ioe: IOException) {
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 {

View file

@ -322,7 +322,7 @@ class WorldTime : AbstractModule() {
put("ZULU", "Zulu")
put("ZW", "Africa/Harare")
ZoneId.getAvailableZoneIds().filter { it.length <= 3 && !containsKey(it) }
.forEach { tz -> put(tz, tz) }
.forEach { tz -> put(tz, tz) }
}
// The Time command
@ -336,7 +336,7 @@ class WorldTime : AbstractModule() {
// Date/Time Format
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.

View file

@ -34,4 +34,4 @@ package net.thauvin.erik.mobibot.msg
* The `ErrorMessage` class.
*/
class ErrorMessage @JvmOverloads constructor(msg: String, color: String = DEFAULT_COLOR) :
Message(msg, color, isError = true)
Message(msg, color, isError = true)

View file

@ -36,11 +36,11 @@ import net.thauvin.erik.semver.Constants
* The `Message` class.
*/
open class Message @JvmOverloads constructor(
var msg: String,
var color: String = DEFAULT_COLOR,
var isNotice: Boolean = false,
isError: Boolean = false,
var isPrivate: Boolean = false
var msg: String,
var color: String = DEFAULT_COLOR,
var isNotice: Boolean = false,
isError: Boolean = false,
var isPrivate: Boolean = false
) {
companion object {
var DEFAULT_COLOR = Constants.EMPTY

View file

@ -34,5 +34,5 @@ package net.thauvin.erik.mobibot.msg
* The `NoticeMessage` class.
*/
class NoticeMessage @JvmOverloads constructor(msg: String, color: String = DEFAULT_COLOR) :
Message(msg, color, isNotice = true)
Message(msg, color, isNotice = true)

View file

@ -34,4 +34,4 @@ package net.thauvin.erik.mobibot.msg
* The `PrivateMessage` class.
*/
class PrivateMessage @JvmOverloads constructor(msg: String, color: String = DEFAULT_COLOR) :
Message(msg, color, isPrivate = true)
Message(msg, color, isPrivate = true)

View file

@ -76,8 +76,8 @@ abstract class SocialModule : AbstractModule() {
post(message = formatEntry(LinksManager.entries.links[index]), isDm = false)
} catch (e: ModuleException) {
if (logger.isWarnEnabled) logger.warn(
"Failed to post entry ${index.toLinkLabel()} on $name.",
e
"Failed to post entry ${index.toLinkLabel()} on $name.",
e
)
}
}

View file

@ -76,11 +76,11 @@ class AddonsTest {
assertThat(addons.names.ops, "names.ops").containsExactly("cycle")
assertThat(addons.names.commands, "names.command").containsExactly(
"joke",
"rock",
"paper",
"scissors",
"ignore"
"joke",
"rock",
"paper",
"scissors",
"ignore"
)
}
}

View file

@ -46,9 +46,9 @@ object ExceptionSanitizer {
with(this) {
if (!cause?.message.isNullOrBlank()) {
return ModuleException(
debugMessage,
cause?.javaClass?.name + ": " + cause?.message?.replaceEach(search, obfuscate),
this
debugMessage,
cause?.javaClass?.name + ": " + cause?.message?.replaceEach(search, obfuscate),
this
)
} else if (!message.isNullOrBlank()) {
return ModuleException(debugMessage, message?.replaceEach(search, obfuscate), this)

View file

@ -68,7 +68,7 @@ class PinboardTest : LocalProperties() {
private fun validatePin(apiToken: String, url: String, vararg matches: String): Boolean {
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 {
if (!response.contains(it)) {

View file

@ -73,7 +73,7 @@ import java.util.*
*/
class UtilsTest {
private val ascii =
" !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"
" !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"
private val cal = Calendar.getInstance()
private val localDateTime = LocalDateTime.of(1952, 2, 17, 12, 30, 0)
private val test = "This is a test."
@ -89,7 +89,7 @@ class UtilsTest {
val sep = '/'
val url = "https://erik.thauvin.net"
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$sep".appendIfMissing(sep), "appendIfMissing($url$sep)").isEqualTo("$url$sep")
}
@ -115,24 +115,24 @@ class UtilsTest {
fun textCapitaliseWords() {
assertThat(test.capitalizeWords(), "captiatlizeWords(test)").isEqualTo("This Is A Test.")
assertThat("Already Capitalized".capitalizeWords(), "already capitalized")
.isEqualTo("Already Capitalized")
.isEqualTo("Already Capitalized")
assertThat(" a test ".capitalizeWords(), "with spaces").isEqualTo(" A Test ")
}
@Test
fun testColorize() {
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()")
.isEqualTo(Colors.RED + ascii + Colors.NORMAL)
.isEqualTo(Colors.RED + ascii + Colors.NORMAL)
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("".colorize(Colors.RED), "colorize()").isEqualTo("")
assertThat(ascii.colorize(DEFAULT_COLOR), "ascii.colorize()").isEqualTo(ascii)
assertThat(" ".colorize(Colors.NORMAL), "blank.colorize()")
.isEqualTo(Colors.NORMAL + " " + Colors.NORMAL)
.isEqualTo(Colors.NORMAL + " " + Colors.NORMAL)
}
@Test
@ -164,19 +164,19 @@ class UtilsTest {
fun testHelpCmdSyntax() {
val bot = "mobibot"
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)")
.isEqualTo("/msg $bot $bot $test /msg $bot $test $bot")
.isEqualTo("/msg $bot $bot $test /msg $bot $test $bot")
}
@Test
fun testHelpFormat() {
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)")
.isEqualTo(test.prependIndent())
.isEqualTo(test.prependIndent())
assertThat(helpFormat(test, isBold = true, isIndent = true), "helpFormat(bold,indent)")
.isEqualTo(test.colorize(Colors.BOLD).prependIndent())
.isEqualTo(test.colorize(Colors.BOLD).prependIndent())
}
@ -218,15 +218,15 @@ class UtilsTest {
val search = arrayOf("one", "two", "three")
val replace = arrayOf("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(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)")
.isEqualTo(test)
.isEqualTo(test)
}
@Test
@ -258,7 +258,7 @@ class UtilsTest {
@Test
fun testUnescapeXml() {
assertThat("&lt;a name=&quot;test &amp; &apos;&#39;&quot;&gt;".unescapeXml()).isEqualTo(
"<a name=\"test & ''\">"
"<a name=\"test & ''\">"
)
}

View file

@ -40,14 +40,14 @@ class InfoTest {
@Test(groups = ["commands"])
fun testToUptime() {
assertThat(
547800300076L.toUptime(),
"upTime(full)"
547800300076L.toUptime(),
"upTime(full)"
).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(110700000L.toUptime(), "upTime(days hours minutes)").isEqualTo("1 day 6 hours 45 minutes")
assertThat(
1320300000L.toUptime(),
"upTime(weeks days hours minutes)"
1320300000L.toUptime(),
"upTime(weeks days hours minutes)"
).isEqualTo("2 weeks 1 day 6 hours 45 minutes")
assertThat(2700000L.toUptime(), "upTime(45 minutes)").isEqualTo("45 minutes")
assertThat(60000L.toUptime(), "upTime(1 minute)").isEqualTo("1 minute")

View file

@ -48,13 +48,13 @@ class RecapTest {
assertThat(Recap.recaps, "Recap.recaps").all {
size().isEqualTo(Recap.MAX_RECAPS)
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)
.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)
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())
}
}

View file

@ -47,8 +47,8 @@ class LinksManagerTest {
fun fetchTitle() {
assertThat(linksManager.fetchTitle("https://erik.thauvin.net/"), "fetchTitle(Erik)").contains("Erik's Weblog")
assertThat(
linksManager.fetchTitle("https://www.google.com/foo"),
"fetchTitle(Foo)"
linksManager.fetchTitle("https://www.google.com/foo"),
"fetchTitle(Foo)"
).isEqualTo(Constants.NO_TITLE)
}

View file

@ -45,14 +45,14 @@ class ViewTest {
for (i in 1..10) {
LinksManager.entries.links.add(
EntryLink(
"https://www.example.com/$i",
"Example $i",
"nick$i",
"login$i",
"#channel",
emptyList()
)
EntryLink(
"https://www.example.com/$i",
"Example $i",
"nick$i",
"login$i",
"#channel",
emptyList()
)
)
}

View file

@ -46,14 +46,14 @@ class EntriesUtilsTest {
private val links = buildList {
for (i in 0..5) {
add(
EntryLink(
"https://www.mobitopia.org/$i",
"Mobitopia$i",
"Skynx$i",
"JimH$i",
"#mobitopia$i",
listOf("tag1", "tag2", "tag3", "TAG4", "Tag5")
)
EntryLink(
"https://www.mobitopia.org/$i",
"Mobitopia$i",
"Skynx$i",
"JimH$i",
"#mobitopia$i",
listOf("tag1", "tag2", "tag3", "TAG4", "Tag5")
)
)
}
}
@ -67,7 +67,7 @@ class EntriesUtilsTest {
fun printLinkTest() {
for (i in links.indices) {
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 )")
}
@ -79,7 +79,7 @@ class EntriesUtilsTest {
fun printTagsTest() {
for (i in links.indices) {
assertThat(
printTags(i - 1, links[i]), "tag $i"
printTags(i - 1, links[i]), "tag $i"
).isEqualTo("L${i}T: tag1, tag2, tag3, tag4, tag5")
}
}

View file

@ -48,8 +48,8 @@ import java.util.*
*/
class EntryLinkTest {
private val entryLink = EntryLink(
"https://www.mobitopia.org/", "Mobitopia", "Skynx", "JimH", "#mobitopia",
listOf("tag1", "tag2", "tag3", "TAG4", "Tag5")
"https://www.mobitopia.org/", "Mobitopia", "Skynx", "JimH", "#mobitopia",
listOf("tag1", "tag2", "tag3", "TAG4", "Tag5")
)
@Test(groups = ["entries"])
@ -117,12 +117,12 @@ class EntryLinkTest {
entryLink.setTags("+mobitopia")
entryLink.setTags("-mobitopia")
assertThat(
entryLink.formatTags(","),
"formatTags(',')"
entryLink.formatTags(","),
"formatTags(',')"
).isEqualTo("tag1,tag2,tag3,tag4,mobitopia")
entryLink.setTags("-tag4 tag5")
assertThat(
entryLink.formatTags(" ", ","), "formatTag(' ',',')"
entryLink.formatTags(" ", ","), "formatTag(' ',',')"
).isEqualTo(",tag1 tag2 tag3 mobitopia tag5")
val size = entryLink.tags.size
entryLink.setTags("")

View file

@ -42,21 +42,21 @@ class ChatGptTest : LocalProperties() {
@Test(groups = ["modules"])
fun testApiKey() {
assertFailure { ChatGpt.chat("1 gallon to liter", "", 0) }
.isInstanceOf(ModuleException::class.java)
.hasNoCause()
.isInstanceOf(ModuleException::class.java)
.hasNoCause()
}
@Test(groups = ["modules", "no-ci"])
fun testChat() {
val apiKey = getProperty(ChatGpt.API_KEY_PROP)
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")
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")
assertFailure { ChatGpt.chat("1 liter to gallon", apiKey, 0) }
.isInstanceOf(ModuleException::class.java)
.isInstanceOf(ModuleException::class.java)
}
}

View file

@ -49,7 +49,7 @@ import org.testng.annotations.Test
/**
* The `CurrencyConvertTest` class.
*/
class CurrencyConverterTest: LocalProperties() {
class CurrencyConverterTest : LocalProperties() {
@BeforeClass
@Throws(ModuleException::class)
@ -62,22 +62,22 @@ class CurrencyConverterTest: LocalProperties() {
fun testConvertCurrency() {
val apiKey = getProperty(CurrencyConverter.API_KEY_PROP)
assertThat(
convertCurrency(apiKey,"100 USD to EUR").msg,
"convertCurrency(100 USD to EUR)"
convertCurrency(apiKey, "100 USD to EUR").msg,
"convertCurrency(100 USD to EUR)"
).matches("100 United States Dollar = \\d{2,3}\\.\\d{2,3} Euro".toRegex())
assertThat(
convertCurrency(apiKey,"1 USD to GBP").msg,
"convertCurrency(1 USD to BGP)"
convertCurrency(apiKey, "1 USD to GBP").msg,
"convertCurrency(1 USD to BGP)"
).matches("1 United States Dollar = 0\\.\\d{2,3} Pound Sterling".toRegex())
assertThat(
convertCurrency(apiKey,"100,000.00 CAD to USD").msg,
"convertCurrency(100,000.00 GBP to USD)"
convertCurrency(apiKey, "100,000.00 CAD to USD").msg,
"convertCurrency(100,000.00 GBP to USD)"
).matches("100,000.00 Canadian Dollar = \\d+\\.\\d{2,3} United States Dollar".toRegex())
assertThat(convertCurrency(apiKey,"100 USD to USD"), "convertCurrency(100 USD to USD)").all {
assertThat(convertCurrency(apiKey, "100 USD to USD"), "convertCurrency(100 USD to USD)").all {
prop(Message::msg).contains("You're kidding, right?")
isInstanceOf(PublicMessage::class.java)
}
assertThat(convertCurrency(apiKey,"100 USD"), "convertCurrency(100 USD)").all {
assertThat(convertCurrency(apiKey, "100 USD"), "convertCurrency(100 USD)").all {
prop(Message::msg).contains("Invalid query.")
isInstanceOf(ErrorMessage::class.java)
}

View file

@ -42,12 +42,12 @@ class DiceTest {
fun testRoll() {
assertThat(Dice.roll(1, 1), "roll(1d1)").isEqualTo("\u00021\u0002")
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)")
.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)")
.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)")
.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())
}
}

View file

@ -48,19 +48,19 @@ class GoogleSearchTest : LocalProperties() {
@Test(groups = ["modules"])
fun testAPIKeys() {
assertThat(
searchGoogle("", "apikey", "cssKey").first(),
"searchGoogle(empty)"
searchGoogle("", "apikey", "cssKey").first(),
"searchGoogle(empty)"
).isInstanceOf(ErrorMessage::class.java)
assertFailure { searchGoogle("test", "", "apiKey") }
.isInstanceOf(ModuleException::class.java).hasNoCause()
.isInstanceOf(ModuleException::class.java).hasNoCause()
assertFailure { searchGoogle("test", "apiKey", "") }
.isInstanceOf(ModuleException::class.java).hasNoCause()
.isInstanceOf(ModuleException::class.java).hasNoCause()
assertFailure { searchGoogle("test", "apiKey", "cssKey") }
.isInstanceOf(ModuleException::class.java)
.hasMessage("API key not valid. Please pass a valid API key.")
.isInstanceOf(ModuleException::class.java)
.hasMessage("API key not valid. Please pass a valid API key.")
}
@Test(groups = ["no-ci", "modules"])

View file

@ -42,13 +42,13 @@ class MastodonTest : LocalProperties() {
fun testToot() {
val msg = "Testing Mastodon API from ${getHostName()}"
assertThat(
toot(
getProperty(Mastodon.ACCESS_TOKEN_PROP),
getProperty(Mastodon.INSTANCE_PROP),
getProperty(Mastodon.HANDLE_PROP),
msg,
true
)
toot(
getProperty(Mastodon.ACCESS_TOKEN_PROP),
getProperty(Mastodon.INSTANCE_PROP),
getProperty(Mastodon.HANDLE_PROP),
msg,
true
)
).contains(msg)
}
}

View file

@ -44,58 +44,58 @@ import java.lang.reflect.Method
*/
class ModuleExceptionTest {
companion object {
const val debugMessage = "debugMessage"
const val message = "message"
const val DEBUG_MESSAGE = "debugMessage"
const val MESSAGE = "message"
}
@DataProvider(name = "dp")
fun createData(@Suppress("UNUSED_PARAMETER") m: Method?): Array<Array<Any>> {
return arrayOf(
arrayOf(ModuleException(debugMessage, message, IOException("URL http://foobar.com"))),
arrayOf(ModuleException(debugMessage, message, IOException("URL http://foobar.com?"))),
arrayOf(ModuleException(debugMessage, message))
arrayOf(ModuleException(DEBUG_MESSAGE, MESSAGE, IOException("URL http://foobar.com"))),
arrayOf(ModuleException(DEBUG_MESSAGE, MESSAGE, IOException("URL http://foobar.com?"))),
arrayOf(ModuleException(DEBUG_MESSAGE, MESSAGE))
)
}
@Test(dataProvider = "dp")
fun testGetDebugMessage(e: ModuleException) {
assertThat(e::debugMessage).isEqualTo(debugMessage)
assertThat(e::debugMessage).isEqualTo(DEBUG_MESSAGE)
}
@Test(dataProvider = "dp")
fun testGetMessage(e: ModuleException) {
assertThat(e).hasMessage(message)
assertThat(e).hasMessage(MESSAGE)
}
@Test(groups = ["modules"])
fun testSanitizeMessage() {
val apiKey = "1234567890"
var e = ModuleException(debugMessage, message, IOException("URL http://foo.com?apiKey=$apiKey&userID=me"))
var e = ModuleException(DEBUG_MESSAGE, MESSAGE, IOException("URL http://foo.com?apiKey=$apiKey&userID=me"))
assertThat(
e.sanitize(apiKey, "", "me").message, "ModuleException(debugMessage, message, IOException(url))"
e.sanitize(apiKey, "", "me").message, "ModuleException(debugMessage, message, IOException(url))"
).isNotNull().all {
contains("xxxxxxxxxx", "userID=xx", "java.io.IOException")
doesNotContain(apiKey, "me")
}
e = ModuleException(debugMessage, message, null)
assertThat(e.sanitize(apiKey), "ModuleException(debugMessage, message, null)").hasMessage(message)
e = ModuleException(DEBUG_MESSAGE, MESSAGE, null)
assertThat(e.sanitize(apiKey), "ModuleException(debugMessage, message, null)").hasMessage(MESSAGE)
e = ModuleException(debugMessage, message, IOException())
assertThat(e.sanitize(apiKey), "ModuleException(debugMessage, message, IOException())").hasMessage(message)
e = ModuleException(DEBUG_MESSAGE, MESSAGE, IOException())
assertThat(e.sanitize(apiKey), "ModuleException(debugMessage, message, IOException())").hasMessage(MESSAGE)
e = ModuleException(debugMessage, apiKey)
e = ModuleException(DEBUG_MESSAGE, apiKey)
assertThat(e.sanitize(apiKey).message, "ModuleException(debugMessage, apiKey)").isNotNull()
.doesNotContain(apiKey)
.doesNotContain(apiKey)
val msg: String? = null
e = ModuleException(debugMessage, msg, IOException(msg))
e = ModuleException(DEBUG_MESSAGE, msg, IOException(msg))
assertThat(e.sanitize(apiKey).message, "ModuleException(debugMessage, msg, IOException(msg))").isNull()
e = ModuleException(debugMessage, msg, IOException("foo is $apiKey"))
e = ModuleException(DEBUG_MESSAGE, msg, IOException("foo is $apiKey"))
assertThat(
e.sanitize(" ", apiKey, "foo").message,
"ModuleException(debugMessage, msg, IOException(foo is $apiKey))"
e.sanitize(" ", apiKey, "foo").message,
"ModuleException(debugMessage, msg, IOException(foo is $apiKey))"
).isNotNull().all {
doesNotContain(apiKey)
endsWith("xxx is xxxxxxxxxx")

View file

@ -60,7 +60,7 @@ class StockQuoteTest : LocalProperties() {
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(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())
symbol = "blahfoo"

View file

@ -45,11 +45,11 @@ class WolframAlphaTest : LocalProperties() {
@Test(groups = ["modules"])
fun testAppId() {
assertFailure { queryWolfram("1 gallon to liter", appId = "DEMO") }
.isInstanceOf(ModuleException::class.java)
.hasMessage("Error 1: Invalid appid")
.isInstanceOf(ModuleException::class.java)
.hasMessage("Error 1: Invalid appid")
assertFailure { queryWolfram("1 gallon to liter", appId = "") }
.isInstanceOf(ModuleException::class.java)
.isInstanceOf(ModuleException::class.java)
}
@Test(groups = ["modules", "no-ci"])
@ -62,8 +62,8 @@ class WolframAlphaTest : LocalProperties() {
query = "SFO to LAX"
assertThat(
queryWolfram(query, WolframAlpha.METRIC, apiKey),
"queryWolfram($query)"
queryWolfram(query, WolframAlpha.METRIC, apiKey),
"queryWolfram($query)"
).contains("kilometers")
} catch (e: ModuleException) {
// Avoid displaying api key in CI logs

View file

@ -49,9 +49,9 @@ class WordTimeTest {
@Test(groups = ["modules"])
fun testTime() {
assertThat(time(), "time()").matches(
("The time is ${Colors.BOLD}\\d{1,2}:\\d{2}${Colors.BOLD} " +
"on ${Colors.BOLD}\\w+, \\d{1,2} \\w+ \\d{4}${Colors.BOLD} " +
"in ${Colors.BOLD}Los Angeles${Colors.BOLD}").toRegex()
("The time is ${Colors.BOLD}\\d{1,2}:\\d{2}${Colors.BOLD} " +
"on ${Colors.BOLD}\\w+, \\d{1,2} \\w+ \\d{4}${Colors.BOLD} " +
"in ${Colors.BOLD}Los Angeles${Colors.BOLD}").toRegex()
)
assertThat(time(""), "time()").endsWith("Los Angeles".bold())
assertThat(time("PST"), "time(PST)").endsWith("Los Angeles".bold())