summer 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +20 -0
- data/README.markdown +96 -0
- data/lib/ext/array.rb +5 -0
- data/lib/ext/object.rb +5 -0
- data/lib/ext/string.rb +5 -0
- data/lib/summer.rb +149 -0
- data/lib/summer/handlers.rb +10 -0
- metadata +101 -0
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 Ryan Bigg
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.markdown
ADDED
@@ -0,0 +1,96 @@
|
|
1
|
+
# Summer
|
2
|
+
|
3
|
+
Summer is an IRC Bot "framework" "inspired" by [http://github.com/RISCFuture/autumn](Autumn). Its goal is to be tiny.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
The project is currently in "preview" state 'cause that's all the rage nowadays. No there's no invites, BUT everybody gets access to it.
|
8
|
+
Sorry to inform you that you'll have to clone it and then run `rake install` if you want to use it.
|
9
|
+
|
10
|
+
## Usage
|
11
|
+
|
12
|
+
To use summer, create a file like this:
|
13
|
+
|
14
|
+
require 'rubygems'
|
15
|
+
require 'summer'
|
16
|
+
|
17
|
+
class Bot < Summer::Connection
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
Bot.new("localhost")
|
22
|
+
|
23
|
+
Running it will make your bot attempt to connect to the server on localhost. For those of you who do not have an IRC server running locally, I would suggest trying irc.freenode.net instead.
|
24
|
+
|
25
|
+
## Configuration
|
26
|
+
|
27
|
+
In the same directory create a directory called _config_ and in that put _summer.yml_ which can have the following keys:
|
28
|
+
|
29
|
+
* nick: The nickname of the bot.
|
30
|
+
* channel: A channel to join on startup.
|
31
|
+
* channels: Channels to join on startup.
|
32
|
+
* auto_rejoin: Set this to true if you want the bot to re-join any channel it's kicked from.
|
33
|
+
|
34
|
+
## `did_start_up`
|
35
|
+
|
36
|
+
Called when the bot has received the final MOTD line (376 or 422) and has finished joining all the channels.
|
37
|
+
|
38
|
+
## `channel_message(sender, channel, message)`
|
39
|
+
|
40
|
+
Called when the bot receives a channel message.
|
41
|
+
|
42
|
+
sender (`Hash`): Contains `nick` and `hostname`
|
43
|
+
channel (`String`): The channel name: e.g. "#logga"
|
44
|
+
message (`String`): The message that was received
|
45
|
+
|
46
|
+
## `private_message(sender, bot, message)`
|
47
|
+
|
48
|
+
Called when the bot receives a private message.
|
49
|
+
|
50
|
+
sender (`Hash`): Contains `nick` and `hostname`
|
51
|
+
bot (`String`): The bot's name.
|
52
|
+
message (`String`): The message that was received
|
53
|
+
|
54
|
+
## `join(sender, channel)`
|
55
|
+
|
56
|
+
Called when the bot sees someone join a channel.
|
57
|
+
|
58
|
+
sender (`Hash`): Contains `nick` and `hostname`
|
59
|
+
channel (`String`): The channel name: e.g. "#logga"
|
60
|
+
|
61
|
+
## `part(sender, channel, message)`
|
62
|
+
|
63
|
+
Called when someone parts a channel:
|
64
|
+
|
65
|
+
sender (`Hash`): Contains `nick` and `hostname`
|
66
|
+
channel (`String`): The channel name: e.g. "#logga"
|
67
|
+
message (`String`): The message that was received
|
68
|
+
|
69
|
+
## `quit(sender, message)`
|
70
|
+
|
71
|
+
Called when someone quits the server:
|
72
|
+
|
73
|
+
sender (`Hash`): Contains `nick` and `hostname`
|
74
|
+
message (`String`): The message that was received.
|
75
|
+
|
76
|
+
|
77
|
+
## `kick(kicker, channel, victim, message)`
|
78
|
+
|
79
|
+
Called when someone quits the server:
|
80
|
+
|
81
|
+
kicker (`Hash`): Contains `nick` and `hostname`
|
82
|
+
channel (`String`): The channel name: e.g. "#logga"
|
83
|
+
victim (`String`): Just the nick of whoever was kicked.
|
84
|
+
message (`String`): The message that was received.
|
85
|
+
|
86
|
+
|
87
|
+
## Handling raw messages
|
88
|
+
|
89
|
+
If you wish to handle raw messages that come into your bot you can define a `handle_xxx` method for that where `xxx` is the three-digit representation of the raw you wish to handle.
|
90
|
+
|
91
|
+
|
92
|
+
### Upcoming
|
93
|
+
|
94
|
+
`mode` method to detect mode changes
|
95
|
+
Auto-rejoin after kick (configuration options)
|
96
|
+
|
data/lib/ext/array.rb
ADDED
data/lib/ext/object.rb
ADDED
data/lib/ext/string.rb
ADDED
data/lib/summer.rb
ADDED
@@ -0,0 +1,149 @@
|
|
1
|
+
require 'socket'
|
2
|
+
require 'yaml'
|
3
|
+
require 'active_support/hash_with_indifferent_access'
|
4
|
+
require 'active_support/core_ext/object/try'
|
5
|
+
|
6
|
+
Dir[File.dirname(__FILE__) + '/ext/*.rb'].each { |f| require f }
|
7
|
+
|
8
|
+
require File.dirname(__FILE__) + "/summer/handlers"
|
9
|
+
|
10
|
+
module Summer
|
11
|
+
class Connection
|
12
|
+
include Handlers
|
13
|
+
attr_accessor :connection, :ready, :started, :config, :server, :port
|
14
|
+
def initialize(server, port=6667, dry=false)
|
15
|
+
@ready = false
|
16
|
+
@started = false
|
17
|
+
|
18
|
+
@server = server
|
19
|
+
@port = port
|
20
|
+
|
21
|
+
load_config
|
22
|
+
connect!
|
23
|
+
|
24
|
+
unless dry
|
25
|
+
loop do
|
26
|
+
startup! if @ready && !@started
|
27
|
+
message = @connection.gets
|
28
|
+
if message
|
29
|
+
parse(message)
|
30
|
+
else
|
31
|
+
break
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def load_config
|
40
|
+
@config = HashWithIndifferentAccess.new(YAML::load_file(File.dirname($0) + "/config/summer.yml"))
|
41
|
+
@config[:channels] ||= []
|
42
|
+
@config[:channels] << @config.delete(:channel) if @config[:channel]
|
43
|
+
end
|
44
|
+
|
45
|
+
def connect!
|
46
|
+
@connection = TCPSocket.open(server, port)
|
47
|
+
response("USER #{config[:nick]} #{config[:nick]} #{config[:nick]} #{config[:nick]}")
|
48
|
+
response("NICK #{config[:nick]}")
|
49
|
+
end
|
50
|
+
|
51
|
+
|
52
|
+
# Will join channels specified in configuration.
|
53
|
+
def startup!
|
54
|
+
nickserv_identify if @config[:nickserv_password]
|
55
|
+
config[:channels].each do |channel|
|
56
|
+
join(channel)
|
57
|
+
end
|
58
|
+
@started = true
|
59
|
+
really_try(:did_start_up) if respond_to?(:did_start_up)
|
60
|
+
end
|
61
|
+
|
62
|
+
def nickserv_identify
|
63
|
+
privmsg("nickserv", "register #{@config[:nickserv_password]} #{@config[:nickserv_email]}")
|
64
|
+
privmsg("nickserv", "identify #{@config[:nickserv_password]}")
|
65
|
+
end
|
66
|
+
# Go somewhere.
|
67
|
+
def join(channel)
|
68
|
+
response("JOIN #{channel}")
|
69
|
+
end
|
70
|
+
|
71
|
+
# Leave somewhere
|
72
|
+
def part(channel)
|
73
|
+
response("PART #{channel}")
|
74
|
+
end
|
75
|
+
|
76
|
+
# What did they say?
|
77
|
+
def parse(message)
|
78
|
+
puts "<< #{message.to_s.strip}"
|
79
|
+
words = message.split(" ")
|
80
|
+
sender = words[0]
|
81
|
+
raw = words[1]
|
82
|
+
channel = words[2]
|
83
|
+
# Handling pings
|
84
|
+
if /^PING (.*?)\s$/.match(message)
|
85
|
+
response("PONG #{$1}")
|
86
|
+
# Handling raws
|
87
|
+
elsif /\d+/.match(raw)
|
88
|
+
send("handle_#{raw}", message) if raws_to_handle.include?(raw)
|
89
|
+
# Privmsgs
|
90
|
+
elsif raw == "PRIVMSG"
|
91
|
+
message = words[3..-1].clean
|
92
|
+
# Parse commands
|
93
|
+
if /^!(\w+)\s*(.*)/.match(message) && respond_to?("#{$1}_command")
|
94
|
+
really_try("#{$1}_command", parse_sender(sender), channel, $2)
|
95
|
+
# Plain and boring message
|
96
|
+
else
|
97
|
+
sender = parse_sender(sender)
|
98
|
+
method, channel = channel == me ? [:private_message, sender[:nick]] : [:channel_message, channel]
|
99
|
+
really_try(method, sender, channel, message)
|
100
|
+
end
|
101
|
+
# Joins
|
102
|
+
elsif raw == "JOIN"
|
103
|
+
really_try(:join, parse_sender(sender), channel)
|
104
|
+
elsif raw == "PART"
|
105
|
+
really_try(:part, parse_sender(sender), channel, words[3..-1].clean)
|
106
|
+
elsif raw == "QUIT"
|
107
|
+
really_try(:quit, parse_sender(sender), words[2..-1].clean)
|
108
|
+
elsif raw == "KICK"
|
109
|
+
really_try(:kick, parse_sender(sender), channel, words[3], words[4..-1].clean)
|
110
|
+
join(channel) if words[3] == me && config[:auto_rejoin]
|
111
|
+
elsif raw == "MODE"
|
112
|
+
really_try(:mode, parse_sender(sender), channel, words[3], words[4..-1].clean)
|
113
|
+
elsif raw == "TOPIC"
|
114
|
+
really_try(:topic, parse_sender(sender), channel, words[3..-1].clean)
|
115
|
+
end
|
116
|
+
|
117
|
+
end
|
118
|
+
|
119
|
+
def parse_sender(sender)
|
120
|
+
nick, hostname = sender.split("!")
|
121
|
+
{ :nick => nick.clean, :hostname => hostname }
|
122
|
+
end
|
123
|
+
|
124
|
+
# These are the raws we care about.
|
125
|
+
def raws_to_handle
|
126
|
+
["422", "376"]
|
127
|
+
end
|
128
|
+
|
129
|
+
def privmsg(message, to)
|
130
|
+
response("PRIVMSG #{to} :#{message}")
|
131
|
+
end
|
132
|
+
|
133
|
+
# Output something to the console and to the socket.
|
134
|
+
def response(message)
|
135
|
+
puts ">> #{message.strip}"
|
136
|
+
@connection.puts(message)
|
137
|
+
end
|
138
|
+
|
139
|
+
def me
|
140
|
+
config[:nick]
|
141
|
+
end
|
142
|
+
|
143
|
+
def log(message)
|
144
|
+
File.open(config[:log_file]) { |file| file.write(message) } if config[:log_file]
|
145
|
+
end
|
146
|
+
|
147
|
+
end
|
148
|
+
|
149
|
+
end
|
metadata
ADDED
@@ -0,0 +1,101 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: summer
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Ryan Bigg
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-01-30 00:00:00.000000000Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: shoulda
|
16
|
+
requirement: &2153293060 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *2153293060
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: rdoc
|
27
|
+
requirement: &2153292580 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ~>
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '3.12'
|
33
|
+
type: :development
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *2153292580
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: bundler
|
38
|
+
requirement: &2153292100 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ~>
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: 1.0.0
|
44
|
+
type: :development
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *2153292100
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: jeweler
|
49
|
+
requirement: &2153291620 !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ~>
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 1.8.3
|
55
|
+
type: :development
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: *2153291620
|
58
|
+
description: Tiny IRC Bot Frameowkr
|
59
|
+
email: radarlistener@gmail.com
|
60
|
+
executables: []
|
61
|
+
extensions: []
|
62
|
+
extra_rdoc_files:
|
63
|
+
- LICENSE
|
64
|
+
- README.markdown
|
65
|
+
files:
|
66
|
+
- lib/ext/array.rb
|
67
|
+
- lib/ext/object.rb
|
68
|
+
- lib/ext/string.rb
|
69
|
+
- lib/summer.rb
|
70
|
+
- lib/summer/handlers.rb
|
71
|
+
- LICENSE
|
72
|
+
- README.markdown
|
73
|
+
homepage: http://github.com/radar/summer
|
74
|
+
licenses:
|
75
|
+
- MIT
|
76
|
+
post_install_message:
|
77
|
+
rdoc_options: []
|
78
|
+
require_paths:
|
79
|
+
- lib
|
80
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ! '>='
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0'
|
86
|
+
segments:
|
87
|
+
- 0
|
88
|
+
hash: -3637726515248804584
|
89
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
90
|
+
none: false
|
91
|
+
requirements:
|
92
|
+
- - ! '>='
|
93
|
+
- !ruby/object:Gem::Version
|
94
|
+
version: '0'
|
95
|
+
requirements: []
|
96
|
+
rubyforge_project:
|
97
|
+
rubygems_version: 1.8.11
|
98
|
+
signing_key:
|
99
|
+
specification_version: 3
|
100
|
+
summary: Tiny IRC Bot Framework
|
101
|
+
test_files: []
|