cinch 1.1.3 → 2.0.0.pre.1

Sign up to get free protection for your applications and to get access to all the features.
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