You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

IrcMessage.kt 2.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. package com.dmdirc.ktirc.model
  2. import com.dmdirc.ktirc.events.EventMetadata
  3. import com.dmdirc.ktirc.util.currentTimeProvider
  4. import com.dmdirc.ktirc.util.currentTimeZoneProvider
  5. import com.dmdirc.ktirc.util.logger
  6. import java.time.Instant
  7. import java.time.LocalDateTime
  8. import java.util.logging.Level
  9. /**
  10. * Represents an IRC protocol message.
  11. */
  12. internal class IrcMessage(val tags: Map<MessageTag, String>, val prefix: ByteArray?, val command: String, val params: List<ByteArray>) {
  13. private val log by logger()
  14. /** The time at which the message was sent, or our best guess at it. */
  15. val metadata = EventMetadata(
  16. time = tags[MessageTag.ServerTime]?.toLocalDateOrNull() ?: currentTimeProvider(),
  17. batchId = tags[MessageTag.Batch],
  18. messageId = tags[MessageTag.MessageId],
  19. label = tags[MessageTag.Label])
  20. /** The user that generated the message, if any. */
  21. val sourceUser = prefix?.asUser()?.apply {
  22. tags[MessageTag.AccountName]?.let { account = it }
  23. }
  24. private fun String.toLocalDateOrNull() = try {
  25. LocalDateTime.ofInstant(Instant.parse(this), currentTimeZoneProvider())
  26. } catch (e: Exception) {
  27. log.log(Level.WARNING, e) { "Received unparsable server-time tag: $this" }
  28. null
  29. }
  30. override fun toString(): String {
  31. return "IrcMessage(tags=$tags, prefix=${prefix?.let { String(prefix) }}, command='$command', params=${params.map { String(it) }}, metadata=$metadata, sourceUser=$sourceUser)"
  32. }
  33. }
  34. /**
  35. * Supported tags that may be applied to messages.
  36. */
  37. @Suppress("unused")
  38. sealed class MessageTag(val name: String) {
  39. /** Specifies the account name of the user, if the `account-tag` capability is negotiated. */
  40. object AccountName : MessageTag("account")
  41. /** Specifies the ID that a batch message belongs to. */
  42. object Batch : MessageTag("batch")
  43. /** An arbitrary label to identify the response to messages we generate. */
  44. object Label : MessageTag("draft/label")
  45. /** A unique ID for the message, used to reply, react, edit, delete, etc. */
  46. object MessageId : MessageTag("draft/msgid")
  47. /** Used to identify a message ID that was replied to, to enable threaded conversations. */
  48. object Reply : MessageTag("+draft/reply")
  49. /** Used to specify a slack-like reaction to another message. */
  50. object React : MessageTag("+draft/react")
  51. /** Specifies the time the server received the message, if the `server-time` capability is negotiated. */
  52. object ServerTime : MessageTag("time")
  53. }
  54. internal val messageTags: Map<String, MessageTag> by lazy {
  55. MessageTag::class.nestedClasses.map { it.objectInstance as MessageTag }.associateBy { it.name }
  56. }