Create MessageParser, use in Reader, add logs

This commit is contained in:
2026-08-12 13:28:45 +01:00
parent 25333482c1
commit b35bb5b679
3 changed files with 48 additions and 25 deletions
@@ -1,39 +1,58 @@
package com.shr4pnel.ferretirc
import com.shr4pnel.ferretirc.net.ClientMessage
import com.shr4pnel.ferretirc.net.messages.ClientMessage
import com.shr4pnel.ferretirc.net.Connection
import com.shr4pnel.ferretirc.net.MessageReader
import com.shr4pnel.ferretirc.net.MessageWriter
import com.shr4pnel.ferretirc.net.messages.ServerMessage
import io.github.oshai.kotlinlogging.KotlinLoggingConfiguration
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.cancel
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.launch
import java.net.URL
class IrcClient(val nick: String, val sock: URL) {
val port: Int = sock.port
val hostname: String = sock.host
val scope = CoroutineScope(SupervisorJob() + Dispatchers.IO)
private val connection = Connection(hostname, port, scope)
lateinit var messages: Channel<String>
class IrcClient(hostname: String, port: Int) {
init {
require(port != -1, fun() = "A port must be specified in your argument to IRCClient")
require(hostname.isNotEmpty(), fun() = "A port must be specified in your argument to IRCClient")
KotlinLoggingConfiguration.logStartupMessage = false
}
val scope = CoroutineScope(SupervisorJob() + Dispatchers.IO)
@PublishedApi
internal val connection = Connection(hostname, port, scope)
suspend fun connect() {
connection.connect()
messages = connection.reader.incomingMessages
}
fun queueMessage(message: ClientMessage) = scope.launch {
suspend fun queueMessage(message: ClientMessage) {
connection.writer.outgoingMessages.send(message)
}
suspend fun queueMessages(vararg messages: ClientMessage) {
messages.forEach {
connection.writer.outgoingMessages.send(it)
}
}
fun close() {
scope.cancel()
}
/**
* Return the next Server Message meeting condition
* @param predicate A function to filter a message based on its parameters
*/
suspend inline fun <reified T : ServerMessage> waitForNext(noinline predicate: (T) -> Boolean = { true }): T =
connection.reader.waitForNext(T::class, predicate)
suspend fun register(nick: String, realName: String? = null, password: String? = null) {
val messages = buildList {
if (!password.isNullOrEmpty()) add(ClientMessage.Pass(password))
add(ClientMessage.Cap.LS())
add(ClientMessage.Nick(nick))
if (!realName.isNullOrEmpty()) add(ClientMessage.User(nick, realName))
else add(ClientMessage.User(nick, nick))
add(ClientMessage.Cap.END())
}
queueMessages(*messages.toTypedArray())
}
}
@@ -1,5 +1,6 @@
package com.shr4pnel.ferretirc.net
import com.shr4pnel.ferretirc.net.messages.ClientMessage
import io.ktor.network.sockets.Socket
import io.ktor.network.sockets.aSocket
import kotlinx.coroutines.CoroutineScope
@@ -1,5 +1,7 @@
package com.shr4pnel.ferretirc.net
import com.shr4pnel.ferretirc.net.messages.MessageIO
import io.github.oshai.kotlinlogging.KotlinLogging
import io.ktor.network.sockets.Socket
import io.ktor.network.sockets.openWriteChannel
import io.ktor.utils.io.ByteWriteChannel
@@ -7,16 +9,17 @@ import io.ktor.utils.io.writeFully
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
class MessageWriter(socket: Socket, scope: CoroutineScope): MessageIO(socket, scope) {
class MessageWriter(socket: Socket, scope: CoroutineScope) : MessageIO(socket, scope) {
private lateinit var send: ByteWriteChannel
private val logger = KotlinLogging.logger("MessageWriter")
override suspend fun start() {
override fun start() = scope.launch {
send = socket.openWriteChannel()
scope.launch {
for (msg in outgoingMessages) {
send.writeFully(msg.toWire())
send.flush()
}
for (msg in outgoingMessages) {
logger.debug { msg.toWireIntermediate() }
send.writeFully(msg.toWire())
send.flush()
}
}
}
}