This commit is contained in:
Erik C. Thauvin 2021-05-16 08:17:16 -07:00
parent 8681dea66f
commit 082b430ee2
25 changed files with 68 additions and 560 deletions

View file

@ -53,9 +53,9 @@ public final class War extends AbstractModule {
private static final String WAR_CMD = "war";
// Deck of card
private static final String[] WAR_DECK =
new String[]{ "Ace", "King", "Queen", "Jack", "10", "9", "8", "7", "6", "5", "4", "3", "2" };
new String[]{"Ace", "King", "Queen", "Jack", "10", "9", "8", "7", "6", "5", "4", "3", "2"};
// Suits for the deck of card
private static final String[] WAR_SUITS = new String[]{ "Hearts", "Spades", "Diamonds", "Clubs" };
private static final String[] WAR_SUITS = new String[]{"Hearts", "Spades", "Diamonds", "Clubs"};
/**
* The default constructor.
@ -85,9 +85,9 @@ public final class War extends AbstractModule {
y = RANDOM.nextInt(WAR_DECK.length);
getBot().send(sender + " drew the " + bold(WAR_DECK[i]) + " of "
+ bold(WAR_SUITS[RANDOM.nextInt(WAR_SUITS.length)]));
+ bold(WAR_SUITS[RANDOM.nextInt(WAR_SUITS.length)]));
getBot().action("drew the " + bold(WAR_DECK[y]) + " of "
+ bold(WAR_SUITS[RANDOM.nextInt(WAR_SUITS.length)]));
+ bold(WAR_SUITS[RANDOM.nextInt(WAR_SUITS.length)]));
if (i != y) {
break;

View file

@ -33,6 +33,8 @@ package net.thauvin.erik.mobibot
import com.rometools.rome.io.SyndFeedInput
import com.rometools.rome.io.XmlReader
import net.thauvin.erik.mobibot.Utils.green
import net.thauvin.erik.mobibot.Utils.helpFormat
import java.net.MalformedURLException
import java.net.URL
@ -67,7 +69,7 @@ class FeedReader(
var i = 0
while (i < items.size && i < maxItems) {
send(sender, items[i].title, false)
send(sender, Utils.helpFormat(Utils.green(items[i].link), false), false)
send(sender, helpFormat(green(items[i].link), false), false)
i++
}
}

View file

@ -32,8 +32,9 @@
package net.thauvin.erik.mobibot
import kotlinx.coroutines.async
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.withContext
import net.thauvin.erik.mobibot.entries.EntryLink
import net.thauvin.erik.pinboard.PinboardPoster
import java.time.ZoneId
@ -51,15 +52,15 @@ object PinboardUtils {
*/
@JvmStatic
fun addPin(poster: PinboardPoster, ircServer: String, entry: EntryLink) = runBlocking {
async {
withContext(Dispatchers.Default) {
poster.addPin(
entry.link,
entry.title,
postedBy(entry, ircServer),
entry.postedBy(ircServer),
entry.pinboardTags,
entry.date.toTimestamp()
)
}.await()
}
}
/**
@ -67,9 +68,9 @@ object PinboardUtils {
*/
@JvmStatic
fun deletePin(poster: PinboardPoster, entry: EntryLink) = runBlocking {
async {
withContext(Dispatchers.Default) {
poster.deletePin(entry.link)
}.await()
}
}
/**
@ -77,14 +78,14 @@ object PinboardUtils {
*/
@JvmStatic
fun updatePin(poster: PinboardPoster, ircServer: String, oldUrl: String, entry: EntryLink) = runBlocking {
async {
withContext(Dispatchers.Default) {
with(entry) {
if (oldUrl != link) {
poster.deletePin(oldUrl)
poster.addPin(
link,
title,
postedBy(entry, ircServer),
entry.postedBy(ircServer),
pinboardTags,
date.toTimestamp()
)
@ -92,7 +93,7 @@ object PinboardUtils {
poster.addPin(
link,
title,
postedBy(entry, ircServer),
entry.postedBy(ircServer),
pinboardTags,
date.toTimestamp(),
replace = true,
@ -100,7 +101,7 @@ object PinboardUtils {
)
}
}
}.await()
}
}
/**
@ -109,15 +110,16 @@ object PinboardUtils {
@JvmStatic
fun Date.toTimestamp(): String {
return ZonedDateTime.ofInstant(
this.toInstant().truncatedTo(ChronoUnit.SECONDS),
ZoneId.systemDefault()).format(DateTimeFormatter.ISO_INSTANT)
this.toInstant().truncatedTo(ChronoUnit.SECONDS),
ZoneId.systemDefault()
).format(DateTimeFormatter.ISO_INSTANT)
}
/**
* Returns the pinboard.in extended attribution line.
*/
private fun postedBy(entry: EntryLink, ircServer: String): String {
return "Posted by ${entry.nick} on ${entry.channel} ( $ircServer )"
private fun EntryLink.postedBy(ircServer: String): String {
return "Posted by ${this.nick} on ${this.channel} ( $ircServer )"
}
}

View file

@ -59,11 +59,11 @@ class Recap(bot: Mobibot) : AbstractCommand(bot) {
fun storeRecap(sender: String, message: String, isAction: Boolean) {
recaps.add(
LocalDateTime.now(Clock.systemUTC()).toUtcDateTime()
+ " - $sender" + (if (isAction) " " else ": ") + message
+ " - $sender" + (if (isAction) " " else ": ") + message
)
@Suppress("MagicNumber")
if (recaps.size > 10) {
recaps.removeAt(0)
recaps.removeFirst()
}
}
}

View file

@ -40,7 +40,7 @@ class Versions(bot: Mobibot) : AbstractCommand(bot) {
private val allVersions = listOf(
"Version: ${ReleaseInfo.VERSION} (${ReleaseInfo.BUILDDATE.toIsoLocalDate()})",
"Platform: " + System.getProperty("os.name") + ' ' + System.getProperty("os.version")
+ " (" + System.getProperty("os.arch") + ')',
+ " (" + System.getProperty("os.arch") + ')',
"Runtime: " + System.getProperty("java.runtime.name") + ' ' + System.getProperty("java.runtime.version")
)
override val name = "versions"

View file

@ -80,7 +80,7 @@ object EntriesMgr {
if (!history.contains(bot.today)) {
history.add(bot.today)
while (history.size > maxBacklogs) {
history.removeAt(0)
history.removeFirst()
}
}
OutputStreamWriter(
@ -201,7 +201,6 @@ object EntriesMgr {
language = "en"
}
val buff: StringBuilder = StringBuilder()
var comment: EntryComment
for (i in entries.size - 1 downTo 0) {
with(entries[i]) {
buff.setLength(0)
@ -215,13 +214,11 @@ object EntriesMgr {
.append("</b></a>")
if (comments.size > 0) {
buff.append(" <br/><br/>")
val comments = comments
for (j in comments.indices) {
comment = comments[j]
if (j > 0) {
buff.append(" <br/>")
}
buff.append(comment.nick).append(": ").append(comment.comment)
buff.append(comments[j].nick).append(": ").append(comments[j].comment)
}
}
item = SyndEntryImpl()

View file

@ -43,9 +43,7 @@ data class EntryComment(var comment: String, var nick: String) : Serializable {
*/
val date: LocalDateTime = LocalDateTime.now()
override fun toString(): String {
return ("EntryComment{comment='$comment', date=$date, nick='$nick'}")
}
override fun toString(): String = "EntryComment{comment='$comment', date=$date, nick='$nick'}"
companion object {
// Serial version UID

View file

@ -145,8 +145,8 @@ class EntryLink : Serializable {
*/
fun matches(match: String?): Boolean {
return (StringUtils.containsIgnoreCase(link, match)
|| StringUtils.containsIgnoreCase(title, match)
|| StringUtils.containsIgnoreCase(nick, match))
|| StringUtils.containsIgnoreCase(title, match)
|| StringUtils.containsIgnoreCase(nick, match))
}
/**
@ -203,7 +203,7 @@ class EntryLink : Serializable {
*/
override fun toString(): String {
return ("EntryLink{channel='$channel', comments=$comments, date=$date, link='$link', login='$login'," +
"nick='$nick', tags=$tags, title='$title'}")
"nick='$nick', tags=$tags, title='$title'}")
}
companion object {

View file

@ -152,6 +152,9 @@ class CurrencyConverter(bot: Mobibot) : ThreadedModule(bot) {
// Last exchange rates table publication date
private var pubDate = ""
private fun Double.formatCurrency(): String =
NumberFormat.getCurrencyInstance(Constants.LOCALE).format(this).substring(1)
/**
* Converts from a currency to another.
*/
@ -171,11 +174,8 @@ class CurrencyConverter(bot: Mobibot) : ThreadedModule(bot) {
val doubleFrom = EXCHANGE_RATES[to]!!.toDouble()
val doubleTo = EXCHANGE_RATES[from]!!.toDouble()
PublicMessage(
NumberFormat.getCurrencyInstance(Constants.LOCALE).format(amt).substring(1)
+ " ${cmds[1].uppercase()} = "
+ NumberFormat.getCurrencyInstance(Constants.LOCALE)
.format(amt * doubleTo / doubleFrom).substring(1)
+ " ${cmds[3].uppercase()}"
amt.formatCurrency() + " ${cmds[1].uppercase()} = "
+ (amt * doubleTo / doubleFrom).formatCurrency() + " ${cmds[3].uppercase()}"
)
} catch (e: NumberFormatException) {
ErrorMessage("Let's try with some real numbers next time, okay?")
@ -187,6 +187,7 @@ class CurrencyConverter(bot: Mobibot) : ThreadedModule(bot) {
} else ErrorMessage("Invalid query. Let's try again.")
}
@JvmStatic
fun currencyRates(): List<String> {
val rates = mutableListOf<String>()

View file

@ -54,12 +54,12 @@ class Dice(bot: Mobibot) : AbstractModule(bot) {
send(
channel,
"$sender rolled two dice: ${bold(playerRoll.first)} and ${bold(playerRoll.second)}"
+ " for a total of ${bold(playerTotal)}",
+ " for a total of ${bold(playerTotal)}",
isPrivate
)
action(
"rolled two dice: ${bold(roll.first)} and ${bold(roll.second)}" +
" for a total of ${bold(total)}"
" for a total of ${bold(total)}"
)
when (winLoseOrTie(total, playerTotal)) {
Result.WIN -> action("wins.")

View file

@ -97,7 +97,7 @@ class GoogleSearch(bot: Mobibot) : ThreadedModule(bot) {
try {
val url = URL(
"https://www.googleapis.com/customsearch/v1?key=$apiKey&cx=$cseKey" +
"&q=${encodeUrl(query)}&filter=1&num=5&alt=json"
"&q=${encodeUrl(query)}&filter=1&num=5&alt=json"
)
val json = JSONObject(urlReader(url))
val ja = json.getJSONArray("items")

View file

@ -58,8 +58,8 @@ class Lookup(bot: Mobibot) : AbstractModule(bot) {
} catch (ignore: UnknownHostException) {
if (args.matches(
("(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\." +
"(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\." +
"(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)").toRegex()
"(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\." +
"(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)").toRegex()
)
) {
try {

View file

@ -56,7 +56,7 @@ class RockPaperScissors(bot: Mobibot) : AbstractModule(bot) {
add(
helpFormat(
"%c ${Hands.ROCK.name.lowercase()} | ${Hands.PAPER.name.lowercase()}"
+ " | ${Hands.SCISSORS.name.lowercase()}"
+ " | ${Hands.SCISSORS.name.lowercase()}"
)
)
}

View file

@ -139,7 +139,7 @@ class StockQuote(bot: Mobibot) : ThreadedModule(bot) {
response = urlReader(
URL(
"${ALPHAVANTAGE_URL}SYMBOL_SEARCH&keywords=" + encodeUrl(symbol)
+ "&apikey=" + encodeUrl(apiKey)
+ "&apikey=" + encodeUrl(apiKey)
)
)
var json = getJsonResponse(response, debugMessage)
@ -153,8 +153,8 @@ class StockQuote(bot: Mobibot) : ThreadedModule(bot) {
response = urlReader(
URL(
"${ALPHAVANTAGE_URL}GLOBAL_QUOTE&symbol="
+ encodeUrl(symbolInfo.getString("1. symbol"))
+ "&apikey=" + encodeUrl(apiKey)
+ encodeUrl(symbolInfo.getString("1. symbol"))
+ "&apikey=" + encodeUrl(apiKey)
)
)
json = getJsonResponse(response, debugMessage)
@ -166,28 +166,23 @@ class StockQuote(bot: Mobibot) : ThreadedModule(bot) {
add(
PublicMessage(
"Symbol: " + unescapeXml(quote.getString("01. symbol"))
+ " [" + unescapeXml(symbolInfo.getString("2. name")) + ']'
+ " [" + unescapeXml(symbolInfo.getString("2. name")) + ']'
)
)
add(PublicMessage(" Price: " + unescapeXml(quote.getString("05. price"))))
add(
PublicMessage(
" Previous: " + unescapeXml(quote.getString("08. previous close"))
)
)
add(PublicMessage(" Previous: " + unescapeXml(quote.getString("08. previous close"))))
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(
add(NoticeMessage(
" Latest: " + unescapeXml(quote.getString("07. latest trading day"))
)
)
add(
NoticeMessage(
" Change: " + unescapeXml(quote.getString("09. change")) + " ["
+ unescapeXml(quote.getString("10. change percent")) + ']'
+ unescapeXml(quote.getString("10. change percent")) + ']'
)
)
}

View file

@ -104,9 +104,7 @@ class Weather2(bot: Mobibot) : ThreadedModule(bot) {
@Throws(ModuleException::class)
fun getWeather(query: String, apiKey: String?): List<Message> {
if (apiKey.isNullOrBlank()) {
throw ModuleException(
"${WEATHER_CMD.capitalise()} is disabled. The API key is missing."
)
throw ModuleException("${WEATHER_CMD.capitalise()} is disabled. The API key is missing.")
}
val owm = OWM(apiKey)
val messages = mutableListOf<Message>()
@ -127,9 +125,7 @@ class Weather2(bot: Mobibot) : ThreadedModule(bot) {
owm.currentWeatherByCityName(city, getCountry(country))
}
if (cwd.hasCityName()) {
messages.add(
PublicMessage("City: ${cwd.cityName} [${country.uppercase()}]")
)
messages.add(PublicMessage("City: ${cwd.cityName} [${country.uppercase()}]"))
with(cwd.mainData) {
if (this != null) {
if (hasTemp()) {
@ -170,7 +166,7 @@ class Weather2(bot: Mobibot) : ThreadedModule(bot) {
messages.add(
NoticeMessage(
"https://openweathermap.org/find?q="
+ encodeUrl("$city,${country.uppercase()}"),
+ encodeUrl("$city,${country.uppercase()}"),
Colors.GREEN
)
)

View file

@ -58,6 +58,10 @@ class WorldTime(bot: Mobibot) : AbstractModule(bot) {
// The Time command
private const val TIME_CMD = "time"
// Date/Time Format
private var dtf =
DateTimeFormatter.ofPattern("'The time is ${bold("'HH:mm'")} on ${bold("'EEEE, d MMMM yyyy'")} in '")
/**
* Returns the current Internet (beat) Time.
*/
@ -65,7 +69,7 @@ class WorldTime(bot: Mobibot) : AbstractModule(bot) {
private fun internetTime(): String {
val zdt = ZonedDateTime.now(ZoneId.of("UTC+01:00"))
val beats = ((zdt[ChronoField.SECOND_OF_MINUTE] + zdt[ChronoField.MINUTE_OF_HOUR] * 60
+ zdt[ChronoField.HOUR_OF_DAY] * 3600) / 86.4).toInt()
+ zdt[ChronoField.HOUR_OF_DAY] * 3600) / 86.4).toInt()
return String.format(Locale.getDefault(), "%c%03d", '@', beats)
}
@ -79,15 +83,8 @@ class WorldTime(bot: Mobibot) : AbstractModule(bot) {
if (BEATS_KEYWORD == tz) {
"The current Internet Time is: ${bold(internetTime())} $BEATS_KEYWORD"
} else {
(ZonedDateTime.now()
.withZoneSameInstant(ZoneId.of(tz))
.format(
DateTimeFormatter.ofPattern(
"'The time is ${bold("'HH:mm'")} on ${bold("'EEEE, d MMMM yyyy'")} in '"
)
)
+ bold(tz.substring(tz.indexOf('/') + 1).replace('_', ' '))
)
(ZonedDateTime.now().withZoneSameInstant(ZoneId.of(tz)).format(dtf)
+ bold(tz.substring(tz.indexOf('/') + 1).replace('_', ' ')))
}
} else {
return ErrorMessage("Unsupported country/zone. Please try again.")

View file

@ -32,14 +32,14 @@
package net.thauvin.erik.mobibot
import net.thauvin.erik.mobibot.entries.EntryLink
import net.thauvin.erik.mobibot.PinboardUtils.toTimestamp
import net.thauvin.erik.mobibot.entries.EntryLink
import net.thauvin.erik.pinboard.PinboardPoster
import org.testng.Assert.assertFalse
import org.testng.Assert.assertTrue
import org.testng.annotations.Test
import java.util.Date
import java.net.URL
import java.util.Date
class PinboardUtilsTest : LocalProperties() {
@Test
@ -71,7 +71,7 @@ class PinboardUtilsTest : LocalProperties() {
val response = Utils.urlReader(
URL(
"https://api.pinboard.in/v1/posts/get?auth_token=${apiToken}&tag=test&"
+ Utils.encodeUrl(url)
+ Utils.encodeUrl(url)
)
)