cinch 1.1.3 → 2.0.0.pre.1
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.
- data/LICENSE +1 -0
- data/README.md +3 -3
- data/docs/bot_options.md +435 -0
- data/docs/changes.md +440 -0
- data/docs/common_mistakes.md +35 -0
- data/docs/common_tasks.md +47 -0
- data/docs/encodings.md +67 -0
- data/docs/events.md +272 -0
- data/docs/logging.md +5 -0
- data/docs/migrating.md +267 -0
- data/docs/readme.md +18 -0
- data/examples/plugins/custom_prefix.rb +1 -1
- data/examples/plugins/dice_roll.rb +38 -0
- data/examples/plugins/lambdas.rb +1 -1
- data/examples/plugins/memo.rb +16 -10
- data/examples/plugins/url_shorten.rb +1 -0
- data/lib/cinch.rb +5 -60
- data/lib/cinch/ban.rb +13 -7
- data/lib/cinch/bot.rb +228 -403
- data/lib/cinch/{cache_manager.rb → cached_list.rb} +5 -1
- data/lib/cinch/callback.rb +3 -0
- data/lib/cinch/channel.rb +119 -195
- data/lib/cinch/{channel_manager.rb → channel_list.rb} +6 -3
- data/lib/cinch/configuration.rb +73 -0
- data/lib/cinch/configuration/bot.rb +47 -0
- data/lib/cinch/configuration/dcc.rb +16 -0
- data/lib/cinch/configuration/plugins.rb +41 -0
- data/lib/cinch/configuration/sasl.rb +17 -0
- data/lib/cinch/configuration/ssl.rb +19 -0
- data/lib/cinch/configuration/storage.rb +37 -0
- data/lib/cinch/configuration/timeouts.rb +14 -0
- data/lib/cinch/constants.rb +531 -369
- data/lib/cinch/dcc.rb +12 -0
- data/lib/cinch/dcc/dccable_object.rb +37 -0
- data/lib/cinch/dcc/incoming.rb +1 -0
- data/lib/cinch/dcc/incoming/send.rb +131 -0
- data/lib/cinch/dcc/outgoing.rb +1 -0
- data/lib/cinch/dcc/outgoing/send.rb +115 -0
- data/lib/cinch/exceptions.rb +8 -1
- data/lib/cinch/formatting.rb +106 -0
- data/lib/cinch/handler.rb +104 -0
- data/lib/cinch/handler_list.rb +86 -0
- data/lib/cinch/helpers.rb +167 -10
- data/lib/cinch/irc.rb +525 -110
- data/lib/cinch/isupport.rb +11 -9
- data/lib/cinch/logger.rb +168 -0
- data/lib/cinch/logger/formatted_logger.rb +72 -55
- data/lib/cinch/logger/zcbot_logger.rb +9 -24
- data/lib/cinch/logger_list.rb +62 -0
- data/lib/cinch/mask.rb +19 -10
- data/lib/cinch/message.rb +94 -28
- data/lib/cinch/message_queue.rb +70 -28
- data/lib/cinch/mode_parser.rb +6 -1
- data/lib/cinch/network.rb +104 -0
- data/lib/cinch/{rubyext/queue.rb → open_ended_queue.rb} +8 -1
- data/lib/cinch/pattern.rb +24 -4
- data/lib/cinch/plugin.rb +352 -177
- data/lib/cinch/plugin_list.rb +35 -0
- data/lib/cinch/rubyext/float.rb +3 -0
- data/lib/cinch/rubyext/module.rb +7 -0
- data/lib/cinch/rubyext/string.rb +9 -0
- data/lib/cinch/sasl.rb +34 -0
- data/lib/cinch/sasl/dh_blowfish.rb +71 -0
- data/lib/cinch/sasl/diffie_hellman.rb +47 -0
- data/lib/cinch/sasl/mechanism.rb +6 -0
- data/lib/cinch/sasl/plain.rb +26 -0
- data/lib/cinch/storage.rb +62 -0
- data/lib/cinch/storage/null.rb +12 -0
- data/lib/cinch/storage/yaml.rb +96 -0
- data/lib/cinch/syncable.rb +13 -1
- data/lib/cinch/target.rb +144 -0
- data/lib/cinch/timer.rb +145 -0
- data/lib/cinch/user.rb +169 -225
- data/lib/cinch/{user_manager.rb → user_list.rb} +7 -2
- data/lib/cinch/utilities/deprecation.rb +12 -0
- data/lib/cinch/utilities/encoding.rb +54 -0
- data/lib/cinch/utilities/kernel.rb +13 -0
- data/lib/cinch/utilities/string.rb +13 -0
- data/lib/cinch/version.rb +4 -0
- metadata +88 -47
- data/lib/cinch/logger/logger.rb +0 -44
- data/lib/cinch/logger/null_logger.rb +0 -18
- data/lib/cinch/rubyext/infinity.rb +0 -1
data/lib/cinch/isupport.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
module Cinch
|
2
|
+
# This class exposes parsed ISUPPORT information of the IRC network.
|
2
3
|
class ISupport < Hash
|
3
4
|
@@mappings = {
|
4
5
|
%w[PREFIX] => lambda {|v|
|
@@ -19,7 +20,7 @@ module Cinch
|
|
19
20
|
|
20
21
|
%w[MODES MAXCHANNELS NICKLEN MAXBANS TOPICLEN
|
21
22
|
KICKLEN CHANNELLEN CHIDLEN SILENCE AWAYLEN
|
22
|
-
MAXTARGETS WATCH] => lambda {|v| v.to_i},
|
23
|
+
MAXTARGETS WATCH MONITOR] => lambda {|v| v.to_i},
|
23
24
|
|
24
25
|
%w[CHANLIMIT MAXLIST IDCHAN] => lambda {|v|
|
25
26
|
h = {}
|
@@ -64,19 +65,20 @@ module Cinch
|
|
64
65
|
"D" => %w[i m n p s t r]
|
65
66
|
}
|
66
67
|
self["MODES"] = 1
|
67
|
-
self["NICKLEN"] =
|
68
|
-
self["MAXBANS"] =
|
69
|
-
self["TOPICLEN"] =
|
70
|
-
self["KICKLEN"] =
|
71
|
-
self["CHANNELLEN"] =
|
68
|
+
self["NICKLEN"] = Float::INFINITY
|
69
|
+
self["MAXBANS"] = Float::INFINITY
|
70
|
+
self["TOPICLEN"] = Float::INFINITY
|
71
|
+
self["KICKLEN"] = Float::INFINITY
|
72
|
+
self["CHANNELLEN"] = Float::INFINITY
|
72
73
|
self["CHIDLEN"] = 5
|
73
|
-
self["AWAYLEN"] =
|
74
|
+
self["AWAYLEN"] = Float::INFINITY
|
74
75
|
self["MAXTARGETS"] = 1
|
75
|
-
self["MAXCHANNELS"] =
|
76
|
-
self["CHANLIMIT"] = {"#" =>
|
76
|
+
self["MAXCHANNELS"] = Float::INFINITY # deprecated
|
77
|
+
self["CHANLIMIT"] = {"#" => Float::INFINITY}
|
77
78
|
self["STATUSMSG"] = ["@", "+"]
|
78
79
|
self["CASEMAPPING"] = :rfc1459
|
79
80
|
self["ELIST"] = []
|
81
|
+
self["MONITOR"] = 0
|
80
82
|
end
|
81
83
|
|
82
84
|
# @api private
|
data/lib/cinch/logger.rb
ADDED
@@ -0,0 +1,168 @@
|
|
1
|
+
module Cinch
|
2
|
+
# This is the base logger class from which all loggers have to
|
3
|
+
# inherit.
|
4
|
+
#
|
5
|
+
# @version 2.0.0
|
6
|
+
class Logger
|
7
|
+
# @private
|
8
|
+
LevelOrder = [:debug, :log, :info, :warn, :error, :fatal]
|
9
|
+
|
10
|
+
# @return [Array<:debug, :log, :info, :warn, :error, :fatal>]
|
11
|
+
# The minimum level of events to log
|
12
|
+
attr_accessor :level
|
13
|
+
|
14
|
+
# @return [Mutex]
|
15
|
+
# @api private
|
16
|
+
attr_reader :mutex
|
17
|
+
|
18
|
+
# @return [IO]
|
19
|
+
# @api private
|
20
|
+
attr_reader :output
|
21
|
+
|
22
|
+
# @param [IO] output The I/O object to write log data to
|
23
|
+
def initialize(output)
|
24
|
+
@output = output
|
25
|
+
@mutex = Mutex.new
|
26
|
+
@level = :debug
|
27
|
+
end
|
28
|
+
|
29
|
+
# Logs a debugging message.
|
30
|
+
#
|
31
|
+
# @param [String] message
|
32
|
+
# @return [void]
|
33
|
+
# @version 2.0.0
|
34
|
+
def debug(message)
|
35
|
+
log(message, :debug)
|
36
|
+
end
|
37
|
+
|
38
|
+
# Logs an error message.
|
39
|
+
#
|
40
|
+
# @param [String] message
|
41
|
+
# @return [void]
|
42
|
+
# @since 2.0.0
|
43
|
+
def error(message)
|
44
|
+
log(message, :error)
|
45
|
+
end
|
46
|
+
|
47
|
+
# Logs a fatal message.
|
48
|
+
#
|
49
|
+
# @param [String] message
|
50
|
+
# @return [void]
|
51
|
+
# @since 2.0.0
|
52
|
+
def fatal(message)
|
53
|
+
log(message, :fatal)
|
54
|
+
end
|
55
|
+
|
56
|
+
# Logs an info message.
|
57
|
+
#
|
58
|
+
# @param [String] message
|
59
|
+
# @return [void]
|
60
|
+
# @since 2.0.0
|
61
|
+
def info(message)
|
62
|
+
log(message, :info)
|
63
|
+
end
|
64
|
+
|
65
|
+
# Logs a warning message.
|
66
|
+
#
|
67
|
+
# @param [String] message
|
68
|
+
# @return [void]
|
69
|
+
# @since 2.0.0
|
70
|
+
def warn(message)
|
71
|
+
log(message, :warn)
|
72
|
+
end
|
73
|
+
|
74
|
+
# Logs an incoming IRC message.
|
75
|
+
#
|
76
|
+
# @param [String] message
|
77
|
+
# @return [void]
|
78
|
+
# @since 2.0.0
|
79
|
+
def incoming(message)
|
80
|
+
log(message, :incoming, :log)
|
81
|
+
end
|
82
|
+
|
83
|
+
# Logs an outgoing IRC message.
|
84
|
+
#
|
85
|
+
# @param [String] message
|
86
|
+
# @return [void]
|
87
|
+
# @since 2.0.0
|
88
|
+
def outgoing(message)
|
89
|
+
log(message, :outgoing, :log)
|
90
|
+
end
|
91
|
+
|
92
|
+
# Logs an exception.
|
93
|
+
#
|
94
|
+
# @param [Exception] e
|
95
|
+
# @return [void]
|
96
|
+
# @since 2.0.0
|
97
|
+
def exception(e)
|
98
|
+
log(e.message, :exception, :error)
|
99
|
+
end
|
100
|
+
|
101
|
+
# Logs a message.
|
102
|
+
#
|
103
|
+
# @param [String, Array] messages The message(s) to log
|
104
|
+
# @param [Symbol<:debug, :incoming, :outgoing, :info, :warn,
|
105
|
+
# :exception, :error, :fatal>] event The kind of event that
|
106
|
+
# triggered the message
|
107
|
+
# @param [Symbol<:debug, :info, :warn, :error, :fatal>] level The level of the message
|
108
|
+
# @return [void]
|
109
|
+
# @version 2.0.0
|
110
|
+
def log(messages, event = :debug, level = event)
|
111
|
+
return unless will_log?(level)
|
112
|
+
@mutex.synchronize do
|
113
|
+
Array(messages).each do |message|
|
114
|
+
message = format_general(message)
|
115
|
+
message = format_message(message, event)
|
116
|
+
|
117
|
+
next if message.nil?
|
118
|
+
@output.puts message.encode("locale", {:invalid => :replace, :undef => :replace})
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
# @param [Symbol<:debug, :info, :warn, :error, :fatal>] level
|
124
|
+
# @return [Boolean] Whether the currently set logging level will
|
125
|
+
# allow the passed in level to be logged
|
126
|
+
# @since 2.0.0
|
127
|
+
def will_log?(level)
|
128
|
+
LevelOrder.index(level) >= LevelOrder.index(@level)
|
129
|
+
end
|
130
|
+
|
131
|
+
private
|
132
|
+
def format_message(message, level)
|
133
|
+
__send__ "format_#{level}", message
|
134
|
+
end
|
135
|
+
|
136
|
+
def format_general(message)
|
137
|
+
message
|
138
|
+
end
|
139
|
+
|
140
|
+
def format_debug(message)
|
141
|
+
message
|
142
|
+
end
|
143
|
+
|
144
|
+
def format_error(message)
|
145
|
+
message
|
146
|
+
end
|
147
|
+
|
148
|
+
def format_info(message)
|
149
|
+
message
|
150
|
+
end
|
151
|
+
|
152
|
+
def format_warn(message)
|
153
|
+
message
|
154
|
+
end
|
155
|
+
|
156
|
+
def format_incoming(message)
|
157
|
+
message
|
158
|
+
end
|
159
|
+
|
160
|
+
def format_outgoing(message)
|
161
|
+
message
|
162
|
+
end
|
163
|
+
|
164
|
+
def format_exception(message)
|
165
|
+
message
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
@@ -1,63 +1,31 @@
|
|
1
|
-
require "cinch/logger
|
1
|
+
require "cinch/logger"
|
2
|
+
|
2
3
|
module Cinch
|
3
|
-
|
4
|
-
#
|
5
|
-
|
6
|
-
|
7
|
-
|
4
|
+
class Logger
|
5
|
+
# @version 2.0.0
|
6
|
+
class FormattedLogger < Logger
|
7
|
+
# @private
|
8
|
+
Colors = {
|
8
9
|
:reset => "\e[0m",
|
9
10
|
:bold => "\e[1m",
|
10
11
|
:red => "\e[31m",
|
11
12
|
:green => "\e[32m",
|
12
13
|
:yellow => "\e[33m",
|
13
14
|
:blue => "\e[34m",
|
15
|
+
:black => "\e[30m",
|
16
|
+
:bg_white => "\e[47m",
|
14
17
|
}
|
15
18
|
|
16
|
-
#
|
17
|
-
def
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
# (see Logger::Logger#debug)
|
23
|
-
def debug(messages)
|
24
|
-
log(messages, :debug)
|
19
|
+
# (see Logger#exception)
|
20
|
+
def exception(e)
|
21
|
+
lines = ["#{e.backtrace.first}: #{e.message} (#{e.class})"]
|
22
|
+
lines.concat e.backtrace[1..-1].map {|s| "\t" + s}
|
23
|
+
log(lines, :exception, :error)
|
25
24
|
end
|
26
25
|
|
27
|
-
|
28
|
-
def
|
29
|
-
|
30
|
-
messages = [messages].flatten.map {|s| s.to_s.chomp}
|
31
|
-
messages.each do |msg|
|
32
|
-
message = Time.now.strftime("[%Y/%m/%d %H:%M:%S.%L] ")
|
33
|
-
if kind == :debug
|
34
|
-
prefix = colorize("!! ", :yellow)
|
35
|
-
message << prefix + msg
|
36
|
-
else
|
37
|
-
pre, msg = msg.split(" :", 2)
|
38
|
-
pre_parts = pre.split(" ")
|
39
|
-
|
40
|
-
if kind == :incoming
|
41
|
-
prefix = colorize(">> ", :green)
|
42
|
-
|
43
|
-
if pre_parts.size == 1
|
44
|
-
pre_parts[0] = colorize(pre_parts[0], :bold)
|
45
|
-
else
|
46
|
-
pre_parts[0] = colorize(pre_parts[0], :blue)
|
47
|
-
pre_parts[1] = colorize(pre_parts[1], :bold)
|
48
|
-
end
|
49
|
-
|
50
|
-
elsif kind == :outgoing
|
51
|
-
prefix = colorize("<< ", :red)
|
52
|
-
pre_parts[0] = colorize(pre_parts[0], :bold)
|
53
|
-
end
|
54
|
-
|
55
|
-
message << prefix + pre_parts.join(" ")
|
56
|
-
message << colorize(" :#{msg}", :yellow) if msg
|
57
|
-
end
|
58
|
-
@output.puts message.encode("locale", {:invalid => :replace, :undef => :replace})
|
59
|
-
end
|
60
|
-
end
|
26
|
+
private
|
27
|
+
def timestamp
|
28
|
+
Time.now.strftime("[%Y/%m/%d %H:%M:%S.%L]")
|
61
29
|
end
|
62
30
|
|
63
31
|
# @api private
|
@@ -66,14 +34,63 @@ module Cinch
|
|
66
34
|
# @return [String] colorized string
|
67
35
|
def colorize(text, *codes)
|
68
36
|
return text unless @output.tty?
|
69
|
-
|
37
|
+
codes = Colors.values_at(*codes).join
|
38
|
+
text = text.gsub(/#{Regexp.escape(Colors[:reset])}/, Colors[:reset] + codes)
|
39
|
+
codes + text + Colors[:reset]
|
70
40
|
end
|
71
41
|
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
42
|
+
def format_general(message)
|
43
|
+
message.gsub(/[^[:print:][:space:]]/) do |m|
|
44
|
+
colorize(m.inspect[1..-2], :bg_white, :black)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def format_debug(message)
|
49
|
+
"%s %s %s" % [timestamp, colorize("!!", :yellow), message]
|
50
|
+
end
|
51
|
+
|
52
|
+
def format_warn(message)
|
53
|
+
format_debug(message)
|
54
|
+
end
|
55
|
+
|
56
|
+
def format_info(message)
|
57
|
+
"%s %s %s" % [timestamp, "II", message]
|
58
|
+
end
|
59
|
+
|
60
|
+
def format_incoming(message)
|
61
|
+
pre, msg = message.split(" :", 2)
|
62
|
+
pre_parts = pre.split(" ")
|
63
|
+
|
64
|
+
prefix = colorize(">>", :green)
|
65
|
+
|
66
|
+
if pre_parts.size == 1
|
67
|
+
pre_parts[0] = colorize(pre_parts[0], :bold)
|
68
|
+
else
|
69
|
+
pre_parts[0] = colorize(pre_parts[0], :blue)
|
70
|
+
pre_parts[1] = colorize(pre_parts[1], :bold)
|
71
|
+
end
|
72
|
+
|
73
|
+
"%s %s %s %s" % [timestamp,
|
74
|
+
prefix,
|
75
|
+
pre_parts.join(" "),
|
76
|
+
msg ? colorize(":#{msg}", :yellow) : ""]
|
77
|
+
end
|
78
|
+
|
79
|
+
def format_outgoing(message)
|
80
|
+
pre, msg = message.split(" :", 2)
|
81
|
+
pre_parts = pre.split(" ")
|
82
|
+
|
83
|
+
prefix = colorize("<<", :red)
|
84
|
+
pre_parts[0] = colorize(pre_parts[0], :bold)
|
85
|
+
|
86
|
+
"%s %s %s %s" % [timestamp,
|
87
|
+
prefix,
|
88
|
+
pre_parts.join(" "),
|
89
|
+
msg ? colorize(":#{msg}", :yellow) : ""]
|
90
|
+
end
|
91
|
+
|
92
|
+
def format_exception(message)
|
93
|
+
"%s %s %s" % [timestamp, colorize("!!", :red), message]
|
77
94
|
end
|
78
95
|
end
|
79
96
|
end
|
@@ -1,36 +1,21 @@
|
|
1
1
|
require "cinch/logger/logger"
|
2
2
|
module Cinch
|
3
|
-
|
3
|
+
class Logger
|
4
4
|
# This logger logs all incoming messages in the format of zcbot.
|
5
5
|
# All other debug output (outgoing messages, exceptions, ...) will
|
6
6
|
# silently be dropped. The sole purpose of this logger is to
|
7
7
|
# produce logs parseable by pisg (with the zcbot formatter) to
|
8
8
|
# create channel statistics..
|
9
|
-
class ZcbotLogger < Cinch::Logger
|
10
|
-
#
|
11
|
-
def
|
12
|
-
|
13
|
-
|
9
|
+
class ZcbotLogger < Cinch::Logger
|
10
|
+
# (see Logger#log)
|
11
|
+
def log(messages, event, level = event)
|
12
|
+
return if event != :incoming
|
13
|
+
super
|
14
14
|
end
|
15
15
|
|
16
|
-
|
17
|
-
def
|
18
|
-
|
19
|
-
|
20
|
-
# (see Logger::Logger#log)
|
21
|
-
def log(messages, kind = :generic)
|
22
|
-
return if kind != :incoming
|
23
|
-
|
24
|
-
@mutex.synchronize do
|
25
|
-
messages = [messages].flatten.map {|s| s.to_s.chomp}
|
26
|
-
messages.each do |msg|
|
27
|
-
@output.puts Time.now.strftime("%m/%d/%Y %H:%M:%S ") + msg.encode("locale", {:invalid => :replace, :undef => :replace})
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
# (see Logger::Logger#log_exception)
|
33
|
-
def log_exception(e)
|
16
|
+
private
|
17
|
+
def format_incoming(message)
|
18
|
+
Time.now.strftime("%m/%d/%Y %H:%M:%S ") + message
|
34
19
|
end
|
35
20
|
end
|
36
21
|
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module Cinch
|
2
|
+
# This class allows Cinch to use multiple loggers at once. A common
|
3
|
+
# use-case would be to log formatted messages to STDERR and a
|
4
|
+
# pisg-compatible log to a file.
|
5
|
+
#
|
6
|
+
# It inherits directly from Array, so adding new loggers is as easy
|
7
|
+
# as calling LoggerList#push.
|
8
|
+
#
|
9
|
+
# @attr_writer level
|
10
|
+
# @since 2.0.0
|
11
|
+
class LoggerList < Array
|
12
|
+
# (see Logger#level=)
|
13
|
+
def level=(level)
|
14
|
+
each {|l| l.level = level}
|
15
|
+
end
|
16
|
+
|
17
|
+
# (see Logger#log)
|
18
|
+
def log(messages, event = :debug, level = event)
|
19
|
+
each {|l| l.log(messages, event, level)}
|
20
|
+
end
|
21
|
+
|
22
|
+
# (see Logger#debug)
|
23
|
+
def debug(message)
|
24
|
+
each {|l| l.debug(message)}
|
25
|
+
end
|
26
|
+
|
27
|
+
# (see Logger#error)
|
28
|
+
def error(message)
|
29
|
+
each {|l| l.error(message)}
|
30
|
+
end
|
31
|
+
|
32
|
+
# (see Logger#error)
|
33
|
+
def fatal(message)
|
34
|
+
each {|l| l.fatal(message)}
|
35
|
+
end
|
36
|
+
|
37
|
+
# (see Logger#info)
|
38
|
+
def info(message)
|
39
|
+
each {|l| l.info(message)}
|
40
|
+
end
|
41
|
+
|
42
|
+
# (see Logger#warn)
|
43
|
+
def warn(message)
|
44
|
+
each {|l| l.warn(message)}
|
45
|
+
end
|
46
|
+
|
47
|
+
# (see Logger#incoming)
|
48
|
+
def incoming(message)
|
49
|
+
each {|l| l.incoming(message)}
|
50
|
+
end
|
51
|
+
|
52
|
+
# (see Logger#outgoing)
|
53
|
+
def outgoing(message)
|
54
|
+
each {|l| l.outgoing(message)}
|
55
|
+
end
|
56
|
+
|
57
|
+
# (see Logger#exception)
|
58
|
+
def exception(message)
|
59
|
+
each {|l| l.exception(message)}
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|