Utils functions improvements.

This commit is contained in:
Erik C. Thauvin 2021-05-14 20:57:25 -07:00
parent 790bd3159e
commit 2e1c6e7732
22 changed files with 221 additions and 225 deletions

View file

@ -36,11 +36,11 @@ import net.thauvin.erik.mobibot.PinboardUtils.deletePin
import net.thauvin.erik.mobibot.PinboardUtils.updatePin
import net.thauvin.erik.mobibot.Utils.buildCmdSyntax
import net.thauvin.erik.mobibot.Utils.colorize
import net.thauvin.erik.mobibot.Utils.ensureDir
import net.thauvin.erik.mobibot.Utils.getIntProperty
import net.thauvin.erik.mobibot.Utils.helpFormat
import net.thauvin.erik.mobibot.Utils.isoLocalDate
import net.thauvin.erik.mobibot.Utils.today
import net.thauvin.erik.mobibot.Utils.toIsoLocalDate
import net.thauvin.erik.mobibot.Utils.toDir
import net.thauvin.erik.mobibot.commands.AddLog
import net.thauvin.erik.mobibot.commands.ChannelFeed
import net.thauvin.erik.mobibot.commands.Cycle
@ -546,7 +546,7 @@ class Mobibot(nickname: String, channel: String, logsDirPath: String, p: Propert
}
commandLine.hasOption(Constants.VERSION_ARG[0]) -> {
// Output the version
println("${ReleaseInfo.PROJECT} ${ReleaseInfo.VERSION} (${isoLocalDate(ReleaseInfo.BUILDDATE)})")
println("${ReleaseInfo.PROJECT} ${ReleaseInfo.VERSION} (${ReleaseInfo.BUILDDATE.toIsoLocalDate()})")
println(ReleaseInfo.WEBSITE)
}
else -> {
@ -567,7 +567,7 @@ class Mobibot(nickname: String, channel: String, logsDirPath: String, p: Propert
}
val nickname = p.getProperty("nick", Mobibot::class.java.name.lowercase())
val channel = p.getProperty("channel")
val logsDir = ensureDir(p.getProperty("logs", "."), false)
val logsDir = p.getProperty("logs", ".").toDir()
// Redirect stdout and stderr
if (!commandLine.hasOption(Constants.DEBUG_ARG[0])) {
@ -637,7 +637,7 @@ class Mobibot(nickname: String, channel: String, logsDirPath: String, p: Propert
// Set the URLs
weblogUrl = p.getProperty("weblog", "")
backlogsUrl = ensureDir(p.getProperty("backlogs", weblogUrl), true)
backlogsUrl = p.getProperty("backlogs", weblogUrl).toDir(true)
// Load the current entries and backlogs, if any
try {

View file

@ -87,7 +87,7 @@ object Utils {
* Capitalize a string.
*/
@JvmStatic
fun capitalize(s: String?): String? = s?.replaceFirstChar { it.uppercase() }
fun String.capitalise(): String = this.replaceFirstChar { it.uppercase() }
/**
* Colorize a string.
@ -115,30 +115,6 @@ object Utils {
@JvmStatic
fun encodeUrl(s: String): String = URLEncoder.encode(s, StandardCharsets.UTF_8)
/**
* Ensures that the given location (File/URL) has a trailing slash (`/`) to indicate a directory.
*/
@JvmStatic
fun ensureDir(location: String, isUrl: Boolean): String {
return if (location.isNotEmpty()) {
if (isUrl) {
if (location[location.length - 1] == '/') {
location
} else {
"$location/"
}
} else {
if (location[location.length - 1] == File.separatorChar) {
location
} else {
location + File.separatorChar
}
}
} else {
location
}
}
/**
* Returns a property as an int.
*/
@ -166,46 +142,27 @@ object Utils {
return (if (isIndent) " " else "").plus(if (isBold) bold(help) else help)
}
/**
* Returns the specified date as an ISO local date string.
*/
@JvmStatic
fun isoLocalDate(date: Date): String {
return isoLocalDate(LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault()))
}
/**
* Returns the specified date as an ISO local date string.
*/
@JvmStatic
fun isoLocalDate(date: LocalDateTime): String = date.format(DateTimeFormatter.ISO_LOCAL_DATE)
/**
* Obfuscates the given string.
*/
@JvmStatic
fun obfuscate(s: String): String {
return if (s.isNotBlank()) {
StringUtils.repeat('x', s.length)
} else s
fun String.obfuscate(): String {
return if (this.isNotBlank()) {
StringUtils.repeat('x', this.length)
} else this
}
/**
* Returns the plural form of a word, if count > 1.
*/
@JvmStatic
fun plural(count: Int, word: String, plural: String): String = plural(count.toLong(), word, plural)
fun String.plural(count: Int, plural: String): String = this.plural(count.toLong(), plural)
/**
* Returns the plural form of a word, if count > 1.
*/
@JvmStatic
fun plural(count: Long, word: String, plural: String): String {
return if (count > 1) {
plural
} else {
word
}
fun String.plural(count: Long, plural: String): String {
return if (count > 1) plural else this
}
/**
@ -224,7 +181,55 @@ object Utils {
* Returns today's date.
*/
@JvmStatic
fun today(): String = isoLocalDate(LocalDateTime.now())
fun today(): String = LocalDateTime.now().toIsoLocalDate()
/**
* Ensures that the given location (File/URL) has a trailing slash (`/`) to indicate a directory.
*/
@JvmStatic
fun String.toDir(isUrl: Boolean = false) : String {
return if (isUrl) {
if (this.last() == '/') {
this
} else {
"$this/"
}
} else {
if (this.last() == File.separatorChar) {
this
} else {
this + File.separatorChar
}
}
}
/**
* Returns the specified date as an ISO local date string.
*/
@JvmStatic
fun Date.toIsoLocalDate(): String {
return LocalDateTime.ofInstant(this.toInstant(), ZoneId.systemDefault()).toIsoLocalDate()
}
/**
* Returns the specified date as an ISO local date string.
*/
@JvmStatic
fun LocalDateTime.toIsoLocalDate(): String = this.format(DateTimeFormatter.ISO_LOCAL_DATE)
/**
* Returns the specified date formatted as `yyyy-MM-dd HH:mm`.
*/
@JvmStatic
fun Date.toUtcDateTime(): String {
return LocalDateTime.ofInstant(this.toInstant(), ZoneId.systemDefault()).toUtcDateTime()
}
/**
* Returns the specified date formatted as `yyyy-MM-dd HH:mm`.
*/
@JvmStatic
fun LocalDateTime.toUtcDateTime(): String = this.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"))
/**
* Converts XML/XHTML entities to plain text.
@ -254,21 +259,21 @@ object Utils {
)
with(info) {
if (years > 0) {
append(years).append(plural(years, " year ", " years "))
append(years).append(" year ".plural(years, " years "))
}
if (months > 0) {
append(weeks).append(plural(months, " month ", " months "))
append(weeks).append(" month ".plural(months, " months "))
}
if (weeks > 0) {
append(weeks).append(plural(weeks, " week ", " weeks "))
append(weeks).append(" week ".plural(weeks, " weeks "))
}
if (days > 0) {
append(days).append(plural(days, " day ", " days "))
append(days).append(" day ".plural(days, " days "))
}
if (hours > 0) {
append(hours).append(plural(hours, " hour ", " hours "))
append(hours).append(" hour ".plural(hours, " hours "))
}
append(minutes).append(plural(minutes, " minute", " minutes"))
append(minutes).append(" minute ".plural(minutes, " minutes"))
return toString()
}
}
@ -282,20 +287,4 @@ object Utils {
BufferedReader(InputStreamReader(url.openStream(), StandardCharsets.UTF_8))
.use { reader -> return reader.lines().collect(Collectors.joining(System.lineSeparator())) }
}
/**
* Returns the specified date formatted as `yyyy-MM-dd HH:mm`.
*/
@JvmStatic
fun utcDateTime(date: Date): String {
return utcDateTime(LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault()))
}
/**
* Returns the specified date formatted as `yyyy-MM-dd HH:mm`.
*/
@JvmStatic
fun utcDateTime(date: LocalDateTime?): String {
return date?.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm")) ?: ""
}
}

View file

@ -33,7 +33,7 @@
package net.thauvin.erik.mobibot.commands
import net.thauvin.erik.mobibot.Mobibot
import net.thauvin.erik.mobibot.Utils
import net.thauvin.erik.mobibot.Utils.buildCmdSyntax
import java.util.concurrent.ConcurrentHashMap
abstract class AbstractCommand(val bot: Mobibot) {
@ -56,7 +56,7 @@ abstract class AbstractCommand(val bot: Mobibot) {
open fun helpResponse(command: String, sender: String, isOp: Boolean, isPrivate: Boolean): Boolean {
if (!this.isOp || this.isOp == isOp) {
for (h in help) {
bot.send(sender, Utils.buildCmdSyntax(h, bot.nick, isPrivate), isPrivate)
bot.send(sender, buildCmdSyntax(h, bot.nick, isPrivate), isPrivate)
}
return true
}

View file

@ -33,7 +33,9 @@
package net.thauvin.erik.mobibot.commands
import net.thauvin.erik.mobibot.Mobibot
import net.thauvin.erik.mobibot.Utils
import net.thauvin.erik.mobibot.Utils.bold
import net.thauvin.erik.mobibot.Utils.buildCmdSyntax
import net.thauvin.erik.mobibot.Utils.helpFormat
import net.thauvin.erik.mobibot.commands.links.LinksMgr
class Ignore(bot: Mobibot) : AbstractCommand(bot) {
@ -46,17 +48,17 @@ class Ignore(bot: Mobibot) : AbstractCommand(bot) {
override val name = IGNORE_CMD
override val help = listOf(
"To ignore a link posted to the channel:",
Utils.helpFormat("https://www.foo.bar %n"),
helpFormat("https://www.foo.bar %n"),
"To check your ignore status:",
Utils.helpFormat("%c $name"),
helpFormat("%c $name"),
"To toggle your ignore status:",
Utils.helpFormat("%c $name $me")
helpFormat("%c $name $me")
)
private val helpOp = listOf(
"To ignore a link posted to the channel:",
Utils.helpFormat("https://www.foo.bar " + Utils.bold("%n"), false),
helpFormat("https://www.foo.bar " + bold("%n"), false),
"To add/remove nicks from the ignored list:",
Utils.helpFormat("%c $name <nick> [<nick> ...]")
helpFormat("%c $name <nick> [<nick> ...]")
)
override val isOp = false
@ -98,7 +100,7 @@ class Ignore(bot: Mobibot) : AbstractCommand(bot) {
): Boolean {
return if (isOp) {
for (h in helpOp) {
bot.send(sender, Utils.buildCmdSyntax(h, bot.nick, isPrivate), isPrivate)
bot.send(sender, buildCmdSyntax(h, bot.nick, isPrivate), isPrivate)
}
true
} else {
@ -143,7 +145,7 @@ class Ignore(bot: Mobibot) : AbstractCommand(bot) {
@Suppress("MagicNumber")
bot.sendList(sender, ignored.sorted(), 8, isPrivate, isIndent = true)
} else {
bot.send(sender, "No one is currently ${Utils.bold("ignored")}.", isPrivate)
bot.send(sender, "No one is currently ${bold("ignored")}.", isPrivate)
}
}

View file

@ -33,7 +33,7 @@ package net.thauvin.erik.mobibot.commands
import net.thauvin.erik.mobibot.Mobibot
import net.thauvin.erik.mobibot.ReleaseInfo
import net.thauvin.erik.mobibot.Utils.capitalize
import net.thauvin.erik.mobibot.Utils.capitalise
import net.thauvin.erik.mobibot.Utils.green
import net.thauvin.erik.mobibot.Utils.helpFormat
import net.thauvin.erik.mobibot.Utils.uptime
@ -42,8 +42,8 @@ import java.lang.management.ManagementFactory
class Info(bot: Mobibot?) : AbstractCommand(bot!!) {
private val allVersions = listOf(
capitalize(ReleaseInfo.PROJECT) + " ${ReleaseInfo.VERSION} (" + green(ReleaseInfo.WEBSITE) + ')',
"Written by ${ReleaseInfo.AUTHOR} (" + green(ReleaseInfo.AUTHOR_URL) + ')'
"${ReleaseInfo.PROJECT.capitalise()} ${ReleaseInfo.VERSION} (${green(ReleaseInfo.WEBSITE)})",
"Written by ${ReleaseInfo.AUTHOR} (${green(ReleaseInfo.AUTHOR_URL)})"
)
override val name = "info"
override val help = listOf("To view information about the bot:", helpFormat("%c $name"))

View file

@ -33,7 +33,8 @@
package net.thauvin.erik.mobibot.commands
import net.thauvin.erik.mobibot.Mobibot
import net.thauvin.erik.mobibot.Utils
import net.thauvin.erik.mobibot.Utils.toUtcDateTime
import net.thauvin.erik.mobibot.Utils.helpFormat
import java.time.Clock
import java.time.LocalDateTime
@ -41,7 +42,7 @@ class Recap(bot: Mobibot) : AbstractCommand(bot) {
override val name = "recap"
override val help = listOf(
"To list the last 10 public channel messages:",
Utils.helpFormat("%c $name")
helpFormat("%c $name")
)
override val isOp = false
override val isPublic = true
@ -57,7 +58,7 @@ class Recap(bot: Mobibot) : AbstractCommand(bot) {
@JvmStatic
fun storeRecap(sender: String, message: String, isAction: Boolean) {
recaps.add(
Utils.utcDateTime(LocalDateTime.now(Clock.systemUTC()))
LocalDateTime.now(Clock.systemUTC()).toUtcDateTime()
+ " - $sender" + (if (isAction) " " else ": ") + message
)
@Suppress("MagicNumber")

View file

@ -34,11 +34,11 @@ package net.thauvin.erik.mobibot.commands
import net.thauvin.erik.mobibot.Mobibot
import net.thauvin.erik.mobibot.ReleaseInfo
import net.thauvin.erik.mobibot.Utils.helpFormat
import net.thauvin.erik.mobibot.Utils.isoLocalDate
import net.thauvin.erik.mobibot.Utils.toIsoLocalDate
class Versions(bot: Mobibot) : AbstractCommand(bot) {
private val allVersions = listOf(
"Version: ${ReleaseInfo.VERSION} (" + isoLocalDate(ReleaseInfo.BUILDDATE) + ')',
"Version: ${ReleaseInfo.VERSION} (${ReleaseInfo.BUILDDATE.toIsoLocalDate()})",
"Platform: " + System.getProperty("os.name") + ' ' + System.getProperty("os.version")
+ " (" + System.getProperty("os.arch") + ')',
"Runtime: " + System.getProperty("java.runtime.name") + ' ' + System.getProperty("java.runtime.version")

View file

@ -34,7 +34,9 @@ package net.thauvin.erik.mobibot.commands.links
import net.thauvin.erik.mobibot.Constants
import net.thauvin.erik.mobibot.Mobibot
import net.thauvin.erik.mobibot.Utils
import net.thauvin.erik.mobibot.Utils.bold
import net.thauvin.erik.mobibot.Utils.helpFormat
import net.thauvin.erik.mobibot.Utils.today
import net.thauvin.erik.mobibot.commands.AbstractCommand
import net.thauvin.erik.mobibot.commands.Ignore
import net.thauvin.erik.mobibot.entries.EntriesMgr
@ -72,7 +74,7 @@ class LinksMgr(bot: Mobibot) : AbstractCommand(bot) {
val history = mutableListOf<String>()
@JvmStatic
var startDate: String = Utils.today()
var startDate: String = today()
private set
/**
@ -88,9 +90,9 @@ class LinksMgr(bot: Mobibot) : AbstractCommand(bot) {
@JvmStatic
fun startup(current: String, backlogs: String, channel: String) {
startDate = EntriesMgr.loadEntries(current, channel, entries)
if (Utils.today() != startDate) {
if (today() != startDate) {
entries.clear()
startDate = Utils.today()
startDate = today()
}
EntriesMgr.loadBacklogs(backlogs, history)
}
@ -144,7 +146,7 @@ class LinksMgr(bot: Mobibot) : AbstractCommand(bot) {
bot.send(sender, "Please specify a title, by typing:", isPrivate)
bot.send(
sender,
Utils.helpFormat("${EntriesUtils.buildLinkCmd(index)}:|This is the title"),
helpFormat("${EntriesUtils.buildLinkCmd(index)}:|This is the title"),
isPrivate
)
}
@ -183,7 +185,7 @@ class LinksMgr(bot: Mobibot) : AbstractCommand(bot) {
for (i in entries.indices) {
if (link == entries[i].link) {
val entry: EntryLink = entries[i]
bot.send(sender, Utils.bold("Duplicate") + " >> " + EntriesUtils.buildLink(i, entry), isPrivate)
bot.send(sender, bold("Duplicate") + " >> " + EntriesUtils.buildLink(i, entry), isPrivate)
return true
}
}
@ -201,10 +203,10 @@ class LinksMgr(bot: Mobibot) : AbstractCommand(bot) {
}
private fun saveDayBackup(bot: Mobibot): Boolean {
if (Utils.today() != startDate) {
if (today() != startDate) {
saveEntries(bot, true)
entries.clear()
startDate = Utils.today()
startDate = today()
return true
}

View file

@ -38,7 +38,7 @@ import net.thauvin.erik.mobibot.Utils.getIntProperty
import net.thauvin.erik.mobibot.Utils.helpFormat
import net.thauvin.erik.mobibot.Utils.plural
import net.thauvin.erik.mobibot.Utils.reverseColor
import net.thauvin.erik.mobibot.Utils.utcDateTime
import net.thauvin.erik.mobibot.Utils.toUtcDateTime
import net.thauvin.erik.mobibot.commands.AbstractCommand
import net.thauvin.erik.mobibot.commands.links.View
@ -117,21 +117,16 @@ class Tell(bot: Mobibot) : AbstractCommand(bot) {
*/
override val name = "tell"
override val help: List<String>
get() = listOf(
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 " + bold(maxDays)
+ plural(maxDays, " day.", " days.")
"Messages are kept for ${bold(maxDays)}" + " day.".plural(maxDays, " days.")
)
override val isOp: Boolean
get() = false
override val isPublic: Boolean
get() = isEnabled()
override val isVisible: Boolean
get() = isEnabled()
override val isOp: Boolean = false
override val isPublic: Boolean = isEnabled()
override val isVisible: Boolean = isEnabled()
override fun commandResponse(
sender: String,
@ -232,8 +227,8 @@ class Tell(bot: Mobibot) : AbstractCommand(bot) {
&& !message.isNotified) {
bot.send(
nickname,
"Your message ${reverseColor("[ID " + message.id + ']')} was sent to " +
"${bold(message.recipient)} on ${utcDateTime(message.receptionDate)}",
"Your message ${reverseColor("[ID " + message.id + ']')} was sent to "
+ "${bold(message.recipient)} on ${message.receptionDate.toUtcDateTime()}",
true
)
message.isNotified = true
@ -248,9 +243,7 @@ class Tell(bot: Mobibot) : AbstractCommand(bot) {
*
* @return The size.
*/
fun size(): Int {
return messages.size
}
fun size(): Int = messages.size
// View all messages.
private fun viewAll(sender: String, isPrivate: Boolean) {
@ -281,7 +274,7 @@ class Tell(bot: Mobibot) : AbstractCommand(bot) {
bot.send(
sender,
bold(message.sender) + ARROW + bold(message.recipient)
+ " [" + utcDateTime(message.receptionDate) + ", ID: "
+ " [${message.receptionDate.toUtcDateTime()}, ID: "
+ bold(message.id) + ", DELIVERED]",
isPrivate
)
@ -289,7 +282,7 @@ class Tell(bot: Mobibot) : AbstractCommand(bot) {
bot.send(
sender,
bold(message.sender) + ARROW + bold(message.recipient)
+ " [" + utcDateTime(message.queued) + ", ID: "
+ " [${message.queued.toUtcDateTime()}, ID: "
+ bold(message.id) + ", QUEUED]",
isPrivate
)
@ -312,11 +305,7 @@ class Tell(bot: Mobibot) : AbstractCommand(bot) {
),
isPrivate
)
bot.send(
sender,
"Messages are kept for ${bold(maxDays)}${plural(maxDays, " day.", " days.")}",
isPrivate
)
bot.send(sender, help.last(), isPrivate)
}
}

View file

@ -40,7 +40,7 @@ import com.rometools.rome.io.FeedException
import com.rometools.rome.io.SyndFeedInput
import com.rometools.rome.io.SyndFeedOutput
import net.thauvin.erik.mobibot.Mobibot
import net.thauvin.erik.mobibot.Utils.isoLocalDate
import net.thauvin.erik.mobibot.Utils.toIsoLocalDate
import java.io.IOException
import java.io.InputStreamReader
import java.io.OutputStreamWriter
@ -146,7 +146,7 @@ object EntriesMgr {
Files.newInputStream(Paths.get(file)), StandardCharsets.UTF_8
).use { reader ->
val feed = input.build(reader)
today = isoLocalDate(feed.publishedDate)
today = feed.publishedDate.toIsoLocalDate()
val items = feed.entries
var entry: EntryLink
for (i in items.indices.reversed()) {

View file

@ -33,7 +33,10 @@ package net.thauvin.erik.mobibot.modules
import net.thauvin.erik.mobibot.Constants
import net.thauvin.erik.mobibot.Mobibot
import net.thauvin.erik.mobibot.Utils
import net.thauvin.erik.mobibot.Utils.bold
import net.thauvin.erik.mobibot.Utils.buildCmdSyntax
import net.thauvin.erik.mobibot.Utils.helpFormat
import net.thauvin.erik.mobibot.Utils.today
import net.thauvin.erik.mobibot.msg.ErrorMessage
import net.thauvin.erik.mobibot.msg.Message
import net.thauvin.erik.mobibot.msg.PublicMessage
@ -56,7 +59,7 @@ class CurrencyConverter(bot: Mobibot) : ThreadedModule(bot) {
isPrivate: Boolean
) {
synchronized(this) {
if (pubDate != Utils.today()) {
if (pubDate != today()) {
EXCHANGE_RATES.clear()
}
}
@ -85,7 +88,7 @@ class CurrencyConverter(bot: Mobibot) : ThreadedModule(bot) {
helpResponse(sender, isPrivate)
}
} else if (args.contains(CURRENCY_RATES_KEYWORD)) {
send(sender, "The currency rates for ${Utils.bold(pubDate)} are:", isPrivate)
send(sender, "The currency rates for ${bold(pubDate)} are:", isPrivate)
@Suppress("MagicNumber")
sendList(sender, currencyRates(), 3, isPrivate, isIndent = true)
} else {
@ -109,16 +112,16 @@ class CurrencyConverter(bot: Mobibot) : ThreadedModule(bot) {
send(sender, "To convert from one currency to another:", isPrivate)
send(
sender,
Utils.helpFormat(
Utils.buildCmdSyntax("%c $CURRENCY_CMD 100 USD to EUR", nick, isPrivateMsgEnabled)
helpFormat(
buildCmdSyntax("%c $CURRENCY_CMD 100 USD to EUR", nick, isPrivateMsgEnabled)
),
isPrivate
)
send(sender, "For a listing of current rates:", isPrivate)
send(
sender,
Utils.helpFormat(
Utils.buildCmdSyntax("%c $CURRENCY_CMD $CURRENCY_RATES_KEYWORD", nick, isPrivateMsgEnabled)
helpFormat(
buildCmdSyntax("%c $CURRENCY_CMD $CURRENCY_RATES_KEYWORD", nick, isPrivateMsgEnabled)
),
isPrivate
)

View file

@ -32,7 +32,11 @@
package net.thauvin.erik.mobibot.modules
import net.thauvin.erik.mobibot.Mobibot
import net.thauvin.erik.mobibot.Utils
import net.thauvin.erik.mobibot.Utils.capitalise
import net.thauvin.erik.mobibot.Utils.encodeUrl
import net.thauvin.erik.mobibot.Utils.helpFormat
import net.thauvin.erik.mobibot.Utils.urlReader
import net.thauvin.erik.mobibot.Utils.unescapeXml
import net.thauvin.erik.mobibot.msg.Message
import net.thauvin.erik.mobibot.msg.NoticeMessage
import org.jibble.pircbot.Colors
@ -86,21 +90,21 @@ class GoogleSearch(bot: Mobibot) : ThreadedModule(bot) {
@Throws(ModuleException::class)
fun searchGoogle(query: String, apiKey: String?, cseKey: String?): List<Message> {
if (apiKey.isNullOrBlank() || cseKey.isNullOrBlank()) {
throw ModuleException("${Utils.capitalize(GOOGLE_CMD)} is disabled. The API keys are missing.")
throw ModuleException("${GOOGLE_CMD.capitalise()} is disabled. The API keys are missing.")
}
return if (query.isNotBlank()) {
val results = mutableListOf<Message>()
try {
val url = URL(
"https://www.googleapis.com/customsearch/v1?key=$apiKey&cx=$cseKey" +
"&q=${Utils.encodeUrl(query)}&filter=1&num=5&alt=json"
"&q=${encodeUrl(query)}&filter=1&num=5&alt=json"
)
val json = JSONObject(Utils.urlReader(url))
val json = JSONObject(urlReader(url))
val ja = json.getJSONArray("items")
for (i in 0 until ja.length()) {
val j = ja.getJSONObject(i)
results.add(NoticeMessage(Utils.unescapeXml(j.getString("title"))))
results.add(NoticeMessage(Utils.helpFormat(j.getString("link"), false), Colors.DARK_GREEN))
results.add(NoticeMessage(unescapeXml(j.getString("title"))))
results.add(NoticeMessage(helpFormat(j.getString("link"), false), Colors.DARK_GREEN))
}
} catch (e: IOException) {
throw ModuleException("searchGoogle($query)", "An IO error has occurred searching Google.", e)
@ -117,7 +121,7 @@ class GoogleSearch(bot: Mobibot) : ThreadedModule(bot) {
init {
commands.add(GOOGLE_CMD)
help.add("To search Google:")
help.add(Utils.helpFormat("%c $GOOGLE_CMD <query>"))
help.add(helpFormat("%c $GOOGLE_CMD <query>"))
initProperties(GOOGLE_API_KEY_PROP, GOOGLE_CSE_KEY_PROP)
}
}

View file

@ -32,7 +32,9 @@
package net.thauvin.erik.mobibot.modules
import net.thauvin.erik.mobibot.Mobibot
import net.thauvin.erik.mobibot.Utils
import net.thauvin.erik.mobibot.Utils.cyan
import net.thauvin.erik.mobibot.Utils.helpFormat
import net.thauvin.erik.mobibot.Utils.urlReader
import net.thauvin.erik.mobibot.msg.Message
import net.thauvin.erik.mobibot.msg.PublicMessage
import org.json.JSONException
@ -58,7 +60,7 @@ class Joke(bot: Mobibot) : ThreadedModule(bot) {
*/
override fun run(sender: String, cmd: String, args: String, isPrivate: Boolean) {
try {
bot.send(Utils.cyan(randomJoke().msg))
bot.send(cyan(randomJoke().msg))
} catch (e: ModuleException) {
if (bot.logger.isWarnEnabled) bot.logger.warn(e.debugMessage, e)
bot.send(sender, e.message, isPrivate)
@ -81,7 +83,7 @@ class Joke(bot: Mobibot) : ThreadedModule(bot) {
fun randomJoke(): Message {
return try {
val url = URL(JOKE_URL)
val json = JSONObject(Utils.urlReader(url))
val json = JSONObject(urlReader(url))
PublicMessage(
json.getJSONObject("value")["joke"].toString().replace("\\'", "'")
.replace("\\\"", "\"")
@ -97,6 +99,6 @@ class Joke(bot: Mobibot) : ThreadedModule(bot) {
init {
commands.add(JOKE_CMD)
help.add("To retrieve a random joke:")
help.add(Utils.helpFormat("%c $JOKE_CMD"))
help.add(helpFormat("%c $JOKE_CMD"))
}
}

View file

@ -68,7 +68,7 @@ class ModuleException : Exception {
* Return the sanitized message (e.g. remove API keys, etc.)
*/
fun getSanitizedMessage(vararg sanitize: String): String {
val obfuscate = sanitize.map { obfuscate(it) }.toTypedArray()
val obfuscate = sanitize.map { it.obfuscate() }.toTypedArray()
return when {
cause != null -> {
cause.javaClass.name + ": " + StringUtils.replaceEach(cause.message, sanitize, obfuscate)

View file

@ -33,7 +33,10 @@
package net.thauvin.erik.mobibot.modules
import net.thauvin.erik.mobibot.Mobibot
import net.thauvin.erik.mobibot.Utils
import net.thauvin.erik.mobibot.Utils.bold
import net.thauvin.erik.mobibot.Utils.green
import net.thauvin.erik.mobibot.Utils.helpFormat
import net.thauvin.erik.mobibot.Utils.red
import kotlin.random.Random
@ -51,7 +54,7 @@ class RockPaperScissors(bot: Mobibot) : AbstractModule(bot) {
with(help) {
add("To play Rock Paper Scissors:")
add(
Utils.helpFormat(
helpFormat(
"%c ${Hands.ROCK.name.lowercase()} | ${Hands.PAPER.name.lowercase()}"
+ " | ${Hands.SCISSORS.name.lowercase()}"
)
@ -99,15 +102,15 @@ class RockPaperScissors(bot: Mobibot) : AbstractModule(bot) {
with(bot) {
when {
hand == botHand -> {
send("${Utils.green(hand.name)} vs. ${Utils.green(botHand.name)}")
send("${green(hand.name)} vs. ${green(botHand.name)}")
action("tied.")
}
hand.beats(botHand) -> {
send("${Utils.green(hand.name)} ${Utils.bold(hand.action)} ${Utils.red(botHand.name)}")
send("${green(hand.name)} ${bold(hand.action)} ${red(botHand.name)}")
action("lost.")
}
else -> {
send("${Utils.green(botHand.name)} ${Utils.bold(botHand.action)} ${Utils.red(hand.name)}")
send("${green(botHand.name)} ${bold(botHand.action)} ${red(hand.name)}")
action("wins.")
}
}

View file

@ -32,7 +32,11 @@
package net.thauvin.erik.mobibot.modules
import net.thauvin.erik.mobibot.Mobibot
import net.thauvin.erik.mobibot.Utils
import net.thauvin.erik.mobibot.Utils.capitalise
import net.thauvin.erik.mobibot.Utils.encodeUrl
import net.thauvin.erik.mobibot.Utils.helpFormat
import net.thauvin.erik.mobibot.Utils.unescapeXml
import net.thauvin.erik.mobibot.Utils.urlReader
import net.thauvin.erik.mobibot.msg.ErrorMessage
import net.thauvin.erik.mobibot.msg.Message
import net.thauvin.erik.mobibot.msg.NoticeMessage
@ -91,7 +95,7 @@ class StockQuote(bot: Mobibot) : ThreadedModule(bot) {
try {
val info = json.getString("Information")
if (info.isNotEmpty()) {
throw ModuleException(debugMessage, Utils.unescapeXml(info))
throw ModuleException(debugMessage, unescapeXml(info))
}
} catch (ignore: JSONException) {
// Do nothing
@ -99,11 +103,11 @@ class StockQuote(bot: Mobibot) : ThreadedModule(bot) {
try {
var error = json.getString("Note")
if (error.isNotEmpty()) {
throw ModuleException(debugMessage, Utils.unescapeXml(error))
throw ModuleException(debugMessage, unescapeXml(error))
}
error = json.getString("Error Message")
if (error.isNotEmpty()) {
throw ModuleException(debugMessage, Utils.unescapeXml(error))
throw ModuleException(debugMessage, unescapeXml(error))
}
} catch (ignore: JSONException) {
// Do nothing
@ -122,7 +126,7 @@ class StockQuote(bot: Mobibot) : ThreadedModule(bot) {
fun getQuote(symbol: String, apiKey: String?): List<Message> {
if (apiKey.isNullOrBlank()) {
throw ModuleException(
"${Utils.capitalize(STOCK_CMD)} is disabled. The API key is missing."
"${STOCK_CMD.capitalise()} is disabled. The API key is missing."
)
}
return if (symbol.isNotBlank()) {
@ -132,10 +136,10 @@ class StockQuote(bot: Mobibot) : ThreadedModule(bot) {
try {
with(messages) {
// Search for symbol/keywords
response = Utils.urlReader(
response = urlReader(
URL(
"${ALPHAVANTAGE_URL}SYMBOL_SEARCH&keywords=" + Utils.encodeUrl(symbol)
+ "&apikey=" + Utils.encodeUrl(apiKey)
"${ALPHAVANTAGE_URL}SYMBOL_SEARCH&keywords=" + encodeUrl(symbol)
+ "&apikey=" + encodeUrl(apiKey)
)
)
var json = getJsonResponse(response, debugMessage)
@ -146,11 +150,11 @@ class StockQuote(bot: Mobibot) : ThreadedModule(bot) {
val symbolInfo = symbols.getJSONObject(0)
// Get quote for symbol
response = Utils.urlReader(
response = urlReader(
URL(
"${ALPHAVANTAGE_URL}GLOBAL_QUOTE&symbol="
+ Utils.encodeUrl(symbolInfo.getString("1. symbol"))
+ "&apikey=" + Utils.encodeUrl(apiKey)
+ encodeUrl(symbolInfo.getString("1. symbol"))
+ "&apikey=" + encodeUrl(apiKey)
)
)
json = getJsonResponse(response, debugMessage)
@ -161,34 +165,28 @@ class StockQuote(bot: Mobibot) : ThreadedModule(bot) {
}
add(
PublicMessage(
"Symbol: " + Utils.unescapeXml(quote.getString("01. symbol"))
+ " [" + Utils.unescapeXml(symbolInfo.getString("2. name")) + ']'
"Symbol: " + unescapeXml(quote.getString("01. symbol"))
+ " [" + unescapeXml(symbolInfo.getString("2. name")) + ']'
)
)
add(PublicMessage(" Price: " + Utils.unescapeXml(quote.getString("05. price"))))
add(PublicMessage(" Price: " + unescapeXml(quote.getString("05. price"))))
add(
PublicMessage(
" Previous: " + Utils.unescapeXml(quote.getString("08. previous close"))
" Previous: " + unescapeXml(quote.getString("08. previous close"))
)
)
add(NoticeMessage(" Open: " + Utils.unescapeXml(quote.getString("02. open"))))
add(NoticeMessage(" High: " + Utils.unescapeXml(quote.getString("03. high"))))
add(NoticeMessage(" Low: " + Utils.unescapeXml(quote.getString("04. low"))))
add(
NoticeMessage(
" Volume: " + Utils.unescapeXml(quote.getString("06. volume"))
add(NoticeMessage(" Open: " + unescapeXml(quote.getString("02. open"))))
add(NoticeMessage(" High: " + unescapeXml(quote.getString("03. high"))))
add(NoticeMessage(" Low: " + unescapeXml(quote.getString("04. low"))))
add(NoticeMessage(" Volume: " + unescapeXml(quote.getString("06. volume"))))
add(NoticeMessage(
" Latest: " + unescapeXml(quote.getString("07. latest trading day"))
)
)
add(
NoticeMessage(
" Latest: "
+ Utils.unescapeXml(quote.getString("07. latest trading day"))
)
)
add(
NoticeMessage(
" Change: " + Utils.unescapeXml(quote.getString("09. change")) + " ["
+ Utils.unescapeXml(quote.getString("10. change percent")) + ']'
" Change: " + unescapeXml(quote.getString("09. change")) + " ["
+ unescapeXml(quote.getString("10. change percent")) + ']'
)
)
}
@ -208,7 +206,7 @@ class StockQuote(bot: Mobibot) : ThreadedModule(bot) {
init {
commands.add(STOCK_CMD)
help.add("To retrieve a stock quote:")
help.add(Utils.helpFormat("%c $STOCK_CMD <symbol|keywords>"))
help.add(helpFormat("%c $STOCK_CMD <symbol|keywords>"))
initProperties(ALPHAVANTAGE_API_KEY_PROP)
}
}

View file

@ -36,7 +36,10 @@ import net.aksingh.owmjapis.core.OWM
import net.aksingh.owmjapis.core.OWM.Country
import net.aksingh.owmjapis.model.CurrentWeather
import net.thauvin.erik.mobibot.Mobibot
import net.thauvin.erik.mobibot.Utils
import net.thauvin.erik.mobibot.Utils.capitalise
import net.thauvin.erik.mobibot.Utils.bold
import net.thauvin.erik.mobibot.Utils.encodeUrl
import net.thauvin.erik.mobibot.Utils.helpFormat
import net.thauvin.erik.mobibot.msg.ErrorMessage
import net.thauvin.erik.mobibot.msg.Message
import net.thauvin.erik.mobibot.msg.NoticeMessage
@ -102,7 +105,7 @@ class Weather2(bot: Mobibot) : ThreadedModule(bot) {
fun getWeather(query: String, apiKey: String?): List<Message> {
if (apiKey.isNullOrBlank()) {
throw ModuleException(
"${Utils.capitalize(WEATHER_CMD)} is disabled. The API key is missing."
"${WEATHER_CMD.capitalise()} is disabled. The API key is missing."
)
}
val owm = OWM(apiKey)
@ -151,7 +154,7 @@ class Weather2(bot: Mobibot) : ThreadedModule(bot) {
for (w in list) {
if (w != null) {
condition.append(' ')
.append(Utils.capitalize(w.getDescription()))
.append(w.getDescription().capitalise())
.append('.')
}
}
@ -167,7 +170,7 @@ class Weather2(bot: Mobibot) : ThreadedModule(bot) {
messages.add(
NoticeMessage(
"https://openweathermap.org/find?q="
+ Utils.encodeUrl("$city,${country.uppercase()}"),
+ encodeUrl("$city,${country.uppercase()}"),
Colors.GREEN
)
)
@ -197,10 +200,10 @@ class Weather2(bot: Mobibot) : ThreadedModule(bot) {
init {
commands.add(WEATHER_CMD)
help.add("To display weather information:")
help.add(Utils.helpFormat("%c $WEATHER_CMD <city> [, <country code>]"))
help.add(helpFormat("%c $WEATHER_CMD <city> [, <country code>]"))
help.add("For example:")
help.add(Utils.helpFormat("%c $WEATHER_CMD paris, fr"))
help.add("The default ISO 3166 country code is ${Utils.bold("US")}. Zip codes supported in most countries.")
help.add(helpFormat("%c $WEATHER_CMD paris, fr"))
help.add("The default ISO 3166 country code is ${bold("US")}. Zip codes supported in most countries.")
initProperties(OWM_API_KEY_PROP)
}
}

View file

@ -77,7 +77,7 @@ class WorldTime(bot: Mobibot) : AbstractModule(bot) {
val tz = COUNTRIES_MAP[(query.substring(query.indexOf(' ') + 1).trim()).uppercase()]
val response: String = if (tz != null) {
if (BEATS_KEYWORD == tz) {
"The current Internet Time is: " + bold(internetTime() + ' ' + BEATS_KEYWORD)
"The current Internet Time is: ${bold(internetTime())} $BEATS_KEYWORD"
} else {
(ZonedDateTime.now()
.withZoneSameInstant(ZoneId.of(tz))
@ -215,7 +215,7 @@ class WorldTime(bot: Mobibot) : AbstractModule(bot) {
init {
help.add("To display a country's current date/time:")
help.add(helpFormat("%c $TIME_CMD") + " [<country code>]")
help.add(helpFormat("%c $TIME_CMD [<country code>]"))
help.add("For a listing of the supported countries:")
help.add(helpFormat("%c $TIME_CMD"))
commands.add(TIME_CMD)

View file

@ -35,18 +35,18 @@ import net.thauvin.erik.mobibot.Utils.bold
import net.thauvin.erik.mobibot.Utils.capitalize
import net.thauvin.erik.mobibot.Utils.colorize
import net.thauvin.erik.mobibot.Utils.cyan
import net.thauvin.erik.mobibot.Utils.ensureDir
import net.thauvin.erik.mobibot.Utils.getIntProperty
import net.thauvin.erik.mobibot.Utils.green
import net.thauvin.erik.mobibot.Utils.isoLocalDate
import net.thauvin.erik.mobibot.Utils.obfuscate
import net.thauvin.erik.mobibot.Utils.plural
import net.thauvin.erik.mobibot.Utils.reverseColor
import net.thauvin.erik.mobibot.Utils.toDir
import net.thauvin.erik.mobibot.Utils.toIsoLocalDate
import net.thauvin.erik.mobibot.Utils.toUtcDateTime
import net.thauvin.erik.mobibot.Utils.today
import net.thauvin.erik.mobibot.Utils.unescapeXml
import net.thauvin.erik.mobibot.Utils.uptime
import net.thauvin.erik.mobibot.Utils.urlReader
import net.thauvin.erik.mobibot.Utils.utcDateTime
import org.apache.commons.lang3.StringUtils
import org.assertj.core.api.Assertions.assertThat
import org.jibble.pircbot.Colors
@ -101,13 +101,6 @@ class UtilsTest {
assertThat(cyan(ascii)).isEqualTo(Colors.CYAN + ascii + Colors.NORMAL)
}
@Test
fun testEnsureDir() {
assertThat(ensureDir("dir", false)).describedAs("ensureDir(dir, false)").isEqualTo("dir" + File.separatorChar)
assertThat(ensureDir("https://erik.thauvin.net", true)).describedAs("ensureDir(erik.thauvin.net, true)")
.isEqualTo("https://erik.thauvin.net/")
}
@Test
fun testGetIntProperty() {
assertThat(getIntProperty("10", 1)).describedAs("getIntProperty(10, 1)").isEqualTo(10)
@ -121,25 +114,25 @@ class UtilsTest {
@Test
fun testIsoLocalDate() {
assertThat(isoLocalDate(cal.time)).describedAs("isoLocalDate(date)").isEqualTo("1952-02-17")
assertThat(isoLocalDate(localDateTime)).describedAs("isoLocalDate(localDate)").isEqualTo("1952-02-17")
assertThat(cal.time.toIsoLocalDate()).describedAs("isoLocalDate(date)").isEqualTo("1952-02-17")
assertThat(localDateTime.toIsoLocalDate()).describedAs("isoLocalDate(localDate)").isEqualTo("1952-02-17")
}
@Test
fun testObfuscate() {
assertThat(obfuscate(ascii).length).describedAs("obfuscate is right length").isEqualTo(ascii.length)
assertThat(obfuscate(ascii)).describedAs("obfuscate()").isEqualTo(StringUtils.repeat("x", ascii.length))
assertThat(obfuscate(" ")).describedAs("obfuscate(blank)").isEqualTo(" ")
assertThat(ascii.obfuscate().length).describedAs("obfuscate is right length").isEqualTo(ascii.length)
assertThat(ascii.obfuscate()).describedAs("obfuscate()").isEqualTo(StringUtils.repeat("x", ascii.length))
assertThat(" ".obfuscate()).describedAs("obfuscate(blank)").isEqualTo(" ")
}
@Test
fun testPlural() {
val week = "week"
val weeks = "weeks"
assertThat(plural(-1, week, weeks)).describedAs("plural(-1)").isEqualTo(week)
assertThat(plural(0, week, weeks)).describedAs("plural(0)").isEqualTo(week)
assertThat(plural(1, week, weeks)).describedAs("plural(1)").isEqualTo(week)
assertThat(plural(2, week, weeks)).describedAs("plural(2)").isEqualTo(weeks)
assertThat(week.plural(-1, weeks)).describedAs("plural(-1)").isEqualTo(week)
assertThat(week.plural(0, weeks)).describedAs("plural(0)").isEqualTo(week)
assertThat(week.plural(1, weeks)).describedAs("plural(1)").isEqualTo(week)
assertThat(week.plural(2, weeks)).describedAs("plural(2)").isEqualTo(weeks)
}
@Test
@ -149,7 +142,14 @@ class UtilsTest {
@Test
fun testToday() {
assertThat(today()).isEqualTo(isoLocalDate(LocalDateTime.now()))
assertThat(today()).isEqualTo(LocalDateTime.now().toIsoLocalDate())
}
@Test
fun testToDir() {
assertThat("dir".toDir(false)).describedAs("toDir(dir, false)").isEqualTo("dir" + File.separatorChar)
assertThat("https://erik.thauvin.net".toDir(true)).describedAs("toDir(erik.thauvin.net, true)")
.isEqualTo("https://erik.thauvin.net/")
}
@Test
@ -174,7 +174,7 @@ class UtilsTest {
@Test
fun testUtcDateTime() {
assertThat(utcDateTime(cal.time)).describedAs("utcDateTime(date)").isEqualTo("1952-02-17 12:30")
assertThat(utcDateTime(localDateTime)).describedAs("utcDateTime(localDate)").isEqualTo("1952-02-17 12:30")
assertThat(cal.time.toUtcDateTime()).describedAs("utcDateTime(date)").isEqualTo("1952-02-17 12:30")
assertThat(localDateTime.toUtcDateTime()).describedAs("utcDateTime(localDate)").isEqualTo("1952-02-17 12:30")
}
}

View file

@ -32,7 +32,7 @@
package net.thauvin.erik.mobibot.modules
import net.objecthunter.exp4j.tokenizer.UnknownFunctionOrVariableException
import net.thauvin.erik.mobibot.Utils
import net.thauvin.erik.mobibot.Utils.bold
import net.thauvin.erik.mobibot.modules.Calc.Companion.calculate
import org.assertj.core.api.Assertions.assertThat
import org.assertj.core.api.Assertions.assertThatThrownBy
@ -44,10 +44,10 @@ import org.testng.annotations.Test
class CalcTest {
@Test
fun testCalculate() {
assertThat(calculate("1 + 1")).describedAs("calculate(1+1)").isEqualTo("1+1 = %s", Utils.bold(2))
assertThat(calculate("1 -3")).describedAs("calculate(1 -3)").isEqualTo("1-3 = %s", Utils.bold(-2))
assertThat(calculate("1 + 1")).describedAs("calculate(1+1)").isEqualTo("1+1 = %s", bold(2))
assertThat(calculate("1 -3")).describedAs("calculate(1 -3)").isEqualTo("1-3 = %s", bold(-2))
assertThat(calculate("pi+π+e+φ")).describedAs("calculate(pi+π+e+φ)")
.isEqualTo("pi+π+e+φ = %s", Utils.bold("10.62"))
.isEqualTo("pi+π+e+φ = %s", bold("10.62"))
assertThatThrownBy { calculate("one + one") }.describedAs("calculate(one+one)")
.isInstanceOf(UnknownFunctionOrVariableException::class.java)
}

View file

@ -31,7 +31,7 @@
*/
package net.thauvin.erik.mobibot.modules
import net.thauvin.erik.mobibot.Utils
import net.thauvin.erik.mobibot.Utils.bold
import net.thauvin.erik.mobibot.modules.WorldTime.Companion.time
import org.assertj.core.api.Assertions.assertThat
import org.testng.annotations.Test
@ -42,7 +42,7 @@ import org.testng.annotations.Test
class WordTimeTest {
@Test
fun testTime() {
assertThat(time("PST").msg).describedAs("PST").endsWith(Utils.bold("Los Angeles"))
assertThat(time("PST").msg).describedAs("PST").endsWith(bold("Los Angeles"))
assertThat(time("BLAH").isError).describedAs("BLAH").isTrue
assertThat(time("BEATS").msg).describedAs("BEATS").contains("@")
}

View file

@ -1,9 +1,9 @@
#Generated by the Semver Plugin for Gradle
#Thu May 13 21:34:31 PDT 2021
version.buildmeta=771
#Fri May 14 20:13:13 PDT 2021
version.buildmeta=782
version.major=0
version.minor=8
version.patch=0
version.prerelease=beta
version.project=mobibot
version.semver=0.8.0-beta+771
version.semver=0.8.0-beta+782