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.
Files changed (83) hide show
  1. data/LICENSE +1 -0
  2. data/README.md +3 -3
  3. data/docs/bot_options.md +435 -0
  4. data/docs/changes.md +440 -0
  5. data/docs/common_mistakes.md +35 -0
  6. data/docs/common_tasks.md +47 -0
  7. data/docs/encodings.md +67 -0
  8. data/docs/events.md +272 -0
  9. data/docs/logging.md +5 -0
  10. data/docs/migrating.md +267 -0
  11. data/docs/readme.md +18 -0
  12. data/examples/plugins/custom_prefix.rb +1 -1
  13. data/examples/plugins/dice_roll.rb +38 -0
  14. data/examples/plugins/lambdas.rb +1 -1
  15. data/examples/plugins/memo.rb +16 -10
  16. data/examples/plugins/url_shorten.rb +1 -0
  17. data/lib/cinch.rb +5 -60
  18. data/lib/cinch/ban.rb +13 -7
  19. data/lib/cinch/bot.rb +228 -403
  20. data/lib/cinch/{cache_manager.rb → cached_list.rb} +5 -1
  21. data/lib/cinch/callback.rb +3 -0
  22. data/lib/cinch/channel.rb +119 -195
  23. data/lib/cinch/{channel_manager.rb → channel_list.rb} +6 -3
  24. data/lib/cinch/configuration.rb +73 -0
  25. data/lib/cinch/configuration/bot.rb +47 -0
  26. data/lib/cinch/configuration/dcc.rb +16 -0
  27. data/lib/cinch/configuration/plugins.rb +41 -0
  28. data/lib/cinch/configuration/sasl.rb +17 -0
  29. data/lib/cinch/configuration/ssl.rb +19 -0
  30. data/lib/cinch/configuration/storage.rb +37 -0
  31. data/lib/cinch/configuration/timeouts.rb +14 -0
  32. data/lib/cinch/constants.rb +531 -369
  33. data/lib/cinch/dcc.rb +12 -0
  34. data/lib/cinch/dcc/dccable_object.rb +37 -0
  35. data/lib/cinch/dcc/incoming.rb +1 -0
  36. data/lib/cinch/dcc/incoming/send.rb +131 -0
  37. data/lib/cinch/dcc/outgoing.rb +1 -0
  38. data/lib/cinch/dcc/outgoing/send.rb +115 -0
  39. data/lib/cinch/exceptions.rb +8 -1
  40. data/lib/cinch/formatting.rb +106 -0
  41. data/lib/cinch/handler.rb +104 -0
  42. data/lib/cinch/handler_list.rb +86 -0
  43. data/lib/cinch/helpers.rb +167 -10
  44. data/lib/cinch/irc.rb +525 -110
  45. data/lib/cinch/isupport.rb +11 -9
  46. data/lib/cinch/logger.rb +168 -0
  47. data/lib/cinch/logger/formatted_logger.rb +72 -55
  48. data/lib/cinch/logger/zcbot_logger.rb +9 -24
  49. data/lib/cinch/logger_list.rb +62 -0
  50. data/lib/cinch/mask.rb +19 -10
  51. data/lib/cinch/message.rb +94 -28
  52. data/lib/cinch/message_queue.rb +70 -28
  53. data/lib/cinch/mode_parser.rb +6 -1
  54. data/lib/cinch/network.rb +104 -0
  55. data/lib/cinch/{rubyext/queue.rb → open_ended_queue.rb} +8 -1
  56. data/lib/cinch/pattern.rb +24 -4
  57. data/lib/cinch/plugin.rb +352 -177
  58. data/lib/cinch/plugin_list.rb +35 -0
  59. data/lib/cinch/rubyext/float.rb +3 -0
  60. data/lib/cinch/rubyext/module.rb +7 -0
  61. data/lib/cinch/rubyext/string.rb +9 -0
  62. data/lib/cinch/sasl.rb +34 -0
  63. data/lib/cinch/sasl/dh_blowfish.rb +71 -0
  64. data/lib/cinch/sasl/diffie_hellman.rb +47 -0
  65. data/lib/cinch/sasl/mechanism.rb +6 -0
  66. data/lib/cinch/sasl/plain.rb +26 -0
  67. data/lib/cinch/storage.rb +62 -0
  68. data/lib/cinch/storage/null.rb +12 -0
  69. data/lib/cinch/storage/yaml.rb +96 -0
  70. data/lib/cinch/syncable.rb +13 -1
  71. data/lib/cinch/target.rb +144 -0
  72. data/lib/cinch/timer.rb +145 -0
  73. data/lib/cinch/user.rb +169 -225
  74. data/lib/cinch/{user_manager.rb → user_list.rb} +7 -2
  75. data/lib/cinch/utilities/deprecation.rb +12 -0
  76. data/lib/cinch/utilities/encoding.rb +54 -0
  77. data/lib/cinch/utilities/kernel.rb +13 -0
  78. data/lib/cinch/utilities/string.rb +13 -0
  79. data/lib/cinch/version.rb +4 -0
  80. metadata +88 -47
  81. data/lib/cinch/logger/logger.rb +0 -44
  82. data/lib/cinch/logger/null_logger.rb +0 -18
  83. data/lib/cinch/rubyext/infinity.rb +0 -1
@@ -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"] = Infinity
68
- self["MAXBANS"] = Infinity
69
- self["TOPICLEN"] = Infinity
70
- self["KICKLEN"] = Infinity
71
- self["CHANNELLEN"] = Infinity
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"] = Infinity
74
+ self["AWAYLEN"] = Float::INFINITY
74
75
  self["MAXTARGETS"] = 1
75
- self["MAXCHANNELS"] = Infinity # deprecated
76
- self["CHANLIMIT"] = {"#" => Infinity}
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
@@ -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/logger"
1
+ require "cinch/logger"
2
+
2
3
  module Cinch
3
- module Logger
4
- # A formatted logger that will colorize individual parts of IRC
5
- # messages.
6
- class FormattedLogger < Cinch::Logger::Logger
7
- COLORS = {
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
- # @param [IO] output An IO to log to.
17
- def initialize(output = STDERR)
18
- @output = output
19
- @mutex = Mutex.new
20
- end
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
- # (see Logger::Logger#log)
28
- def log(messages, kind = :generic)
29
- @mutex.synchronize do
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
- COLORS.values_at(*codes).join + text + COLORS[:reset]
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
- # (see Logger::Logger#log_exception)
73
- def log_exception(e)
74
- lines = ["#{e.backtrace.first}: #{e.message} (#{e.class})"]
75
- lines.concat e.backtrace[1..-1].map {|s| "\t" + s}
76
- debug(lines)
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
- module Logger
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::Logger
10
- # @param [IO] output An IO to log to.
11
- def initialize(output = STDERR)
12
- @output = output
13
- @mutex = Mutex.new
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
- # (see Logger::Logger#debug)
17
- def debug(messages)
18
- end
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