grinch 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.yardopts +1 -0
- data/LICENSE +22 -0
- data/README.md +180 -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 +15 -0
- data/examples/basic/join_part.rb +34 -0
- data/examples/basic/memo.rb +39 -0
- data/examples/basic/msg.rb +16 -0
- data/examples/basic/seen.rb +36 -0
- data/examples/basic/urban_dict.rb +35 -0
- data/examples/basic/url_shorten.rb +35 -0
- data/examples/plugins/autovoice.rb +37 -0
- data/examples/plugins/custom_prefix.rb +23 -0
- data/examples/plugins/dice_roll.rb +38 -0
- data/examples/plugins/google.rb +36 -0
- data/examples/plugins/hello.rb +22 -0
- data/examples/plugins/hooks.rb +36 -0
- data/examples/plugins/join_part.rb +42 -0
- data/examples/plugins/lambdas.rb +35 -0
- data/examples/plugins/last_nick.rb +24 -0
- data/examples/plugins/msg.rb +22 -0
- data/examples/plugins/multiple_matches.rb +32 -0
- data/examples/plugins/own_events.rb +37 -0
- data/examples/plugins/seen.rb +45 -0
- data/examples/plugins/timer.rb +22 -0
- data/examples/plugins/url_shorten.rb +33 -0
- data/lib/cinch.rb +5 -0
- data/lib/cinch/ban.rb +50 -0
- data/lib/cinch/bot.rb +479 -0
- data/lib/cinch/cached_list.rb +19 -0
- data/lib/cinch/callback.rb +20 -0
- data/lib/cinch/channel.rb +463 -0
- data/lib/cinch/channel_list.rb +29 -0
- data/lib/cinch/configuration.rb +73 -0
- data/lib/cinch/configuration/bot.rb +48 -0
- data/lib/cinch/configuration/dcc.rb +16 -0
- data/lib/cinch/configuration/plugins.rb +41 -0
- data/lib/cinch/configuration/sasl.rb +19 -0
- data/lib/cinch/configuration/ssl.rb +19 -0
- data/lib/cinch/configuration/timeouts.rb +14 -0
- data/lib/cinch/constants.rb +533 -0
- 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 +147 -0
- data/lib/cinch/dcc/outgoing.rb +1 -0
- data/lib/cinch/dcc/outgoing/send.rb +122 -0
- data/lib/cinch/exceptions.rb +46 -0
- data/lib/cinch/formatting.rb +125 -0
- data/lib/cinch/handler.rb +118 -0
- data/lib/cinch/handler_list.rb +90 -0
- data/lib/cinch/helpers.rb +231 -0
- data/lib/cinch/irc.rb +924 -0
- data/lib/cinch/isupport.rb +98 -0
- data/lib/cinch/log_filter.rb +21 -0
- data/lib/cinch/logger.rb +168 -0
- data/lib/cinch/logger/formatted_logger.rb +97 -0
- data/lib/cinch/logger/zcbot_logger.rb +22 -0
- data/lib/cinch/logger_list.rb +85 -0
- data/lib/cinch/mask.rb +69 -0
- data/lib/cinch/message.rb +392 -0
- data/lib/cinch/message_queue.rb +107 -0
- data/lib/cinch/mode_parser.rb +76 -0
- data/lib/cinch/network.rb +104 -0
- data/lib/cinch/open_ended_queue.rb +26 -0
- data/lib/cinch/pattern.rb +65 -0
- data/lib/cinch/plugin.rb +515 -0
- data/lib/cinch/plugin_list.rb +38 -0
- data/lib/cinch/rubyext/float.rb +3 -0
- data/lib/cinch/rubyext/module.rb +26 -0
- data/lib/cinch/rubyext/string.rb +33 -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/syncable.rb +83 -0
- data/lib/cinch/target.rb +199 -0
- data/lib/cinch/timer.rb +145 -0
- data/lib/cinch/user.rb +488 -0
- data/lib/cinch/user_list.rb +87 -0
- data/lib/cinch/utilities/deprecation.rb +16 -0
- data/lib/cinch/utilities/encoding.rb +37 -0
- data/lib/cinch/utilities/kernel.rb +13 -0
- data/lib/cinch/version.rb +4 -0
- metadata +140 -0
data/docs/plugins.md
ADDED
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,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
|