ircinch 2.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (105) hide show
  1. checksums.yaml +7 -0
  2. data/.standard.yml +3 -0
  3. data/CHANGELOG.md +298 -0
  4. data/CODE_OF_CONDUCT.md +84 -0
  5. data/Gemfile +5 -0
  6. data/LICENSE.txt +23 -0
  7. data/README.md +195 -0
  8. data/Rakefile +14 -0
  9. data/docs/bot_options.md +454 -0
  10. data/docs/changes.md +541 -0
  11. data/docs/common_mistakes.md +60 -0
  12. data/docs/common_tasks.md +57 -0
  13. data/docs/encodings.md +69 -0
  14. data/docs/events.md +273 -0
  15. data/docs/getting_started.md +184 -0
  16. data/docs/logging.md +90 -0
  17. data/docs/migrating.md +267 -0
  18. data/docs/plugins.md +4 -0
  19. data/docs/readme.md +20 -0
  20. data/examples/basic/autovoice.rb +32 -0
  21. data/examples/basic/google.rb +35 -0
  22. data/examples/basic/hello.rb +14 -0
  23. data/examples/basic/join_part.rb +35 -0
  24. data/examples/basic/memo.rb +39 -0
  25. data/examples/basic/msg.rb +15 -0
  26. data/examples/basic/seen.rb +37 -0
  27. data/examples/basic/urban_dict.rb +36 -0
  28. data/examples/basic/url_shorten.rb +36 -0
  29. data/examples/plugins/autovoice.rb +37 -0
  30. data/examples/plugins/custom_prefix.rb +22 -0
  31. data/examples/plugins/dice_roll.rb +38 -0
  32. data/examples/plugins/google.rb +36 -0
  33. data/examples/plugins/hello.rb +21 -0
  34. data/examples/plugins/hooks.rb +34 -0
  35. data/examples/plugins/join_part.rb +41 -0
  36. data/examples/plugins/lambdas.rb +35 -0
  37. data/examples/plugins/last_nick.rb +24 -0
  38. data/examples/plugins/msg.rb +21 -0
  39. data/examples/plugins/multiple_matches.rb +32 -0
  40. data/examples/plugins/own_events.rb +37 -0
  41. data/examples/plugins/seen.rb +44 -0
  42. data/examples/plugins/timer.rb +22 -0
  43. data/examples/plugins/url_shorten.rb +34 -0
  44. data/ircinch.gemspec +43 -0
  45. data/lib/cinch/ban.rb +53 -0
  46. data/lib/cinch/bot.rb +476 -0
  47. data/lib/cinch/cached_list.rb +21 -0
  48. data/lib/cinch/callback.rb +22 -0
  49. data/lib/cinch/channel.rb +465 -0
  50. data/lib/cinch/channel_list.rb +31 -0
  51. data/lib/cinch/configuration/bot.rb +50 -0
  52. data/lib/cinch/configuration/dcc.rb +18 -0
  53. data/lib/cinch/configuration/plugins.rb +43 -0
  54. data/lib/cinch/configuration/sasl.rb +21 -0
  55. data/lib/cinch/configuration/ssl.rb +21 -0
  56. data/lib/cinch/configuration/timeouts.rb +16 -0
  57. data/lib/cinch/configuration.rb +75 -0
  58. data/lib/cinch/constants.rb +535 -0
  59. data/lib/cinch/dcc/dccable_object.rb +39 -0
  60. data/lib/cinch/dcc/incoming/send.rb +149 -0
  61. data/lib/cinch/dcc/incoming.rb +3 -0
  62. data/lib/cinch/dcc/outgoing/send.rb +123 -0
  63. data/lib/cinch/dcc/outgoing.rb +3 -0
  64. data/lib/cinch/dcc.rb +14 -0
  65. data/lib/cinch/exceptions.rb +48 -0
  66. data/lib/cinch/formatting.rb +127 -0
  67. data/lib/cinch/handler.rb +120 -0
  68. data/lib/cinch/handler_list.rb +92 -0
  69. data/lib/cinch/helpers.rb +230 -0
  70. data/lib/cinch/i_support.rb +100 -0
  71. data/lib/cinch/irc.rb +924 -0
  72. data/lib/cinch/log_filter.rb +23 -0
  73. data/lib/cinch/logger/formatted_logger.rb +100 -0
  74. data/lib/cinch/logger/zcbot_logger.rb +26 -0
  75. data/lib/cinch/logger.rb +171 -0
  76. data/lib/cinch/logger_list.rb +88 -0
  77. data/lib/cinch/mask.rb +69 -0
  78. data/lib/cinch/message.rb +397 -0
  79. data/lib/cinch/message_queue.rb +104 -0
  80. data/lib/cinch/mode_parser.rb +78 -0
  81. data/lib/cinch/network.rb +106 -0
  82. data/lib/cinch/open_ended_queue.rb +26 -0
  83. data/lib/cinch/pattern.rb +66 -0
  84. data/lib/cinch/plugin.rb +517 -0
  85. data/lib/cinch/plugin_list.rb +40 -0
  86. data/lib/cinch/rubyext/float.rb +5 -0
  87. data/lib/cinch/rubyext/module.rb +28 -0
  88. data/lib/cinch/rubyext/string.rb +35 -0
  89. data/lib/cinch/sasl/dh_blowfish.rb +73 -0
  90. data/lib/cinch/sasl/diffie_hellman.rb +50 -0
  91. data/lib/cinch/sasl/mechanism.rb +8 -0
  92. data/lib/cinch/sasl/plain.rb +29 -0
  93. data/lib/cinch/sasl.rb +36 -0
  94. data/lib/cinch/syncable.rb +83 -0
  95. data/lib/cinch/target.rb +199 -0
  96. data/lib/cinch/timer.rb +147 -0
  97. data/lib/cinch/user.rb +489 -0
  98. data/lib/cinch/user_list.rb +89 -0
  99. data/lib/cinch/utilities/deprecation.rb +18 -0
  100. data/lib/cinch/utilities/encoding.rb +39 -0
  101. data/lib/cinch/utilities/kernel.rb +15 -0
  102. data/lib/cinch/version.rb +6 -0
  103. data/lib/cinch.rb +7 -0
  104. data/lib/ircinch.rb +7 -0
  105. metadata +205 -0
@@ -0,0 +1,230 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Cinch
4
+ # The Helpers module contains a number of methods whose purpose is
5
+ # to make writing plugins easier by hiding parts of the API. The
6
+ # {#Channel} helper, for example, provides an easier way for turning
7
+ # a String object into a {Channel} object than directly using
8
+ # {ChannelList}: Compare `Channel("#some_channel")` with
9
+ # `bot.channel_list.find_ensured("#some_channel")`.
10
+ #
11
+ # The Helpers module automatically gets included in all plugins.
12
+ module Helpers
13
+ # @group Type casts
14
+
15
+ # Helper method for turning a String into a {Target} object.
16
+ #
17
+ # @param [String] target a target name
18
+ # @return [Target] a {Target} object
19
+ # @example
20
+ # on :message, /^message (.+)$/ do |m, target|
21
+ # Target(target).send "hi!"
22
+ # end
23
+ # @since 2.0.0
24
+ def Target(target)
25
+ return target if target.is_a?(Target)
26
+ Target.new(target, bot)
27
+ end
28
+
29
+ # Helper method for turning a String into a {Channel} object.
30
+ #
31
+ # @param [String] channel a channel name
32
+ # @return [Channel] a {Channel} object
33
+ # @example
34
+ # on :message, /^please join (#.+)$/ do |m, target|
35
+ # Channel(target).join
36
+ # end
37
+ # @since 1.0.0
38
+ def Channel(channel)
39
+ return channel if channel.is_a?(Channel)
40
+ bot.channel_list.find_ensured(channel)
41
+ end
42
+
43
+ # Helper method for turning a String into an {User} object.
44
+ #
45
+ # @param [String] user a user's nickname
46
+ # @return [User] an {User} object
47
+ # @example
48
+ # on :message, /^tell me everything about (.+)$/ do |m, target|
49
+ # user = User(target)
50
+ # m.reply "%s is named %s and connects from %s" % [user.nick, user.name, user.host]
51
+ # end
52
+ # @since 1.0.0
53
+ def User(user)
54
+ return user if user.is_a?(User)
55
+ if user == bot.nick
56
+ bot
57
+ else
58
+ bot.user_list.find_ensured(user)
59
+ end
60
+ end
61
+
62
+ # @example Used as a class method in a plugin
63
+ # timer 5, method: :some_method
64
+ # def some_method
65
+ # Channel("#cinch-bots").send(Time.now.to_s)
66
+ # end
67
+ #
68
+ # @example Used as an instance method in a plugin
69
+ # match "start timer"
70
+ # def execute(m)
71
+ # Timer(5) { puts "timer fired" }
72
+ # end
73
+ #
74
+ # @example Used as an instance method in a traditional `on` handler
75
+ # on :message, "start timer" do
76
+ # Timer(5) { puts "timer fired" }
77
+ # end
78
+ #
79
+ # @param [Numeric] interval Interval in seconds
80
+ # @param [Proc] block A proc to execute
81
+ # @option options [Symbol] :method (:timer) Method to call (only
82
+ # if no proc is provided)
83
+ # @option options [Boolean] :threaded (true) Call method in a
84
+ # thread?
85
+ # @option options [Integer] :shots (Float::INFINITY) How often
86
+ # should the timer fire?
87
+ # @option options [Boolean] :start_automatically (true) If true,
88
+ # the timer will automatically start after the bot finished
89
+ # connecting.
90
+ # @option options [Boolean] :stop_automaticall (true) If true, the
91
+ # timer will automatically stop when the bot disconnects.
92
+ # @return [Timer]
93
+ # @since 2.0.0
94
+ def Timer(interval, options = {}, &block)
95
+ options = {method: :timer, threaded: true, interval: interval}.merge(options)
96
+ block ||= method(options[:method])
97
+ timer = Cinch::Timer.new(bot, options, &block)
98
+ timer.start
99
+
100
+ if respond_to?(:timers)
101
+ timers << timer
102
+ end
103
+
104
+ timer
105
+ end
106
+
107
+ # @endgroup
108
+
109
+ # @group Logging
110
+
111
+ # Use this method to automatically log exceptions to the loggers.
112
+ #
113
+ # @example
114
+ # def my_method
115
+ # rescue_exception do
116
+ # something_that_might_raise()
117
+ # end
118
+ # end
119
+ #
120
+ # @return [void]
121
+ # @since 2.0.0
122
+ def rescue_exception
123
+ yield
124
+ rescue => e
125
+ bot.loggers.exception(e)
126
+ end
127
+
128
+ # (see Logger#log)
129
+ def log(messages, event = :debug, level = event)
130
+ if is_a?(Cinch::Plugin)
131
+ messages = Array(messages).map { |m|
132
+ "[#{self.class}] " + m
133
+ }
134
+ end
135
+ @bot.loggers.log(messages, event, level)
136
+ end
137
+
138
+ # (see Logger#debug)
139
+ def debug(message)
140
+ log(message, :debug)
141
+ end
142
+
143
+ # (see Logger#error)
144
+ def error(message)
145
+ log(message, :error)
146
+ end
147
+
148
+ # (see Logger#fatal)
149
+ def fatal(message)
150
+ log(message, :fatal)
151
+ end
152
+
153
+ # (see Logger#info)
154
+ def info(message)
155
+ log(message, :info)
156
+ end
157
+
158
+ # (see Logger#warn)
159
+ def warn(message)
160
+ log(message, :warn)
161
+ end
162
+
163
+ # (see Logger#incoming)
164
+ def incoming(message)
165
+ log(message, :incoming, :log)
166
+ end
167
+
168
+ # (see Logger#outgoing)
169
+ def outgoing(message)
170
+ log(message, :outgoing, :log)
171
+ end
172
+
173
+ # (see Logger#exception)
174
+ def exception(e)
175
+ log(e.message, :exception, :error)
176
+ end
177
+ # @endgroup
178
+
179
+ # @group Formatting
180
+
181
+ # (see Formatting.format)
182
+ def Format(*settings, string)
183
+ Formatting.format(*settings, string)
184
+ end
185
+ alias_method :Color, :Format # deprecated
186
+ undef_method(:Color) # yardoc hack
187
+
188
+ def Color(*args)
189
+ Cinch::Utilities::Deprecation.print_deprecation("2.2.0", "Helpers.Color", "Helpers.Format")
190
+ Format(*args)
191
+ end
192
+
193
+ # (see .sanitize)
194
+ def Sanitize(string)
195
+ Cinch::Helpers.sanitize(string)
196
+ end
197
+
198
+ # Deletes all characters in the ranges 0–8, 10–31 as well as the
199
+ # character 127, that is all non-printable characters and
200
+ # newlines.
201
+ #
202
+ # This method is useful for filtering text from external sources
203
+ # before sending it to IRC.
204
+ #
205
+ # Note that this method does not gracefully handle mIRC color
206
+ # codes, because it will leave the numeric arguments behind. If
207
+ # your text comes from IRC, you may want to filter it through
208
+ # {#Unformat} first. If you want to send sanitized input that
209
+ # includes your own formatting, first use this method, then add
210
+ # your formatting.
211
+ #
212
+ # There exist methods for sending messages that automatically
213
+ # call this method, namely {Target#safe_msg},
214
+ # {Target#safe_notice}, and {Target#safe_action}.
215
+ #
216
+ # @param [String] string The string to filter
217
+ # @return [String] The filtered string
218
+ # @since 2.2.0
219
+ def self.sanitize(string)
220
+ string.gsub(/[\x00-\x08\x0a-\x1f\x7f]/, "")
221
+ end
222
+
223
+ # (see Formatting.unformat)
224
+ def Unformat(string)
225
+ Formatting.unformat(string)
226
+ end
227
+
228
+ # @endgroup
229
+ end
230
+ end
@@ -0,0 +1,100 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Cinch
4
+ # This class exposes parsed ISUPPORT information of the IRC network.
5
+ class ISupport < Hash
6
+ @@mappings = {
7
+ %w[PREFIX] => lambda { |v|
8
+ modes, prefixes = v.match(/^\((.+)\)(.+)$/)[1..2]
9
+ h = {}
10
+ modes.chars.each_with_index do |c, i|
11
+ h[c] = prefixes[i]
12
+ end
13
+ h
14
+ },
15
+
16
+ %w[CHANTYPES] => lambda { |v| v.chars },
17
+ %w[CHANMODES] => lambda { |v|
18
+ h = {}
19
+ h["A"], h["B"], h["C"], h["D"] = v.split(",").map { |l| l.chars }
20
+ h
21
+ },
22
+
23
+ %w[MODES MAXCHANNELS NICKLEN MAXBANS TOPICLEN
24
+ KICKLEN CHANNELLEN CHIDLEN SILENCE AWAYLEN
25
+ MAXTARGETS WATCH MONITOR] => lambda { |v| v.to_i },
26
+
27
+ %w[CHANLIMIT MAXLIST IDCHAN] => lambda { |v|
28
+ h = {}
29
+ v.split(",").each do |pair|
30
+ args, num = pair.split(":")
31
+ args.chars.each do |arg|
32
+ h[arg] = num.to_i
33
+ end
34
+ end
35
+ h
36
+ },
37
+
38
+ %w[TARGMAX] => lambda { |v|
39
+ h = {}
40
+ v.split(",").each do |pair|
41
+ name, value = pair.split(":")
42
+ h[name] = value.to_i
43
+ end
44
+ h
45
+ },
46
+
47
+ %w[NETWORK] => lambda { |v| v },
48
+ %w[STATUSMSG] => lambda { |v| v.chars },
49
+ %w[CASEMAPPING] => lambda { |v| v.to_sym },
50
+ %w[ELIST] => lambda { |v| v.chars }
51
+ # TODO STD
52
+ }
53
+
54
+ def initialize(*args)
55
+ super
56
+ # by setting most numeric values to "Infinity", we let the
57
+ # server truncate messages and lists while at the same time
58
+ # allowing the use of strictness=:strict for servers that don't
59
+ # support ISUPPORT (hopefully none, anyway)
60
+
61
+ self["PREFIX"] = {"o" => "@", "v" => "+"}
62
+ self["CHANTYPES"] = ["#"]
63
+ self["CHANMODES"] = {
64
+ "A" => ["b"],
65
+ "B" => ["k"],
66
+ "C" => ["l"],
67
+ "D" => %w[i m n p s t r]
68
+ }
69
+ self["MODES"] = 1
70
+ self["NICKLEN"] = Float::INFINITY
71
+ self["MAXBANS"] = Float::INFINITY
72
+ self["TOPICLEN"] = Float::INFINITY
73
+ self["KICKLEN"] = Float::INFINITY
74
+ self["CHANNELLEN"] = Float::INFINITY
75
+ self["CHIDLEN"] = 5
76
+ self["AWAYLEN"] = Float::INFINITY
77
+ self["MAXTARGETS"] = 1
78
+ self["MAXCHANNELS"] = Float::INFINITY # deprecated
79
+ self["CHANLIMIT"] = {"#" => Float::INFINITY}
80
+ self["STATUSMSG"] = []
81
+ self["CASEMAPPING"] = :rfc1459
82
+ self["ELIST"] = []
83
+ self["MONITOR"] = 0
84
+ end
85
+
86
+ # @api private
87
+ # @return [void]
88
+ def parse(*options)
89
+ options.each do |option|
90
+ name, value = option.split("=")
91
+ if value
92
+ proc = @@mappings.find { |key, _| key.include?(name) }
93
+ self[name] = (proc && proc[1].call(value)) || value
94
+ else
95
+ self[name] = true
96
+ end
97
+ end
98
+ end
99
+ end
100
+ end