Compare commits

...

3 commits

Author SHA1 Message Date
1cd7c5a79e Upgraded to Kotlin 1.9.20 2023-11-01 22:10:50 -07:00
4c90870f4a Cleaned up code 2023-11-01 22:02:54 -07:00
d700aa06df Fixed SonarCloud code smells 2023-10-26 21:13:46 -07:00
66 changed files with 555 additions and 536 deletions

2
.idea/kotlinc.xml generated
View file

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="KotlinJpsPluginSettings">
<option name="version" value="1.9.10" />
<option name="version" value="1.9.20" />
</component>
</project>

1
.idea/misc.xml generated
View file

@ -1,4 +1,3 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="FrameworkDetectionExcludesConfiguration">

View file

@ -7,11 +7,11 @@ plugins {
id 'application'
id 'com.github.ben-manes.versions' version '0.49.0'
id 'idea'
id 'io.gitlab.arturbosch.detekt' version '1.23.1'
id 'io.gitlab.arturbosch.detekt' version '1.23.3'
id 'java'
id 'net.thauvin.erik.gradle.semver' version '1.0.4'
id 'org.jetbrains.kotlin.jvm' version '1.9.10'
id 'org.jetbrains.kotlin.kapt' version '1.9.10'
id 'org.jetbrains.kotlin.jvm' version '1.9.20'
id 'org.jetbrains.kotlin.kapt' version '1.9.20'
id 'org.jetbrains.kotlinx.kover' version '0.7.4'
id 'org.sonarqube' version '4.4.1.3373'
id 'pmd'
@ -55,7 +55,7 @@ dependencies {
// Commons (mostly for PircBotX)
implementation 'org.apache.commons:commons-lang3:3.13.0'
implementation 'org.apache.commons:commons-text:1.10.0'
implementation 'org.apache.commons:commons-text:1.11.0'
implementation 'commons-codec:commons-codec:1.16.0'
implementation 'commons-net:commons-net:3.10.0'

View file

@ -2,9 +2,9 @@
<SmellBaseline>
<ManuallySuppressedIssues></ManuallySuppressedIssues>
<CurrentIssues>
<ID>CyclomaticComplexMethod:FeedsManager.kt$FeedsManager.Companion$@JvmStatic fun saveFeed(entries: Entries, currentFile: String = currentXml)</ID>
<ID>CyclomaticComplexMethod:FeedsManager.kt$FeedsManager.Companion$@JvmStatic fun saveFeed(entries: Entries, currentFile: String = CURRENT_XML)</ID>
<ID>CyclomaticComplexMethod:Weather2.kt$Weather2.Companion$@JvmStatic @Throws(ModuleException::class) fun getWeather(query: String, apiKey: String?): List&lt;Message&gt;</ID>
<ID>LongMethod:FeedsManager.kt$FeedsManager.Companion$@JvmStatic fun saveFeed(entries: Entries, currentFile: String = currentXml)</ID>
<ID>LongMethod:FeedsManager.kt$FeedsManager.Companion$@JvmStatic fun saveFeed(entries: Entries, currentFile: String = CURRENT_XML)</ID>
<ID>LongMethod:Mobibot.kt$Mobibot.Companion$@JvmStatic @Throws(Exception::class) fun main(args: Array&lt;String&gt;)</ID>
<ID>LongMethod:StockQuote.kt$StockQuote.Companion$@JvmStatic @Throws(ModuleException::class) fun getQuote(symbol: String, apiKey: String?): List&lt;Message&gt;</ID>
<ID>LongMethod:Weather2.kt$Weather2.Companion$@JvmStatic @Throws(ModuleException::class) fun getWeather(query: String, apiKey: String?): List&lt;Message&gt;</ID>
@ -46,15 +46,6 @@
<ID>MagicNumber:WorldTime.kt$WorldTime.Companion$3600</ID>
<ID>MagicNumber:WorldTime.kt$WorldTime.Companion$60</ID>
<ID>MagicNumber:WorldTime.kt$WorldTime.Companion$86.4</ID>
<ID>MaxLineLength:DiceTest.kt$DiceTest$.</ID>
<ID>MaxLineLength:Lookup.kt$Lookup$("(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)")</ID>
<ID>MaxLineLength:Mastodon.kt$Mastodon.Companion$mapOf("status" to "${handle?.prefixIfMissing('@')} $message", "visibility" to "direct")</ID>
<ID>MaxLineLength:Mobibot.kt$Mobibot$helpCmdSyntax("%c ${Constants.HELP_CMD} &lt;command&gt;", event.bot().nick, event is PrivateMessageEvent)</ID>
<ID>MaxLineLength:PinboardTest.kt$PinboardTest$URL("https://api.pinboard.in/v1/posts/get?auth_token=${apiToken}&amp;tag=test&amp;" + url.encodeUrl()).reader().body</ID>
<ID>MaxLineLength:StockQuote.kt$StockQuote.Companion$+</ID>
<ID>MaxLineLength:Utils.kt$Utils$list.subList(i, list.size.coerceAtMost(i + maxPerLine)).joinToString(separator, truncated = "")</ID>
<ID>MaxLineLength:View.kt$View$helpCmdSyntax("%c $name ${index + 1} $query", event.bot().nick, event is PrivateMessageEvent)</ID>
<ID>MaxLineLength:Weather2.kt$Weather2.Companion$country.name.replace('_', ' ').capitalizeWords()</ID>
<ID>NestedBlockDepth:Addons.kt$Addons$fun add(command: AbstractCommand): Boolean</ID>
<ID>NestedBlockDepth:Addons.kt$Addons$fun add(module: AbstractModule): Boolean</ID>
<ID>NestedBlockDepth:ChatGpt.kt$ChatGpt.Companion$@JvmStatic @Throws(ModuleException::class) fun chat(query: String, apiKey: String?, maxTokens: Int): String</ID>
@ -62,8 +53,8 @@
<ID>NestedBlockDepth:CurrencyConverter.kt$CurrencyConverter.Companion$@JvmStatic @Throws(ModuleException::class) fun loadSymbols(apiKey: String?)</ID>
<ID>NestedBlockDepth:CurrencyConverter.kt$CurrencyConverter.Companion$@JvmStatic fun convertCurrency(apiKey: String?, query: String): Message</ID>
<ID>NestedBlockDepth:EntryLink.kt$EntryLink$private fun setTags(tags: List&lt;String?&gt;)</ID>
<ID>NestedBlockDepth:FeedsManager.kt$FeedsManager.Companion$@JvmStatic @Throws(IOException::class, FeedException::class) fun loadFeed(entries: Entries, currentFile: String = currentXml): String</ID>
<ID>NestedBlockDepth:FeedsManager.kt$FeedsManager.Companion$@JvmStatic fun saveFeed(entries: Entries, currentFile: String = currentXml)</ID>
<ID>NestedBlockDepth:FeedsManager.kt$FeedsManager.Companion$@JvmStatic @Throws(IOException::class, FeedException::class) fun loadFeed(entries: Entries, currentFile: String = CURRENT_XML): String</ID>
<ID>NestedBlockDepth:FeedsManager.kt$FeedsManager.Companion$@JvmStatic fun saveFeed(entries: Entries, currentFile: String = CURRENT_XML)</ID>
<ID>NestedBlockDepth:GoogleSearch.kt$GoogleSearch$override fun commandResponse(channel: String, cmd: String, args: String, event: GenericMessageEvent)</ID>
<ID>NestedBlockDepth:GoogleSearch.kt$GoogleSearch.Companion$@JvmStatic @Throws(ModuleException::class) fun searchGoogle( query: String, apiKey: String?, cseKey: String?, quotaUser: String = ReleaseInfo.PROJECT ): List&lt;Message&gt;</ID>
<ID>NestedBlockDepth:LinksManager.kt$LinksManager$override fun commandResponse(channel: String, args: String, event: GenericMessageEvent)</ID>

View file

@ -42,7 +42,6 @@ import org.slf4j.Logger
import java.io.*
import java.net.HttpURLConnection
import java.net.URL
import java.net.URLEncoder
import java.nio.file.Files
import java.nio.file.Paths
import java.time.LocalDateTime
@ -125,16 +124,24 @@ object Utils {
*/
@JvmStatic
fun String?.colorize(color: String): String {
return if (isNullOrEmpty()) {
return when {
isNullOrEmpty() -> {
""
} else if (color == DEFAULT_COLOR) {
}
color == DEFAULT_COLOR -> {
this
} else if (Colors.BOLD == color || Colors.REVERSE == color) {
}
Colors.BOLD == color || Colors.REVERSE == color -> {
color + this + color
} else {
}
else -> {
color + this + Colors.NORMAL
}
}
}
/**
* Makes the given string cyan.

View file

@ -129,7 +129,7 @@ class Ignore : AbstractCommand() {
}
}
if (ignored.size > 0) {
if (ignored.isNotEmpty()) {
event.sendMessage("The following nicks are ignored:")
event.sendList(ignored.sorted(), 8, isIndent = true)
} else {

View file

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

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

@ -85,19 +85,27 @@ class Tell(private val serialObject: String) : AbstractCommand() {
override fun commandResponse(channel: String, args: String, event: GenericMessageEvent) {
if (isEnabled()) {
if (args.isBlank()) {
when {
args.isBlank() -> {
helpResponse(channel, args, event)
} else if (args.startsWith(View.VIEW_CMD)) {
}
args.startsWith(View.VIEW_CMD) -> {
if (event.isChannelOp(channel) && "${View.VIEW_CMD} $TELL_ALL_KEYWORD" == args) {
viewAll(event)
} else {
viewMessages(event)
}
} else if (args.startsWith("$TELL_DEL_KEYWORD ")) {
}
args.startsWith("$TELL_DEL_KEYWORD ") -> {
deleteMessage(channel, args, event)
} else {
}
else -> {
newMessage(channel, args, event)
}
}
if (clean()) {
save()
}

View file

@ -98,6 +98,7 @@ class TellMessage(
}
companion object {
@Suppress("ConstPropertyName")
private const val serialVersionUID = 2L
}
}

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

@ -207,6 +207,7 @@ class EntryLink(
companion object {
// Serial version UID
@Suppress("ConstPropertyName")
private const val serialVersionUID: Long = 1L
}
}

View file

@ -55,17 +55,17 @@ 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()
@ -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 {
@ -141,7 +141,7 @@ class FeedsManager private constructor() {
.append("\"><b>")
.append(channel)
.append("</b></a>")
if (comments.size > 0) {
if (comments.isNotEmpty()) {
buff.append(" <br/><br/>")
for (j in comments.indices) {
if (j > 0) {
@ -167,7 +167,7 @@ class FeedsManager private constructor() {
OutputStreamWriter(
Files.newOutputStream(
Paths.get(
entries.logsDir + today() + dotXml
entries.logsDir + today() + DOT_XML
)
), StandardCharsets.UTF_8
).use { fw -> output.output(rss, fw) }

View file

@ -74,21 +74,29 @@ class CurrencyConverter : AbstractModule() {
override fun commandResponse(channel: String, cmd: String, args: String, event: GenericMessageEvent) {
reload(properties[API_KEY_PROP])
if (SYMBOLS.isEmpty()) {
when {
SYMBOLS.isEmpty() -> {
event.respond(EMPTY_SYMBOLS_TABLE)
} else if (args.matches("\\d+([,\\d]+)?(\\.\\d+)? [a-zA-Z]{3}+ (to|in) [a-zA-Z]{3}+".toRegex())) {
}
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)
if (msg.isError) {
helpResponse(event)
}
} else if (args.contains(CODES_KEYWORD)) {
}
args.contains(CODES_KEYWORD) -> {
event.sendMessage("The supported currency codes are:")
event.sendList(SYMBOLS.keys.toList(), 11, isIndent = true)
} else {
}
else -> {
helpResponse(event)
}
}
}
override fun helpResponse(event: GenericMessageEvent): Boolean {
reload(properties[API_KEY_PROP])

View file

@ -39,6 +39,7 @@ class ModuleException @JvmOverloads constructor(
cause: Throwable? = null
) : Exception(message, cause) {
companion object {
@Suppress("ConstPropertyName")
private const val serialVersionUID = 1L
}
}

View file

@ -44,33 +44,33 @@ 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))"
).isNotNull().all {
@ -78,21 +78,21 @@ class ModuleExceptionTest {
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)
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))"

View file

@ -1,9 +1,9 @@
#Generated by the Semver Plugin for Gradle
#Thu Oct 26 20:43:39 PDT 2023
version.buildmeta=20231026204339
#Wed Nov 01 22:09:32 PDT 2023
version.buildmeta=20231101220932
version.major=0
version.minor=8
version.patch=0
version.prerelease=rc
version.project=mobibot
version.semver=0.8.0-rc+20231026204339
version.semver=0.8.0-rc+20231101220932