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.

Dsl.kt 5.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. package com.dmdirc.ktirc
  2. /**
  3. * Dsl marker for [IrcClient] dsl.
  4. */
  5. @DslMarker
  6. annotation class IrcClientDsl
  7. internal data class IrcClientConfig(val server: ServerConfig, val profile: ProfileConfig, val sasl: SaslConfig?)
  8. /**
  9. * Dsl for configuring an IRC Client.
  10. *
  11. * [server] and [profile] blocks are required. The full range of configuration options are:
  12. *
  13. * ```
  14. * server {
  15. * host = "irc.example.com" // Required
  16. * port = 6667
  17. * useTls = true
  18. * password = "H4ckTh3Pl4n3t"
  19. * }
  20. *
  21. * profile {
  22. * nickname = "MyBot" // Required
  23. * username = "bot
  24. * realName = "Botomatic v1.2"
  25. * }
  26. *
  27. * sasl {
  28. * mechanisms += "PLAIN" // or to set the list from scratch:
  29. * mechanisms("PLAIN")
  30. *
  31. * username = "botaccount"
  32. * password = "s3cur3"
  33. * }
  34. * ```
  35. */
  36. @IrcClientDsl
  37. class IrcClientConfigBuilder {
  38. private var server: ServerConfig? = null
  39. set(value) {
  40. check(field == null) { "server may only be specified once" }
  41. check(!value?.host.isNullOrEmpty()) { "server.host must be specified" }
  42. field = value
  43. }
  44. private var profile: ProfileConfig? = null
  45. set(value) {
  46. check(field == null) { "profile may only be specified once" }
  47. check(!value?.nickname.isNullOrEmpty()) { "profile.nickname must be specified" }
  48. field = value
  49. }
  50. private var sasl: SaslConfig? = null
  51. set(value) {
  52. check(field == null) { "sasl may only be specified once" }
  53. field = value
  54. }
  55. /**
  56. * Configures the server that the IrcClient will connect to.
  57. *
  58. * See [ServerConfig] for details of each parameter.
  59. *
  60. * @param block Optional additional configuration to apply to the [ServerConfig]
  61. */
  62. @IrcClientDsl
  63. fun server(host: String? = null, port: Int? = null, useTls: Boolean? = null, password: String? = null, block: (ServerConfig.() -> Unit)? = null) {
  64. server = ServerConfig().apply {
  65. host?.let { this.host = it }
  66. port?.let { this.port = it }
  67. useTls?.let { this.useTls = it }
  68. password?.let { this.password = it }
  69. block?.let { apply(it) }
  70. }
  71. }
  72. /**
  73. * Configures the profile of the IrcClient user.
  74. *
  75. * See [ProfileConfig] for details of each parameter.
  76. *
  77. * @param block Optional additional configuration to apply to the [ProfileConfig]
  78. */
  79. @IrcClientDsl
  80. fun profile(nickname: String? = null, username: String? = null, realName: String? = null, block: (ProfileConfig.() -> Unit)? = null) {
  81. profile = ProfileConfig().apply {
  82. nickname?.let { this.nickname = it }
  83. username?.let { this.username = it }
  84. realName?.let { this.realName = it }
  85. block?.let { apply(it) }
  86. }
  87. }
  88. /**
  89. * Configures SASL authentication (optional).
  90. */
  91. @IrcClientDsl
  92. fun sasl(block: SaslConfig.() -> Unit) {
  93. sasl = SaslConfig().apply(block)
  94. }
  95. internal fun build() =
  96. IrcClientConfig(
  97. checkNotNull(server) { "Server must be specified " },
  98. checkNotNull(profile) { "Profile must be specified" },
  99. sasl)
  100. }
  101. /**
  102. * Dsl for configuring a server.
  103. */
  104. @IrcClientDsl
  105. class ServerConfig {
  106. /** The hostname (or IP address) of the server to connect to. */
  107. var host: String = ""
  108. /** The port to connect on. Defaults to 6667. */
  109. var port: Int = 6667
  110. /** Whether or not to use TLS (an encrypted connection). */
  111. var useTls: Boolean = false
  112. /** The password required to connect to the server, if any. */
  113. var password: String? = null
  114. }
  115. /**
  116. * Dsl for configuring a profile.
  117. */
  118. @IrcClientDsl
  119. class ProfileConfig {
  120. /** The initial nickname to use when connecting. */
  121. var nickname: String = ""
  122. /** The username (used in place of an ident response) to provide to the server. */
  123. var username: String = "KtIrc"
  124. /** The "real name" to provide to the server. */
  125. var realName: String = "KtIrc User"
  126. }
  127. /**
  128. * Dsl for configuring SASL authentication.
  129. *
  130. * By default the `PLAIN`, `SCRAM-SHA-1`, and `SCRAM-SHA-256` methods will be enabled if SASL is configured.
  131. *
  132. * You can modify the mechanisms either by editing the [mechanisms] collection:
  133. *
  134. * ```
  135. * mechanisms += "EXTERNAL"
  136. * mechanisms.remove("PLAIN")
  137. * ```
  138. *
  139. * or by calling the [mechanisms] function with all the mechanisms you wish
  140. * to enable:
  141. *
  142. * ```
  143. * mechanisms("PLAIN", "EXTERNAL")
  144. * ```
  145. *
  146. * Priority of mechanisms is determined by KtIrc, regardless of the order
  147. * they are specified in here.
  148. */
  149. @IrcClientDsl
  150. class SaslConfig {
  151. /** The SASL mechanisms to enable. */
  152. val mechanisms: MutableCollection<String> = mutableSetOf("PLAIN", "SCRAM-SHA-1", "SCRAM-SHA-256")
  153. /** The username to provide when authenticating using SASL. */
  154. var username: String = ""
  155. /** The username to provide when authenticating using SASL. */
  156. var password: String = ""
  157. @IrcClientDsl
  158. fun mechanisms(vararg methods: String) {
  159. with(this.mechanisms) {
  160. clear()
  161. addAll(methods)
  162. }
  163. }
  164. }