Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

ServerState.kt 4.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. package com.dmdirc.ktirc.model
  2. import com.dmdirc.ktirc.io.CaseMapping
  3. import kotlin.reflect.KClass
  4. /**
  5. * Contains the current state of a single IRC server.
  6. */
  7. class ServerState internal constructor(initialNickname: String, initialServerName: String) {
  8. /** Whether we've received the 'Welcome to IRC' (001) message. */
  9. internal var receivedWelcome = false
  10. /** The current status of the server. */
  11. var status = ServerStatus.Connecting
  12. internal set
  13. /**
  14. * What we believe our current nickname to be on the server.
  15. *
  16. * Initially this will be the nickname provided in the [Profile]. It will be updated to the actual nickname
  17. * in use when connecting. Once you have received a [com.dmdirc.ktirc.events.ServerWelcome] event you can
  18. * rely on this value being current.
  19. * */
  20. var localNickname: String = initialNickname
  21. internal set
  22. /**
  23. * The name of the server we are connected to.
  24. *
  25. * Initially this will be the hostname or IP address provided in the [Server]. It will be updated to the server's
  26. * self-reported hostname when connecting. Once you have received a [com.dmdirc.ktirc.events.ServerWelcome] event
  27. * you can rely on this value being current.
  28. */
  29. var serverName: String = initialServerName
  30. internal set
  31. /** The features that the server has declared it supports (from the 005 header). */
  32. val features = ServerFeatureMap()
  33. /** The capabilities we have negotiated with the server (from IRCv3). */
  34. val capabilities = CapabilitiesState()
  35. }
  36. /**
  37. * Maps known features onto their values, enforcing type safety.
  38. */
  39. class ServerFeatureMap {
  40. private val features = HashMap<ServerFeature<*>, Any?>()
  41. /**
  42. * Gets the value, or the default value, of the given feature.
  43. */
  44. @Suppress("UNCHECKED_CAST")
  45. operator fun <T : Any> get(feature: ServerFeature<T>) = features.getOrDefault(feature, feature.default) as? T? ?: feature.default
  46. internal operator fun set(feature: ServerFeature<*>, value: Any) {
  47. require(feature.type.isInstance(value))
  48. features[feature] = value
  49. }
  50. internal fun setAll(featureMap: ServerFeatureMap) = featureMap.features.forEach { feature, value -> features[feature] = value }
  51. internal fun reset(feature: ServerFeature<*>) = features.put(feature, null)
  52. }
  53. /**
  54. * Stores the mapping of mode prefixes received from the server.
  55. */
  56. data class ModePrefixMapping(val modes: String, val prefixes: String) {
  57. /** Determines whether the given character is a mode prefix (e.g. "@", "+"). */
  58. fun isPrefix(char: Char) = prefixes.contains(char)
  59. /** Gets the mode corresponding to the given prefix (e.g. "@" -> "o"). */
  60. fun getMode(prefix: Char) = modes[prefixes.indexOf(prefix)]
  61. /** Gets the modes corresponding to the given prefixes (e.g. "@+" -> "ov"). */
  62. fun getModes(prefixes: String) = String(prefixes.map(this::getMode).toCharArray())
  63. }
  64. /**
  65. * Describes a server feature determined from the 005 response.
  66. */
  67. sealed class ServerFeature<T : Any>(val name: String, val type: KClass<T>, val default: T? = null) {
  68. /** The network the server says it belongs to. */
  69. object Network : ServerFeature<String>("NETWORK", String::class)
  70. /** The case mapping the server uses, defaulting to RFC. */
  71. object ServerCaseMapping : ServerFeature<CaseMapping>("CASEMAPPING", CaseMapping::class, CaseMapping.Rfc)
  72. /** The mode prefixes the server uses, defaulting to ov/@+. */
  73. object ModePrefixes : ServerFeature<ModePrefixMapping>("PREFIX", ModePrefixMapping::class, ModePrefixMapping("ov", "@+"))
  74. /** The maximum number of channels a client may join. */
  75. object MaximumChannels : ServerFeature<Int>("MAXCHANNELS", Int::class) // TODO: CHANLIMIT also exists
  76. /** The modes supported in channels. */
  77. object ChannelModes : ServerFeature<String>("CHANMODES", String::class)
  78. /** The maximum length of a channel name, defaulting to 200. */
  79. object MaximumChannelNameLength : ServerFeature<Int>("CHANNELLEN", Int::class, 200)
  80. /** Whether or not the server supports extended who. */
  81. object WhoxSupport : ServerFeature<Boolean>("WHOX", Boolean::class, false)
  82. }
  83. internal val serverFeatures: Map<String, ServerFeature<*>> by lazy {
  84. ServerFeature::class.nestedClasses.map { it.objectInstance as ServerFeature<*> }.associateBy { it.name }
  85. }
  86. /**
  87. * Enumeration of the possible states of a server.
  88. */
  89. enum class ServerStatus {
  90. /** We are attempting to connect to the server. It is not yet ready for use. */
  91. Connecting,
  92. /** We are logging in, dealing with capabilities, etc. The server is not yet ready for use. */
  93. Negotiating,
  94. /** We are connected and commands can be sent. */
  95. Ready,
  96. }