grinch 1.0.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 (99) hide show
  1. checksums.yaml +7 -0
  2. data/.yardopts +1 -0
  3. data/LICENSE +22 -0
  4. data/README.md +180 -0
  5. data/docs/bot_options.md +454 -0
  6. data/docs/changes.md +541 -0
  7. data/docs/common_mistakes.md +60 -0
  8. data/docs/common_tasks.md +57 -0
  9. data/docs/encodings.md +69 -0
  10. data/docs/events.md +273 -0
  11. data/docs/getting_started.md +184 -0
  12. data/docs/logging.md +90 -0
  13. data/docs/migrating.md +267 -0
  14. data/docs/plugins.md +4 -0
  15. data/docs/readme.md +20 -0
  16. data/examples/basic/autovoice.rb +32 -0
  17. data/examples/basic/google.rb +35 -0
  18. data/examples/basic/hello.rb +15 -0
  19. data/examples/basic/join_part.rb +34 -0
  20. data/examples/basic/memo.rb +39 -0
  21. data/examples/basic/msg.rb +16 -0
  22. data/examples/basic/seen.rb +36 -0
  23. data/examples/basic/urban_dict.rb +35 -0
  24. data/examples/basic/url_shorten.rb +35 -0
  25. data/examples/plugins/autovoice.rb +37 -0
  26. data/examples/plugins/custom_prefix.rb +23 -0
  27. data/examples/plugins/dice_roll.rb +38 -0
  28. data/examples/plugins/google.rb +36 -0
  29. data/examples/plugins/hello.rb +22 -0
  30. data/examples/plugins/hooks.rb +36 -0
  31. data/examples/plugins/join_part.rb +42 -0
  32. data/examples/plugins/lambdas.rb +35 -0
  33. data/examples/plugins/last_nick.rb +24 -0
  34. data/examples/plugins/msg.rb +22 -0
  35. data/examples/plugins/multiple_matches.rb +32 -0
  36. data/examples/plugins/own_events.rb +37 -0
  37. data/examples/plugins/seen.rb +45 -0
  38. data/examples/plugins/timer.rb +22 -0
  39. data/examples/plugins/url_shorten.rb +33 -0
  40. data/lib/cinch.rb +5 -0
  41. data/lib/cinch/ban.rb +50 -0
  42. data/lib/cinch/bot.rb +479 -0
  43. data/lib/cinch/cached_list.rb +19 -0
  44. data/lib/cinch/callback.rb +20 -0
  45. data/lib/cinch/channel.rb +463 -0
  46. data/lib/cinch/channel_list.rb +29 -0
  47. data/lib/cinch/configuration.rb +73 -0
  48. data/lib/cinch/configuration/bot.rb +48 -0
  49. data/lib/cinch/configuration/dcc.rb +16 -0
  50. data/lib/cinch/configuration/plugins.rb +41 -0
  51. data/lib/cinch/configuration/sasl.rb +19 -0
  52. data/lib/cinch/configuration/ssl.rb +19 -0
  53. data/lib/cinch/configuration/timeouts.rb +14 -0
  54. data/lib/cinch/constants.rb +533 -0
  55. data/lib/cinch/dcc.rb +12 -0
  56. data/lib/cinch/dcc/dccable_object.rb +37 -0
  57. data/lib/cinch/dcc/incoming.rb +1 -0
  58. data/lib/cinch/dcc/incoming/send.rb +147 -0
  59. data/lib/cinch/dcc/outgoing.rb +1 -0
  60. data/lib/cinch/dcc/outgoing/send.rb +122 -0
  61. data/lib/cinch/exceptions.rb +46 -0
  62. data/lib/cinch/formatting.rb +125 -0
  63. data/lib/cinch/handler.rb +118 -0
  64. data/lib/cinch/handler_list.rb +90 -0
  65. data/lib/cinch/helpers.rb +231 -0
  66. data/lib/cinch/irc.rb +924 -0
  67. data/lib/cinch/isupport.rb +98 -0
  68. data/lib/cinch/log_filter.rb +21 -0
  69. data/lib/cinch/logger.rb +168 -0
  70. data/lib/cinch/logger/formatted_logger.rb +97 -0
  71. data/lib/cinch/logger/zcbot_logger.rb +22 -0
  72. data/lib/cinch/logger_list.rb +85 -0
  73. data/lib/cinch/mask.rb +69 -0
  74. data/lib/cinch/message.rb +392 -0
  75. data/lib/cinch/message_queue.rb +107 -0
  76. data/lib/cinch/mode_parser.rb +76 -0
  77. data/lib/cinch/network.rb +104 -0
  78. data/lib/cinch/open_ended_queue.rb +26 -0
  79. data/lib/cinch/pattern.rb +65 -0
  80. data/lib/cinch/plugin.rb +515 -0
  81. data/lib/cinch/plugin_list.rb +38 -0
  82. data/lib/cinch/rubyext/float.rb +3 -0
  83. data/lib/cinch/rubyext/module.rb +26 -0
  84. data/lib/cinch/rubyext/string.rb +33 -0
  85. data/lib/cinch/sasl.rb +34 -0
  86. data/lib/cinch/sasl/dh_blowfish.rb +71 -0
  87. data/lib/cinch/sasl/diffie_hellman.rb +47 -0
  88. data/lib/cinch/sasl/mechanism.rb +6 -0
  89. data/lib/cinch/sasl/plain.rb +26 -0
  90. data/lib/cinch/syncable.rb +83 -0
  91. data/lib/cinch/target.rb +199 -0
  92. data/lib/cinch/timer.rb +145 -0
  93. data/lib/cinch/user.rb +488 -0
  94. data/lib/cinch/user_list.rb +87 -0
  95. data/lib/cinch/utilities/deprecation.rb +16 -0
  96. data/lib/cinch/utilities/encoding.rb +37 -0
  97. data/lib/cinch/utilities/kernel.rb +13 -0
  98. data/lib/cinch/version.rb +4 -0
  99. metadata +140 -0
data/docs/plugins.md ADDED
@@ -0,0 +1,4 @@
1
+ # @title Plugins
2
+ # @markup kramdown
3
+
4
+ Content will follow soon…
data/docs/readme.md ADDED
@@ -0,0 +1,20 @@
1
+ # @title README
2
+ # @markup kramdown
3
+
4
+
5
+ - {file:docs/changes.md Changelog}
6
+ - {file:docs/migrating.md Migration guides}
7
+
8
+ # Important documents
9
+
10
+ The following is a list of important documents to read.
11
+
12
+ - {file:docs/bot_options.md Bot options}
13
+ - {file:docs/common_tasks.md Common Tasks}
14
+ - {file:docs/common_mistakes.md Common mistakes}
15
+ - {Cinch::DCC DCC}
16
+ - {file:docs/encodings.md Encodings}
17
+ - {file:docs/logging.md Logging}
18
+ - {Cinch::SASL SASL}
19
+ - {Cinch::Formatting Formatting messages}
20
+ - {file:docs/events.md Events}
@@ -0,0 +1,32 @@
1
+ require 'cinch'
2
+
3
+ # Give this bot ops in a channel and it'll auto voice
4
+ # visitors
5
+ #
6
+ # Enable with !autovoice on
7
+ # Disable with !autovoice off
8
+ #
9
+ # It starts out disabled.
10
+
11
+ bot = Cinch::Bot.new do
12
+ configure do |c|
13
+ c.nick = "cinch_autovoice"
14
+ c.server = "irc.freenode.org"
15
+ c.verbose = true
16
+ c.channels = ["#cinch-bots"]
17
+ end
18
+
19
+ on :join do |m|
20
+ unless m.user.nick == bot.nick # We shouldn't attempt to voice ourselves
21
+ m.channel.voice(m.user) if @autovoice
22
+ end
23
+ end
24
+
25
+ on :channel, /^!autovoice (on|off)$/ do |m, option|
26
+ @autovoice = option == "on"
27
+
28
+ m.reply "Autovoice is now #{@autovoice ? 'enabled' : 'disabled'}"
29
+ end
30
+ end
31
+
32
+ bot.start
@@ -0,0 +1,35 @@
1
+ require 'cinch'
2
+ require 'open-uri'
3
+ require 'nokogiri'
4
+ require 'cgi'
5
+
6
+ bot = Cinch::Bot.new do
7
+ configure do |c|
8
+ c.server = "irc.freenode.net"
9
+ c.nick = "MrCinch"
10
+ c.channels = ["#cinch-bots"]
11
+ end
12
+
13
+ helpers do
14
+ # Extremely basic method, grabs the first result returned by Google
15
+ # or "No results found" otherwise
16
+ def google(query)
17
+ url = "http://www.google.com/search?q=#{CGI.escape(query)}"
18
+ res = Nokogiri.parse(open(url).read).at("h3.r")
19
+
20
+ title = res.text
21
+ link = res.at('a')[:href]
22
+ desc = res.at("./following::div").children.first.text
23
+ rescue
24
+ "No results found"
25
+ else
26
+ CGI.unescape_html "#{title} - #{desc} (#{link})"
27
+ end
28
+ end
29
+
30
+ on :message, /^!google (.+)/ do |m, query|
31
+ m.reply google(query)
32
+ end
33
+ end
34
+
35
+ bot.start
@@ -0,0 +1,15 @@
1
+ require 'cinch'
2
+
3
+ bot = Cinch::Bot.new do
4
+ configure do |c|
5
+ c.server = "irc.freenode.org"
6
+ c.channels = ["#cinch-bots"]
7
+ end
8
+
9
+ on :message, "hello" do |m|
10
+ m.reply "Hello, #{m.user.nick}"
11
+ end
12
+ end
13
+
14
+ bot.start
15
+
@@ -0,0 +1,34 @@
1
+ require 'cinch'
2
+
3
+ # Who should be able to access these plugins
4
+ $admin = "injekt"
5
+
6
+ bot = Cinch::Bot.new do
7
+ configure do |c|
8
+ c.server = "irc.freenode.org"
9
+ c.nick = "CinchBot"
10
+ c.channels = ["#cinch-bots"]
11
+ end
12
+
13
+ helpers do
14
+ def is_admin?(user)
15
+ true if user.nick == $admin
16
+ end
17
+ end
18
+
19
+ on :message, /^!join (.+)/ do |m, channel|
20
+ bot.join(channel) if is_admin?(m.user)
21
+ end
22
+
23
+ on :message, /^!part(?: (.+))?/ do |m, channel|
24
+ # Part current channel if none is given
25
+ channel = channel || m.channel
26
+
27
+ if channel
28
+ bot.part(channel) if is_admin?(m.user)
29
+ end
30
+ end
31
+ end
32
+
33
+ bot.start
34
+
@@ -0,0 +1,39 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'cinch'
4
+
5
+ class Memo < Struct.new(:nick, :channel, :text, :time)
6
+ def to_s
7
+ "[#{time.asctime}] <#{channel}/#{nick}> #{text}"
8
+ end
9
+ end
10
+
11
+ $memos = {}
12
+
13
+ bot = Cinch::Bot.new do
14
+ configure do |c|
15
+ c.server = "irc.freenode.org"
16
+ c.channels = ["#cinch-bots"]
17
+ end
18
+
19
+ on :message do |m|
20
+ if $memos.has_key?(m.user.nick)
21
+ m.user.send $memos.delete(m.user.nick).to_s
22
+ end
23
+ end
24
+
25
+ on :message, /^!memo (.+?) (.+)/ do |m, nick, message|
26
+ if $memos.key?(nick)
27
+ m.reply "There's already a memo for #{nick}. You can only store one right now"
28
+ elsif nick == m.user.nick
29
+ m.reply "You can't leave memos for yourself.."
30
+ elsif nick == bot.nick
31
+ m.reply "You can't leave memos for me.."
32
+ else
33
+ $memos[nick] = Memo.new(m.user.nick, m.channel, message, Time.now)
34
+ m.reply "Added memo for #{nick}"
35
+ end
36
+ end
37
+ end
38
+
39
+ bot.start
@@ -0,0 +1,16 @@
1
+ require 'cinch'
2
+
3
+ bot = Cinch::Bot.new do
4
+ configure do |c|
5
+ c.server = "irc.freenode.org"
6
+ c.nick = "CinchBot"
7
+ c.channels = ["#cinch-bots"]
8
+ end
9
+
10
+ on :message, /^!msg (.+?) (.+)/ do |m, who, text|
11
+ User(who).send text
12
+ end
13
+ end
14
+
15
+ bot.start
16
+
@@ -0,0 +1,36 @@
1
+ require 'cinch'
2
+
3
+ class Seen < Struct.new(:who, :where, :what, :time)
4
+ def to_s
5
+ "[#{time.asctime}] #{who} was seen in #{where} saying #{what}"
6
+ end
7
+ end
8
+
9
+ $users = {}
10
+
11
+ bot = Cinch::Bot.new do
12
+ configure do |c|
13
+ c.server = 'irc.freenode.org'
14
+ c.channels = ["#cinch-bots"]
15
+ end
16
+
17
+ # Only log channel messages
18
+ on :channel do |m|
19
+ $users[m.user.nick] = Seen.new(m.user.nick, m.channel, m.message, Time.new)
20
+ end
21
+
22
+ on :channel, /^!seen (.+)/ do |m, nick|
23
+ if nick == bot.nick
24
+ m.reply "That's me!"
25
+ elsif nick == m.user.nick
26
+ m.reply "That's you!"
27
+ elsif $users.key?(nick)
28
+ m.reply $users[nick].to_s
29
+ else
30
+ m.reply "I haven't seen #{nick}"
31
+ end
32
+ end
33
+ end
34
+
35
+ bot.start
36
+
@@ -0,0 +1,35 @@
1
+ require 'cinch'
2
+ require 'open-uri'
3
+ require 'nokogiri'
4
+ require 'cgi'
5
+
6
+ # This bot connects to urban dictionary and returns the first result
7
+ # for a given query, replying with the result directly to the sender
8
+
9
+ bot = Cinch::Bot.new do
10
+ configure do |c|
11
+ c.server = "irc.freenode.net"
12
+ c.nick = "MrCinch"
13
+ c.channels = ["#cinch-bots"]
14
+ end
15
+
16
+ helpers do
17
+ # This method assumes everything will go ok, it's not the best method
18
+ # of doing this *by far* and is simply a helper method to show how it
19
+ # can be done.. it works!
20
+ def urban_dict(query)
21
+ url = "http://www.urbandictionary.com/define.php?term=#{CGI.escape(query)}"
22
+ CGI.unescape_html Nokogiri::HTML(open(url)).css("div.meaning").first.text.gsub(/\s+/, ' ').strip rescue nil
23
+ end
24
+ end
25
+
26
+ on :message, /^!urban (.+)/ do |m, term|
27
+ m.reply(urban_dict(term) || "No results found", true)
28
+ end
29
+ end
30
+
31
+ bot.start
32
+
33
+ # injekt> !urban cinch
34
+ # MrCinch> injekt: describing an action that's extremely easy.
35
+
@@ -0,0 +1,35 @@
1
+ require 'open-uri'
2
+ require 'cinch'
3
+
4
+ # Automatically shorten URL's found in messages
5
+ # Using the tinyURL API
6
+
7
+ bot = Cinch::Bot.new do
8
+ configure do |c|
9
+ c.server = "irc.freenode.org"
10
+ c.channels = ["#cinch-bots"]
11
+ end
12
+
13
+ helpers do
14
+ def shorten(url)
15
+ url = open("http://tinyurl.com/api-create.php?url=#{URI.escape(url)}").read
16
+ url == "Error" ? nil : url
17
+ rescue OpenURI::HTTPError
18
+ nil
19
+ end
20
+ end
21
+
22
+ on :channel do |m|
23
+ urls = URI.extract(m.message, "http")
24
+
25
+ unless urls.empty?
26
+ short_urls = urls.map {|url| shorten(url) }.compact
27
+
28
+ unless short_urls.empty?
29
+ m.reply short_urls.join(", ")
30
+ end
31
+ end
32
+ end
33
+ end
34
+
35
+ bot.start
@@ -0,0 +1,37 @@
1
+ require 'cinch'
2
+
3
+ # Give this bot ops in a channel and it'll auto voice
4
+ # visitors
5
+ #
6
+ # Enable with !autovoice on
7
+ # Disable with !autovoice off
8
+
9
+ class Autovoice
10
+ include Cinch::Plugin
11
+ listen_to :join
12
+ match /autovoice (on|off)$/
13
+
14
+ def listen(m)
15
+ unless m.user.nick == bot.nick
16
+ m.channel.voice(m.user) if @autovoice
17
+ end
18
+ end
19
+
20
+ def execute(m, option)
21
+ @autovoice = option == "on"
22
+
23
+ m.reply "Autovoice is now #{@autovoice ? 'enabled' : 'disabled'}"
24
+ end
25
+ end
26
+
27
+ bot = Cinch::Bot.new do
28
+ configure do |c|
29
+ c.nick = "cinch_autovoice"
30
+ c.server = "irc.freenode.org"
31
+ c.channels = ["#cinch-bots"]
32
+ c.verbose = true
33
+ c.plugins.plugins = [Autovoice]
34
+ end
35
+ end
36
+
37
+ bot.start
@@ -0,0 +1,23 @@
1
+ require 'cinch'
2
+
3
+ class SomeCommand
4
+ include Cinch::Plugin
5
+
6
+ set :prefix, /^~/
7
+ match "somecommand"
8
+
9
+ def execute(m)
10
+ m.reply "Successful"
11
+ end
12
+ end
13
+
14
+ bot = Cinch::Bot.new do
15
+ configure do |c|
16
+ c.server = "irc.freenode.org"
17
+ c.channels = ["#cinch-bots"]
18
+ c.plugins.plugins = [SomeCommand]
19
+ end
20
+ end
21
+
22
+ bot.start
23
+
@@ -0,0 +1,38 @@
1
+ require 'cinch'
2
+
3
+ class DiceRoll
4
+ include Cinch::Plugin
5
+
6
+ # [[<repeats>#]<rolls>]d<sides>[<+/-><offset>]
7
+ match(/roll (?:(?:(\d+)#)?(\d+))?d(\d+)(?:([+-])(\d+))?/)
8
+ def execute(m, repeats, rolls, sides, offset_op, offset)
9
+ repeats = repeats.to_i
10
+ repeats = 1 if repeats < 1
11
+ rolls = rolls.to_i
12
+ rolls = 1 if rolls < 1
13
+
14
+ total = 0
15
+
16
+ repeats.times do
17
+ rolls.times do
18
+ score = rand(sides.to_i) + 1
19
+ if offset_op
20
+ score = score.send(offset_op, offset.to_i)
21
+ end
22
+ total += score
23
+ end
24
+ end
25
+
26
+ m.reply "Your dice roll was: #{total}", true
27
+ end
28
+ end
29
+
30
+ bot = Cinch::Bot.new do
31
+ configure do |c|
32
+ c.server = 'irc.freenode.org'
33
+ c.channels = ['#cinch-bots']
34
+ c.plugins.plugins = [DiceRoll]
35
+ end
36
+ end
37
+
38
+ bot.start
@@ -0,0 +1,36 @@
1
+ require 'cinch'
2
+ require 'open-uri'
3
+ require 'nokogiri'
4
+ require 'cgi'
5
+
6
+ class Google
7
+ include Cinch::Plugin
8
+ match /google (.+)/
9
+
10
+ def search(query)
11
+ url = "http://www.google.com/search?q=#{CGI.escape(query)}"
12
+ res = Nokogiri.parse(open(url).read).at("h3.r")
13
+
14
+ title = res.text
15
+ link = res.at('a')[:href]
16
+ desc = res.at("./following::div").children.first.text
17
+ CGI.unescape_html "#{title} - #{desc} (#{link})"
18
+ rescue
19
+ "No results found"
20
+ end
21
+
22
+ def execute(m, query)
23
+ m.reply(search(query))
24
+ end
25
+ end
26
+
27
+ bot = Cinch::Bot.new do
28
+ configure do |c|
29
+ c.server = "irc.freenode.net"
30
+ c.nick = "MrCinch"
31
+ c.channels = ["#cinch-bots"]
32
+ c.plugins.plugins = [Google]
33
+ end
34
+ end
35
+
36
+ bot.start