Browse Source

Support for notices and CTCPRs

Auth notices will be from a server or "*".

Closes #3
tags/v0.5.0
Chris Smith 5 years ago
parent
commit
6fb728f7e2

+ 2
- 0
CHANGELOG View File

@@ -13,6 +13,8 @@ vNEXT (in development)
13 13
     * Added MotdFinished event
14 14
     * Added UserAccountChanged event
15 15
     * Added ChannelUserKicked event
16
+    * Added NoticeReceived event
17
+    * Added CtcpReplyReceived event
16 18
  * Improved some documentation
17 19
 
18 20
 v0.4.0

+ 10
- 0
src/main/kotlin/com/dmdirc/ktirc/events/Events.kt View File

@@ -50,12 +50,22 @@ class ChannelNamesFinished(time: LocalDateTime, val channel: String) : IrcEvent(
50 50
 /** Raised when a message is received. */
51 51
 class MessageReceived(time: LocalDateTime, val user: User, val target: String, val message: String) : IrcEvent(time)
52 52
 
53
+/**
54
+ * Raised when a notice is received.
55
+ *
56
+ * The [user] may in fact be a server, or have a nickname of `*` while connecting.
57
+ */
58
+class NoticeReceived(time: LocalDateTime, val user: User, val target: String, val message: String) : IrcEvent(time)
59
+
53 60
 /** Raised when an action is received. */
54 61
 class ActionReceived(time: LocalDateTime, val user: User, val target: String, val action: String) : IrcEvent(time)
55 62
 
56 63
 /** Raised when a CTCP is received. */
57 64
 class CtcpReceived(time: LocalDateTime, val user: User, val target: String, val type: String, val content: String) : IrcEvent(time)
58 65
 
66
+/** Raised when a CTCP reply is received. */
67
+class CtcpReplyReceived(time: LocalDateTime, val user: User, val target: String, val type: String, val content: String) : IrcEvent(time)
68
+
59 69
 /** Raised when a user quits. */
60 70
 class UserQuit(time: LocalDateTime, val user: User, val reason: String = "") : IrcEvent(time)
61 71
 

+ 1
- 0
src/main/kotlin/com/dmdirc/ktirc/messages/MessageProcessor.kt View File

@@ -26,6 +26,7 @@ internal val messageProcessors = setOf(
26 26
         ModeProcessor(),
27 27
         MotdProcessor(),
28 28
         NamesProcessor(),
29
+        NoticeProcessor(),
29 30
         PartProcessor(),
30 31
         PingProcessor(),
31 32
         PrivmsgProcessor(),

+ 28
- 0
src/main/kotlin/com/dmdirc/ktirc/messages/NoticeProcessor.kt View File

@@ -0,0 +1,28 @@
1
+package com.dmdirc.ktirc.messages
2
+
3
+import com.dmdirc.ktirc.events.CtcpReplyReceived
4
+import com.dmdirc.ktirc.events.IrcEvent
5
+import com.dmdirc.ktirc.events.NoticeReceived
6
+import com.dmdirc.ktirc.model.IrcMessage
7
+import com.dmdirc.ktirc.model.User
8
+
9
+internal class NoticeProcessor : MessageProcessor {
10
+
11
+    override val commands = arrayOf("NOTICE")
12
+
13
+    override fun process(message: IrcMessage) = when {
14
+            message.isCtcp() -> handleCtcp(message,  message.sourceUser)
15
+            else -> listOf(NoticeReceived(message.time,  message.sourceUser ?: User("*"), String(message.params[0]), String(message.params[1])))
16
+        }
17
+
18
+    private fun handleCtcp(message: IrcMessage, user: User?): List<IrcEvent> {
19
+        user ?: return emptyList()
20
+        val content = String(message.params[1]).substring(1 until message.params[1].size - 1)
21
+        val parts = content.split(' ', limit=2)
22
+        val body = if (parts.size == 2) parts[1] else ""
23
+        return listOf(CtcpReplyReceived(message.time, user, String(message.params[0]), parts[0], body))
24
+    }
25
+
26
+    private fun IrcMessage.isCtcp() = params[1].size > 2 && params[1][0] == CTCP_BYTE && params[1][params[1].size - 1] == CTCP_BYTE
27
+
28
+}

+ 2
- 0
src/main/kotlin/com/dmdirc/ktirc/messages/NumericConstants.kt View File

@@ -1,5 +1,7 @@
1 1
 package com.dmdirc.ktirc.messages
2 2
 
3
+internal const val CTCP_BYTE : Byte = 1
4
+
3 5
 internal const val RPL_WELCOME = "001"
4 6
 internal const val RPL_ISUPPORT = "005"
5 7
 

+ 0
- 2
src/main/kotlin/com/dmdirc/ktirc/messages/PrivmsgProcessor.kt View File

@@ -7,8 +7,6 @@ import com.dmdirc.ktirc.events.MessageReceived
7 7
 import com.dmdirc.ktirc.model.IrcMessage
8 8
 import com.dmdirc.ktirc.model.User
9 9
 
10
-private const val CTCP_BYTE : Byte = 1
11
-
12 10
 internal class PrivmsgProcessor : MessageProcessor {
13 11
 
14 12
     override val commands = arrayOf("PRIVMSG")

+ 81
- 0
src/test/kotlin/com/dmdirc/ktirc/messages/NoticeProcessorTest.kt View File

@@ -0,0 +1,81 @@
1
+package com.dmdirc.ktirc.messages
2
+
3
+import com.dmdirc.ktirc.TestConstants
4
+import com.dmdirc.ktirc.events.CtcpReplyReceived
5
+import com.dmdirc.ktirc.events.NoticeReceived
6
+import com.dmdirc.ktirc.model.IrcMessage
7
+import com.dmdirc.ktirc.model.User
8
+import com.dmdirc.ktirc.params
9
+import com.dmdirc.ktirc.util.currentTimeProvider
10
+import org.junit.jupiter.api.Assertions.assertEquals
11
+import org.junit.jupiter.api.BeforeEach
12
+import org.junit.jupiter.api.Test
13
+
14
+internal class NoticeProcessorTest {
15
+
16
+    @BeforeEach
17
+    fun setUp() {
18
+        currentTimeProvider = { TestConstants.time }
19
+    }
20
+
21
+    @Test
22
+    fun `raises notice received event`() {
23
+        val events = NoticeProcessor().process(
24
+                IrcMessage(emptyMap(), "acidburn!libby@root.localhost".toByteArray(), "NOTICE", params("#crashandburn", "hack the planet!")))
25
+        assertEquals(1, events.size)
26
+
27
+        val event = events[0] as NoticeReceived
28
+        assertEquals(TestConstants.time, event.time)
29
+        assertEquals(User("acidburn", "libby", "root.localhost"), event.user)
30
+        assertEquals("#crashandburn", event.target)
31
+        assertEquals("hack the planet!", event.message)
32
+    }
33
+
34
+    @Test
35
+    fun `raises notice received event with no prefix`() {
36
+        val events = NoticeProcessor().process(
37
+                IrcMessage(emptyMap(), null, "NOTICE", params("#crashandburn", "hack the planet!")))
38
+        assertEquals(1, events.size)
39
+
40
+        val event = events[0] as NoticeReceived
41
+        assertEquals(TestConstants.time, event.time)
42
+        assertEquals(User("*"), event.user)
43
+        assertEquals("#crashandburn", event.target)
44
+        assertEquals("hack the planet!", event.message)
45
+    }
46
+
47
+    @Test
48
+    fun `raises CTCP reply received event with content`() {
49
+        val events = NoticeProcessor().process(
50
+                IrcMessage(emptyMap(), "acidburn!libby@root.localhost".toByteArray(), "NOTICE", params("#crashandburn", "\u0001PING 12345\u0001")))
51
+        assertEquals(1, events.size)
52
+
53
+        val event = events[0] as CtcpReplyReceived
54
+        assertEquals(TestConstants.time, event.time)
55
+        assertEquals(User("acidburn", "libby", "root.localhost"), event.user)
56
+        assertEquals("#crashandburn", event.target)
57
+        assertEquals("PING", event.type)
58
+        assertEquals("12345", event.content)
59
+    }
60
+
61
+    @Test
62
+    fun `raises CTCP reply received event without content`() {
63
+        val events = NoticeProcessor().process(
64
+                IrcMessage(emptyMap(), "acidburn!libby@root.localhost".toByteArray(), "NOTICE", params("#crashandburn", "\u0001PING\u0001")))
65
+        assertEquals(1, events.size)
66
+
67
+        val event = events[0] as CtcpReplyReceived
68
+        assertEquals(TestConstants.time, event.time)
69
+        assertEquals(User("acidburn", "libby", "root.localhost"), event.user)
70
+        assertEquals("#crashandburn", event.target)
71
+        assertEquals("PING", event.type)
72
+        assertEquals("", event.content)
73
+    }
74
+
75
+    @Test
76
+    fun `does nothing if prefix missing for CTCP replies`() {
77
+        val events = NoticeProcessor().process(
78
+                IrcMessage(emptyMap(), null, "NOTICE", params("#crashandburn", "\u0001BORK\u0001")))
79
+        assertEquals(0, events.size)
80
+    }
81
+}

Loading…
Cancel
Save