Implemented appendIfMissing and replaceEach extension functions to remove dependencies on StringUtils.

This commit is contained in:
Erik C. Thauvin 2021-07-30 01:19:31 -07:00
parent d8930a9520
commit 1535290290
7 changed files with 143 additions and 74 deletions

View file

@ -34,11 +34,11 @@ package net.thauvin.erik.mobibot
import net.thauvin.erik.mobibot.PinboardUtils.addPin
import net.thauvin.erik.mobibot.PinboardUtils.deletePin
import net.thauvin.erik.mobibot.PinboardUtils.updatePin
import net.thauvin.erik.mobibot.Utils.appendIfMissing
import net.thauvin.erik.mobibot.Utils.buildCmdSyntax
import net.thauvin.erik.mobibot.Utils.colorize
import net.thauvin.erik.mobibot.Utils.getIntProperty
import net.thauvin.erik.mobibot.Utils.helpFormat
import net.thauvin.erik.mobibot.Utils.toDir
import net.thauvin.erik.mobibot.Utils.toIsoLocalDate
import net.thauvin.erik.mobibot.Utils.today
import net.thauvin.erik.mobibot.commands.AddLog
@ -95,6 +95,7 @@ import org.apache.logging.log4j.LogManager
import org.apache.logging.log4j.Logger
import org.jibble.pircbot.PircBot
import java.io.BufferedOutputStream
import java.io.File
import java.io.FileNotFoundException
import java.io.FileOutputStream
import java.io.IOException
@ -586,7 +587,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 = p.getProperty("logs", ".").toDir()
val logsDir = p.getProperty("logs", ".").appendIfMissing(File.separatorChar)
// Redirect stdout and stderr
if (!commandLine.hasOption(Constants.DEBUG_ARG[0])) {
@ -656,14 +657,14 @@ class Mobibot(nickname: String, channel: String, logsDirPath: String, p: Propert
// Set the URLs
weblogUrl = p.getProperty("weblog", "")
backlogsUrl = p.getProperty("backlogs", weblogUrl).toDir(true)
backlogsUrl = p.getProperty("backlogs", weblogUrl).appendIfMissing('/')
// Load the current entries and backlogs, if any
try {
LinksMgr.startup(logsDir + EntriesMgr.CURRENT_XML, logsDir + EntriesMgr.NAV_XML, this.channel)
if (logger.isDebugEnabled) logger.debug("Last feed: ${LinksMgr.startDate}")
} catch (e: Exception) {
logger.error("An error occurred while loading the logs.", e)
if (logger.isErrorEnabled) logger.error("An error occurred while loading the logs.", e)
}
// Set the pinboard authentication

View file

@ -31,7 +31,6 @@
*/
package net.thauvin.erik.mobibot
import org.apache.commons.lang3.StringUtils
import org.jibble.pircbot.Colors
import org.jsoup.Jsoup
import java.io.BufferedReader
@ -56,6 +55,18 @@ import java.util.stream.Collectors
object Utils {
private val searchFlags = arrayOf("%c", "%n")
/**
* Appends a suffix to the end of the String if not present.
*/
@JvmStatic
fun String.appendIfMissing(suffix: Char) : String {
return if (this.last() != suffix) {
"$this${suffix}"
} else {
this
}
}
/**
* Makes the given int bold.
*/
@ -81,7 +92,7 @@ object Utils {
@JvmStatic
fun buildCmdSyntax(text: String, botNick: String, isPrivate: Boolean): String {
val replace = arrayOf(if (isPrivate) "/msg $botNick" else "$botNick:", botNick)
return StringUtils.replaceEach(text, searchFlags, replace)
return text.replaceEach(searchFlags, replace)
}
/**
@ -95,7 +106,7 @@ object Utils {
*/
@JvmStatic
fun colorize(s: String?, color: String): String {
return if (s.isNullOrBlank()) {
return if (s.isNullOrEmpty()) {
Colors.NORMAL
} else if (Colors.BOLD == color || Colors.REVERSE == color) {
color + s + color
@ -136,7 +147,8 @@ object Utils {
@JvmStatic
@JvmOverloads
fun helpFormat(help: String, isBold: Boolean = true, isIndent: Boolean = true): String {
return (if (isIndent) " " else "").plus(if (isBold) bold(help) else help)
val s = if (isBold) bold(help) else help
return if (isIndent) s.prependIndent() else s
}
/**
@ -145,21 +157,16 @@ object Utils {
@JvmStatic
fun String.obfuscate(): String {
return if (this.isNotBlank()) {
StringUtils.repeat('x', this.length)
"x".repeat(this.length)
} else this
}
/**
* Returns the plural form of a word, if count > 1.
*/
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 String.plural(count: Long, plural: String): String {
return if (count > 1) plural else this
fun String.plural(count: Long): String {
return if (count > 1) "${this}s" else this
}
/**
@ -168,6 +175,20 @@ object Utils {
@JvmStatic
fun red(s: String?): String = colorize(s, Colors.RED)
/**
* Replaces all occurrences of Strings within another String.
*/
@JvmStatic
fun String.replaceEach(search: Array<out String>, replace: Array<out String>): String {
var result = this
if (search.size == replace.size) {
search.forEachIndexed { i, s ->
result = result.replace(s, replace[i])
}
}
return result
}
/**
* Makes the given string reverse color.
*/
@ -180,26 +201,6 @@ object Utils {
@JvmStatic
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
}
}
}
/**
* Converts a string to an int.
*/
@ -266,21 +267,23 @@ object Utils {
with(info) {
if (years > 0) {
append(years).append(" year ".plural(years, " years "))
append(years).append(" year".plural(years)).append(' ')
}
if (months > 0) {
append(weeks).append(" month ".plural(months, " months "))
append(weeks).append(" month".plural(months)).append(' ')
}
if (weeks > 0) {
append(weeks).append(" week ".plural(weeks, " weeks "))
append(weeks).append(" week".plural(weeks)).append(' ')
}
if (days > 0) {
append(days).append(" day ".plural(days, " days "))
append(days).append(" day".plural(days)).append(' ')
}
if (hours > 0) {
append(hours).append(" hour ".plural(hours, " hours "))
append(hours).append(" hour".plural(hours)).append(' ')
}
append(minutes).append(" minute ".plural(minutes, " minutes"))
append(minutes).append(" minute".plural(minutes))
return toString()
}
}

View file

@ -122,7 +122,7 @@ class Tell(bot: Mobibot) : AbstractCommand(bot) {
helpFormat("%c $name <nick> <message>"),
"To view queued and sent messages:",
helpFormat("%c $name ${View.VIEW_CMD}"),
"Messages are kept for ${bold(maxDays)}" + " day.".plural(maxDays, " days.")
"Messages are kept for ${bold(maxDays)}" + " day".plural(maxDays.toLong()) + '.'
)
override val isOp: Boolean = false
override val isPublic: Boolean = isEnabled()

View file

@ -34,7 +34,6 @@ package net.thauvin.erik.mobibot.entries
import com.rometools.rome.feed.synd.SyndCategory
import com.rometools.rome.feed.synd.SyndCategoryImpl
import net.thauvin.erik.mobibot.commands.links.LinksMgr
import org.apache.commons.lang3.StringUtils
import java.io.Serializable
import java.util.Calendar
import java.util.Date
@ -144,9 +143,11 @@ class EntryLink : Serializable {
* Returns true if a string is contained in the link, title, or nick.
*/
fun matches(match: String?): Boolean {
return (StringUtils.containsIgnoreCase(link, match)
|| StringUtils.containsIgnoreCase(title, match)
|| StringUtils.containsIgnoreCase(nick, match))
return if (match.isNullOrEmpty()) {
false
} else {
link.contains(match, true) || title.contains(match, true) || nick.contains(match, true)
}
}
/**

View file

@ -40,7 +40,6 @@ 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
import org.apache.commons.lang3.StringUtils
import org.jdom2.JDOMException
import org.jdom2.input.SAXBuilder
import java.io.IOException
@ -193,7 +192,7 @@ class CurrencyConverter(bot: Mobibot) : ThreadedModule(bot) {
val rates = mutableListOf<String>()
for ((key, value) in EXCHANGE_RATES) {
@Suppress("MagicNumber")
rates.add(" $key: ${StringUtils.leftPad(value, 8)}")
rates.add(" $key: ${value.padStart(8)}")
}
return rates
}

View file

@ -32,7 +32,7 @@
package net.thauvin.erik.mobibot.modules
import net.thauvin.erik.mobibot.Utils.obfuscate
import org.apache.commons.lang3.StringUtils
import net.thauvin.erik.mobibot.Utils.replaceEach
/**
* The `ModuleException` class.
@ -70,11 +70,11 @@ class ModuleException : Exception {
fun getSanitizedMessage(vararg sanitize: String): String {
val obfuscate = sanitize.map { it.obfuscate() }.toTypedArray()
return when {
cause != null -> {
cause.javaClass.name + ": " + StringUtils.replaceEach(cause.message, sanitize, obfuscate)
cause?.message != null -> {
cause.javaClass.name + ": " + cause.message!!.replaceEach(sanitize, obfuscate)
}
message != null -> {
message.javaClass.name + ": " + StringUtils.replaceEach(message, sanitize, obfuscate)
message.javaClass.name + ": " + message.replaceEach(sanitize, obfuscate)
}
else -> ""
}

View file

@ -31,16 +31,21 @@
*/
package net.thauvin.erik.mobibot
import net.thauvin.erik.mobibot.Utils.appendIfMissing
import net.thauvin.erik.mobibot.Utils.bold
import net.thauvin.erik.mobibot.Utils.buildCmdSyntax
import net.thauvin.erik.mobibot.Utils.capitalise
import net.thauvin.erik.mobibot.Utils.colorize
import net.thauvin.erik.mobibot.Utils.cyan
import net.thauvin.erik.mobibot.Utils.encodeUrl
import net.thauvin.erik.mobibot.Utils.getIntProperty
import net.thauvin.erik.mobibot.Utils.green
import net.thauvin.erik.mobibot.Utils.helpFormat
import net.thauvin.erik.mobibot.Utils.obfuscate
import net.thauvin.erik.mobibot.Utils.plural
import net.thauvin.erik.mobibot.Utils.red
import net.thauvin.erik.mobibot.Utils.replaceEach
import net.thauvin.erik.mobibot.Utils.reverseColor
import net.thauvin.erik.mobibot.Utils.toDir
import net.thauvin.erik.mobibot.Utils.toIntOrDefault
import net.thauvin.erik.mobibot.Utils.toIsoLocalDate
import net.thauvin.erik.mobibot.Utils.toUtcDateTime
@ -48,7 +53,6 @@ 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 org.apache.commons.lang3.StringUtils
import org.assertj.core.api.Assertions.assertThat
import org.jibble.pircbot.Colors
import org.testng.annotations.BeforeClass
@ -68,24 +72,47 @@ class UtilsTest {
" !\"#$%&'()*+,-./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."
@BeforeClass
fun setUp() {
cal[1952, Calendar.FEBRUARY, 17, 12, 30] = 0
}
@Test
fun testAppendIfMissing() {
val dir = "dir"
val sep = '/'
val url = "https://erik.thauvin.net"
assertThat(dir.appendIfMissing(File.separatorChar)).describedAs("appendIfMissing(dir)")
.isEqualTo(dir + File.separatorChar)
assertThat(url.appendIfMissing(sep)).describedAs("appendIfMissing(url)").isEqualTo("$url$sep")
assertThat("$url$sep".appendIfMissing(sep)).describedAs("appendIfMissing($url$sep)").isEqualTo("$url$sep")
}
@Test
fun testBold() {
assertThat(bold(1)).describedAs("bold(1)").isEqualTo(Colors.BOLD + "1" + Colors.BOLD)
assertThat(bold(2L)).describedAs("bold(1)").isEqualTo(Colors.BOLD + "2" + Colors.BOLD)
assertThat(bold(ascii)).describedAs("bold(ascii)").isEqualTo(Colors.BOLD + ascii + Colors.BOLD)
assertThat(bold("test")).describedAs("bold(test)").isEqualTo(Colors.BOLD + "test" + Colors.BOLD)
}
@Test
fun testBuildCmdSyntax() {
val bot = "mobibot"
assertThat(buildCmdSyntax("%c $test %n $test", bot, false)).describedAs("public")
.isEqualTo("$bot: $test $bot $test")
assertThat(buildCmdSyntax("%c %n $test %c $test %n", bot, true)).describedAs("public")
.isEqualTo("/msg $bot $bot $test /msg $bot $test $bot")
}
@Test
fun testCapitalise() {
assertThat("test".capitalise()).describedAs("capitalize(test)").isEqualTo("Test")
assertThat("Test".capitalise()).describedAs("capitalize(Test)").isEqualTo("Test")
assertThat(test.capitalise()).describedAs("capitalize($test)").isEqualTo(test)
assertThat("".capitalise()).describedAs("capitalize()").isEqualTo("")
}
@ -99,6 +126,8 @@ class UtilsTest {
assertThat(colorize(ascii, Colors.BOLD)).describedAs("colorized(bold)")
.isEqualTo(Colors.BOLD + ascii + Colors.BOLD)
assertThat(colorize(null, Colors.RED)).describedAs("colorize(null)").isEqualTo(Colors.NORMAL)
assertThat(colorize("", Colors.RED)).describedAs("colorize()").isEqualTo(Colors.NORMAL)
}
@Test
@ -106,13 +135,19 @@ class UtilsTest {
assertThat(cyan(ascii)).isEqualTo(Colors.CYAN + ascii + Colors.NORMAL)
}
@Test
fun testEncodeUrl() {
assertThat(encodeUrl("Hello Günter")).isEqualTo("Hello+G%C3%BCnter")
}
@Test
fun testGetIntProperty() {
val p = Properties()
p["one"] = "1"
p["two"] = "foo"
assertThat(p.getIntProperty("one", 1)).describedAs("getIntProperty(one)").isEqualTo(1)
p["two"] = "two"
assertThat(p.getIntProperty("one", 9)).describedAs("getIntProperty(one)").isEqualTo(1)
assertThat(p.getIntProperty("two", 2)).describedAs("getIntProperty(two)").isEqualTo(2)
assertThat(p.getIntProperty("foo", 3)).describedAs("getIntProperty(foo)").isEqualTo(3)
}
@Test
@ -120,6 +155,17 @@ class UtilsTest {
assertThat(green(ascii)).isEqualTo(Colors.DARK_GREEN + ascii + Colors.NORMAL)
}
@Test
fun testHelpFormat() {
assertThat(helpFormat(test, isBold = true, isIndent = false)).describedAs("bold")
.isEqualTo("${Colors.BOLD}$test${Colors.BOLD}")
assertThat(helpFormat(test, isBold = false, isIndent = true)).describedAs("indent")
.isEqualTo(test.prependIndent())
assertThat(helpFormat(test, isBold = true, isIndent = true)).describedAs("bold-indent")
.isEqualTo(colorize(test, Colors.BOLD).prependIndent())
}
@Test
fun testIsoLocalDate() {
assertThat(cal.time.toIsoLocalDate()).describedAs("isoLocalDate(date)").isEqualTo("1952-02-17")
@ -129,7 +175,7 @@ class UtilsTest {
@Test
fun testObfuscate() {
assertThat(ascii.obfuscate().length).describedAs("obfuscate is right length").isEqualTo(ascii.length)
assertThat(ascii.obfuscate()).describedAs("obfuscate()").isEqualTo(StringUtils.repeat("x", ascii.length))
assertThat(ascii.obfuscate()).describedAs("obfuscate()").isEqualTo("x".repeat(ascii.length))
assertThat(" ".obfuscate()).describedAs("obfuscate(blank)").isEqualTo(" ")
}
@ -137,10 +183,31 @@ class UtilsTest {
fun testPlural() {
val week = "week"
val weeks = "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)
for (i in -1..3) {
assertThat(week.plural(i.toLong())).describedAs("plural($i)").isEqualTo(if (i > 1) weeks else week)
}
}
@Test
fun testReplaceEach() {
val search = arrayOf("one", "two", "three")
val replace = arrayOf("1", "2", "3")
assertThat(search.joinToString(",").replaceEach(search, replace)).describedAs("replaceEach(1,2,3")
.isEqualTo(replace.joinToString(","))
assertThat(test.replaceEach(search, replace)).describedAs("replaceEach(nothing)").isEqualTo(test)
assertThat(test.replaceEach(arrayOf("t", "e"), arrayOf("", "E"))).describedAs("replaceEach($test)")
.isEqualTo(test.replace("t", "").replace("e", "E"))
assertThat(test.replaceEach(search, emptyArray())).describedAs("replaceEach(search, empty)")
.isEqualTo(test)
}
@Test
fun testRed() {
assertThat(red(ascii)).isEqualTo(colorize(ascii, Colors.RED))
}
@Test
@ -153,13 +220,6 @@ class UtilsTest {
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
fun testToIntOrDefault() {
assertThat("10".toIntOrDefault(1)).describedAs("toIntOrDefault(10, 1)").isEqualTo(10)
@ -175,16 +235,21 @@ class UtilsTest {
@Test
fun testUptime() {
assertThat("17 years 2 months 2 weeks 1 day 6 hours 45 minutes").isEqualTo(uptime(547800300076L))
assertThat(uptime(547800300076L)).describedAs("full")
.isEqualTo("17 years 2 months 2 weeks 1 day 6 hours 45 minutes")
assertThat(uptime(2700000L)).describedAs("minutes").isEqualTo("45 minutes")
assertThat(uptime(24300000L)).describedAs("hours minutes").isEqualTo("6 hours 45 minutes")
assertThat(uptime(110700000L)).describedAs("days hours minutes").isEqualTo("1 day 6 hours 45 minutes")
assertThat(uptime(1320300000L)).describedAs("weeks days hours minutes")
.isEqualTo("2 weeks 1 day 6 hours 45 minutes")
assertThat(uptime(0L)).describedAs("0 minutes").isEqualTo("0 minute")
}
@Test
@Throws(IOException::class)
fun testUrlReader() {
assertThat(urlReader(URL("https://postman-echo.com/status/200"))).describedAs("urlReader()")
.isEqualTo(
"{\"status\":200}"
)
.isEqualTo("{\"status\":200}")
}
@Test