Seen is now keeping track of nicks using a TreeMap on various events (nick change, join, etc.)
This commit is contained in:
parent
145749408b
commit
f35313bf62
8 changed files with 108 additions and 33 deletions
|
@ -173,6 +173,7 @@ class Mobibot(nickname: String, val channel: String, logsDirPath: String, p: Pro
|
|||
event?.let {
|
||||
with(event.getBot<PircBotX>()) {
|
||||
LinksMgr.twitter.notification("$nick disconnected from irc://$serverHostname")
|
||||
seen.add(userChannelDao.getChannel(channel).users)
|
||||
}
|
||||
}
|
||||
LinksMgr.twitter.shutdown()
|
||||
|
@ -197,8 +198,10 @@ class Mobibot(nickname: String, val channel: String, logsDirPath: String, p: Pro
|
|||
with(event.getBot<PircBotX>()) {
|
||||
if (user.nick == nick) {
|
||||
LinksMgr.twitter.notification("$nick has joined ${event.channel.name} on irc://$serverHostname")
|
||||
seen.add(userChannelDao.getChannel(channel).users)
|
||||
} else {
|
||||
tell.send(event)
|
||||
seen.add(user.nick)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -228,7 +231,13 @@ class Mobibot(nickname: String, val channel: String, logsDirPath: String, p: Pro
|
|||
}
|
||||
|
||||
override fun onNickChange(event: NickChangeEvent?) {
|
||||
event?.let { tell.send(event) }
|
||||
event?.let {
|
||||
tell.send(event)
|
||||
if (!it.oldNick.equals(it.newNick, true)) {
|
||||
seen.add(it.oldNick)
|
||||
}
|
||||
seen.add(it.newNick)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onPart(event: PartEvent?) {
|
||||
|
@ -236,6 +245,7 @@ class Mobibot(nickname: String, val channel: String, logsDirPath: String, p: Pro
|
|||
with(event.getBot<PircBotX>()) {
|
||||
if (user.nick == nick) {
|
||||
LinksMgr.twitter.notification("$nick has left ${event.channel.name} on irc://$serverHostname")
|
||||
seen.add(userChannelDao.getChannel(channel).users)
|
||||
} else {
|
||||
seen.add(user.nick)
|
||||
}
|
||||
|
@ -424,10 +434,10 @@ class Mobibot(nickname: String, val channel: String, logsDirPath: String, p: Pro
|
|||
addons.add(Ping())
|
||||
addons.add(RockPaperScissors())
|
||||
addons.add(StockQuote())
|
||||
addons.add(Weather2())
|
||||
addons.add(WorldTime())
|
||||
addons.add(War())
|
||||
addons.add(Weather2())
|
||||
addons.add(WolframAlpha())
|
||||
addons.add(WorldTime())
|
||||
|
||||
// Sort the addons
|
||||
addons.names.sort()
|
||||
|
|
|
@ -214,7 +214,7 @@ object Utils {
|
|||
} catch (e: IOException) {
|
||||
logger.error("An IO error occurred loading the ${description}.", e)
|
||||
} catch (e: ClassNotFoundException) {
|
||||
logger.error("An error occurred loading the {$description}.", e)
|
||||
logger.error("An error occurred loading the ${description}.", e)
|
||||
}
|
||||
}
|
||||
return default
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* SeenComparator.kt
|
||||
*
|
||||
* Copyright (c) 2004-2022, Erik C. Thauvin (erik@thauvin.net)
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* Neither the name of this project nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package net.thauvin.erik.mobibot.commands.seen
|
||||
|
||||
import java.io.Serializable
|
||||
|
||||
class NickComparator: Comparator<String>, Serializable {
|
||||
override fun compare(a: String, b: String): Int {
|
||||
return a.lowercase().compareTo(b.lowercase())
|
||||
}
|
||||
companion object {
|
||||
private const val serialVersionUID = 1L
|
||||
}
|
||||
}
|
|
@ -32,6 +32,7 @@
|
|||
|
||||
package net.thauvin.erik.mobibot.commands.seen
|
||||
|
||||
import com.google.common.collect.ImmutableSortedSet
|
||||
import net.thauvin.erik.mobibot.Utils.bot
|
||||
import net.thauvin.erik.mobibot.Utils.helpFormat
|
||||
import net.thauvin.erik.mobibot.Utils.loadData
|
||||
|
@ -39,13 +40,16 @@ import net.thauvin.erik.mobibot.Utils.saveData
|
|||
import net.thauvin.erik.mobibot.Utils.sendMessage
|
||||
import net.thauvin.erik.mobibot.commands.AbstractCommand
|
||||
import net.thauvin.erik.mobibot.commands.Info.Companion.toUptime
|
||||
import org.pircbotx.User
|
||||
import org.pircbotx.hooks.types.GenericMessageEvent
|
||||
import org.slf4j.Logger
|
||||
import org.slf4j.LoggerFactory
|
||||
import java.util.TreeMap
|
||||
|
||||
|
||||
class Seen(private val serialObject: String) : AbstractCommand() {
|
||||
private val logger: Logger = LoggerFactory.getLogger(Seen::class.java)
|
||||
val seenNicks: MutableList<SeenNick> = mutableListOf()
|
||||
val seenNicks = TreeMap<String, SeenNick>(NickComparator())
|
||||
|
||||
override val name = "seen"
|
||||
override val help = listOf("To view when a nickname was last seen:", helpFormat("%c $name <nick>"))
|
||||
|
@ -53,6 +57,7 @@ class Seen(private val serialObject: String) : AbstractCommand() {
|
|||
override val isPublic = true
|
||||
override val isVisible = true
|
||||
|
||||
|
||||
override fun commandResponse(channel: String, args: String, event: GenericMessageEvent) {
|
||||
if (isEnabled()) {
|
||||
if (args.isNotBlank() && !args.contains(' ')) {
|
||||
|
@ -63,12 +68,11 @@ class Seen(private val serialObject: String) : AbstractCommand() {
|
|||
return
|
||||
}
|
||||
}
|
||||
seenNicks.forEach {
|
||||
if (it.nick.equals(args, true)) {
|
||||
val lastSeen = System.currentTimeMillis() - it.last
|
||||
event.sendMessage("${it.nick} was last seen on $channel ${lastSeen.toUptime()} ago.")
|
||||
return
|
||||
}
|
||||
if (seenNicks.containsKey(args)) {
|
||||
val seenNick = seenNicks.getValue(args)
|
||||
val lastSeen = System.currentTimeMillis() - seenNick.lastSeen
|
||||
event.sendMessage("${seenNick.nick} was last seen on $channel ${lastSeen.toUptime()} ago.")
|
||||
return
|
||||
}
|
||||
event.sendMessage("I haven't seen $args on $channel lately.")
|
||||
} else {
|
||||
|
@ -79,15 +83,16 @@ class Seen(private val serialObject: String) : AbstractCommand() {
|
|||
|
||||
fun add(nick: String) {
|
||||
if (isEnabled()) {
|
||||
seenNicks.forEach {
|
||||
if (it.nick.equals(nick, true)) {
|
||||
if (it.nick != nick) it.nick = nick
|
||||
it.last = System.currentTimeMillis()
|
||||
save()
|
||||
return
|
||||
}
|
||||
seenNicks[nick] = SeenNick(nick, System.currentTimeMillis())
|
||||
save()
|
||||
}
|
||||
}
|
||||
|
||||
fun add(users: ImmutableSortedSet<User>) {
|
||||
if (isEnabled()) {
|
||||
users.forEach {
|
||||
seenNicks[it.nick] = SeenNick(it.nick, System.currentTimeMillis())
|
||||
}
|
||||
seenNicks.add(SeenNick(nick))
|
||||
save()
|
||||
}
|
||||
}
|
||||
|
@ -99,12 +104,14 @@ class Seen(private val serialObject: String) : AbstractCommand() {
|
|||
fun load() {
|
||||
if (isEnabled()) {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
seenNicks += loadData(
|
||||
serialObject,
|
||||
mutableListOf<SeenNick>(),
|
||||
logger,
|
||||
"seen nicknames"
|
||||
) as MutableList<SeenNick>
|
||||
seenNicks.putAll(
|
||||
loadData(
|
||||
serialObject,
|
||||
TreeMap<String, SeenNick>(),
|
||||
logger,
|
||||
"seen nicknames"
|
||||
) as TreeMap<String, SeenNick>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -34,7 +34,7 @@ package net.thauvin.erik.mobibot.commands.seen
|
|||
|
||||
import java.io.Serializable
|
||||
|
||||
data class SeenNick(var nick: String, var last: Long = System.currentTimeMillis()) : Serializable {
|
||||
data class SeenNick(val nick: String, val lastSeen: Long) : Serializable {
|
||||
companion object {
|
||||
private const val serialVersionUID = 1L
|
||||
}
|
||||
|
|
|
@ -35,6 +35,7 @@ package net.thauvin.erik.mobibot.commands.seen
|
|||
import assertk.assertThat
|
||||
import assertk.assertions.isEqualTo
|
||||
import assertk.assertions.isGreaterThan
|
||||
import assertk.assertions.isNotEqualTo
|
||||
import assertk.assertions.isTrue
|
||||
import org.testng.annotations.AfterClass
|
||||
import org.testng.annotations.BeforeClass
|
||||
|
@ -45,6 +46,7 @@ import kotlin.io.path.fileSize
|
|||
class SeenTest {
|
||||
private val tmpFile = kotlin.io.path.createTempFile(suffix = ".ser")
|
||||
private val seen = Seen(tmpFile.toAbsolutePath().toString())
|
||||
private val nick = "ErikT"
|
||||
|
||||
@BeforeClass
|
||||
fun saveTest() {
|
||||
|
@ -57,12 +59,21 @@ class SeenTest {
|
|||
tmpFile.deleteIfExists()
|
||||
}
|
||||
|
||||
@Test
|
||||
@Test(priority = 1)
|
||||
fun loadTest() {
|
||||
val nick = seen.seenNicks[0]
|
||||
seen.clear()
|
||||
assertThat(seen.seenNicks.isEmpty(), "nicknames map is not empty").isTrue()
|
||||
seen.load()
|
||||
assertThat(seen.seenNicks[0] == nick, "nick is different").isTrue()
|
||||
assertThat(seen.seenNicks.containsKey(nick), "nick is missing").isTrue()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun addTest() {
|
||||
val last = seen.seenNicks[nick]?.lastSeen
|
||||
seen.add(nick.lowercase())
|
||||
assertThat(seen.seenNicks.size, "nick is duplicated").isEqualTo(1)
|
||||
assertThat(seen.seenNicks[nick]?.lastSeen, "last seen is not different").isNotEqualTo(last)
|
||||
assertThat(seen.seenNicks[nick]?.nick, "nick is not lowercase").isEqualTo(nick.lowercase())
|
||||
}
|
||||
|
||||
@Test(priority = 10)
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
#Generated by the Semver Plugin for Gradle
|
||||
#Fri Sep 16 00:01:57 PDT 2022
|
||||
version.buildmeta=525
|
||||
#Fri Sep 16 10:29:48 PDT 2022
|
||||
version.buildmeta=542
|
||||
version.major=0
|
||||
version.minor=8
|
||||
version.patch=0
|
||||
version.prerelease=rc
|
||||
version.project=mobibot
|
||||
version.semver=0.8.0-rc+525
|
||||
version.semver=0.8.0-rc+542
|
||||
|
|
|
@ -100,7 +100,7 @@
|
|||
<div><code>mobibot: time UK</code></div>
|
||||
<div><code>mobibot: time GMT</code></div>
|
||||
</li>
|
||||
<li>Sending messages to people on join/activity:
|
||||
<li>Sending messages to people on join/activity
|
||||
<div><code>mobibot: tell nickname Give me a call when you see this.</code></div>
|
||||
</li>
|
||||
<li>Recapping public channel messages
|
||||
|
@ -109,6 +109,9 @@
|
|||
<li>Listing the users on the channel
|
||||
<div><code>/msg mobibot users</code></div>
|
||||
</li>
|
||||
<li>Viewing when a nickname was last seen
|
||||
<div><code>/msg mobibot seen nickname</code></div>
|
||||
</li>
|
||||
<li>Random jokes from <a href="http://www.icndb.com/">The Internet Chuck Norris Database</a>
|
||||
<div><code>mobibot: joke</code></div>
|
||||
</li>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue