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.
- checksums.yaml +7 -0
- data/.standard.yml +3 -0
- data/CHANGELOG.md +298 -0
- data/CODE_OF_CONDUCT.md +84 -0
- data/Gemfile +5 -0
- data/LICENSE.txt +23 -0
- data/README.md +195 -0
- data/Rakefile +14 -0
- data/docs/bot_options.md +454 -0
- data/docs/changes.md +541 -0
- data/docs/common_mistakes.md +60 -0
- data/docs/common_tasks.md +57 -0
- data/docs/encodings.md +69 -0
- data/docs/events.md +273 -0
- data/docs/getting_started.md +184 -0
- data/docs/logging.md +90 -0
- data/docs/migrating.md +267 -0
- data/docs/plugins.md +4 -0
- data/docs/readme.md +20 -0
- data/examples/basic/autovoice.rb +32 -0
- data/examples/basic/google.rb +35 -0
- data/examples/basic/hello.rb +14 -0
- data/examples/basic/join_part.rb +35 -0
- data/examples/basic/memo.rb +39 -0
- data/examples/basic/msg.rb +15 -0
- data/examples/basic/seen.rb +37 -0
- data/examples/basic/urban_dict.rb +36 -0
- data/examples/basic/url_shorten.rb +36 -0
- data/examples/plugins/autovoice.rb +37 -0
- data/examples/plugins/custom_prefix.rb +22 -0
- data/examples/plugins/dice_roll.rb +38 -0
- data/examples/plugins/google.rb +36 -0
- data/examples/plugins/hello.rb +21 -0
- data/examples/plugins/hooks.rb +34 -0
- data/examples/plugins/join_part.rb +41 -0
- data/examples/plugins/lambdas.rb +35 -0
- data/examples/plugins/last_nick.rb +24 -0
- data/examples/plugins/msg.rb +21 -0
- data/examples/plugins/multiple_matches.rb +32 -0
- data/examples/plugins/own_events.rb +37 -0
- data/examples/plugins/seen.rb +44 -0
- data/examples/plugins/timer.rb +22 -0
- data/examples/plugins/url_shorten.rb +34 -0
- data/ircinch.gemspec +43 -0
- data/lib/cinch/ban.rb +53 -0
- data/lib/cinch/bot.rb +476 -0
- data/lib/cinch/cached_list.rb +21 -0
- data/lib/cinch/callback.rb +22 -0
- data/lib/cinch/channel.rb +465 -0
- data/lib/cinch/channel_list.rb +31 -0
- data/lib/cinch/configuration/bot.rb +50 -0
- data/lib/cinch/configuration/dcc.rb +18 -0
- data/lib/cinch/configuration/plugins.rb +43 -0
- data/lib/cinch/configuration/sasl.rb +21 -0
- data/lib/cinch/configuration/ssl.rb +21 -0
- data/lib/cinch/configuration/timeouts.rb +16 -0
- data/lib/cinch/configuration.rb +75 -0
- data/lib/cinch/constants.rb +535 -0
- data/lib/cinch/dcc/dccable_object.rb +39 -0
- data/lib/cinch/dcc/incoming/send.rb +149 -0
- data/lib/cinch/dcc/incoming.rb +3 -0
- data/lib/cinch/dcc/outgoing/send.rb +123 -0
- data/lib/cinch/dcc/outgoing.rb +3 -0
- data/lib/cinch/dcc.rb +14 -0
- data/lib/cinch/exceptions.rb +48 -0
- data/lib/cinch/formatting.rb +127 -0
- data/lib/cinch/handler.rb +120 -0
- data/lib/cinch/handler_list.rb +92 -0
- data/lib/cinch/helpers.rb +230 -0
- data/lib/cinch/i_support.rb +100 -0
- data/lib/cinch/irc.rb +924 -0
- data/lib/cinch/log_filter.rb +23 -0
- data/lib/cinch/logger/formatted_logger.rb +100 -0
- data/lib/cinch/logger/zcbot_logger.rb +26 -0
- data/lib/cinch/logger.rb +171 -0
- data/lib/cinch/logger_list.rb +88 -0
- data/lib/cinch/mask.rb +69 -0
- data/lib/cinch/message.rb +397 -0
- data/lib/cinch/message_queue.rb +104 -0
- data/lib/cinch/mode_parser.rb +78 -0
- data/lib/cinch/network.rb +106 -0
- data/lib/cinch/open_ended_queue.rb +26 -0
- data/lib/cinch/pattern.rb +66 -0
- data/lib/cinch/plugin.rb +517 -0
- data/lib/cinch/plugin_list.rb +40 -0
- data/lib/cinch/rubyext/float.rb +5 -0
- data/lib/cinch/rubyext/module.rb +28 -0
- data/lib/cinch/rubyext/string.rb +35 -0
- data/lib/cinch/sasl/dh_blowfish.rb +73 -0
- data/lib/cinch/sasl/diffie_hellman.rb +50 -0
- data/lib/cinch/sasl/mechanism.rb +8 -0
- data/lib/cinch/sasl/plain.rb +29 -0
- data/lib/cinch/sasl.rb +36 -0
- data/lib/cinch/syncable.rb +83 -0
- data/lib/cinch/target.rb +199 -0
- data/lib/cinch/timer.rb +147 -0
- data/lib/cinch/user.rb +489 -0
- data/lib/cinch/user_list.rb +89 -0
- data/lib/cinch/utilities/deprecation.rb +18 -0
- data/lib/cinch/utilities/encoding.rb +39 -0
- data/lib/cinch/utilities/kernel.rb +15 -0
- data/lib/cinch/version.rb +6 -0
- data/lib/cinch.rb +7 -0
- data/lib/ircinch.rb +7 -0
- 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
|