Auto 4.0.0.alpha.1-x86-mingw32
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.
- data/.yardopts +7 -0
- data/Gemfile +19 -0
- data/LICENSE.md +31 -0
- data/README.md +109 -0
- data/Rakefile +41 -0
- data/bin/auto +110 -0
- data/bin/auto-conf +45 -0
- data/conf/example.json +100 -0
- data/conf/example.yml +125 -0
- data/docs/Contributing.md +77 -0
- data/docs/Events.md +103 -0
- data/docs/Todo.md +21 -0
- data/docs/Upgrade.md +16 -0
- data/ext/dsl_base.c +49 -0
- data/ext/libauto/auto.h +20 -0
- data/ext/libauto/extconf.rb +16 -0
- data/ext/libauto/libauto.c +29 -0
- data/ext/libauto/libauto.h +28 -0
- data/ext/libauto/logger.c +177 -0
- data/ext/libauto/logger.h +44 -0
- data/lib/auto.rb +43 -0
- data/lib/auto/api.rb +7 -0
- data/lib/auto/api/events.rb +166 -0
- data/lib/auto/api/object.rb +29 -0
- data/lib/auto/api/plugin.rb +155 -0
- data/lib/auto/api/timers.rb +93 -0
- data/lib/auto/bot.rb +338 -0
- data/lib/auto/config.rb +181 -0
- data/lib/auto/configure.rb +410 -0
- data/lib/auto/configure/shell.rb +154 -0
- data/lib/auto/dsl/base.rb +74 -0
- data/lib/auto/dsl/irc.rb +13 -0
- data/lib/auto/irc.rb +8 -0
- data/lib/auto/irc/common.rb +63 -0
- data/lib/auto/irc/library.rb +89 -0
- data/lib/auto/irc/object/channel.rb +21 -0
- data/lib/auto/irc/object/entity.rb +90 -0
- data/lib/auto/irc/object/message.rb +99 -0
- data/lib/auto/irc/object/user.rb +139 -0
- data/lib/auto/irc/protocol.rb +164 -0
- data/lib/auto/irc/protocol/numerics.rb +60 -0
- data/lib/auto/irc/sasl/diffie_hellman.rb +36 -0
- data/lib/auto/irc/sasl/mech.rb +15 -0
- data/lib/auto/irc/sasl/mech/dh_blowfish.rb +83 -0
- data/lib/auto/irc/sasl/mech/plain.rb +39 -0
- data/lib/auto/irc/server.rb +301 -0
- data/lib/auto/irc/state/channel_manager.rb +6 -0
- data/lib/auto/irc/state/support.rb +142 -0
- data/lib/auto/irc/state/user_manager.rb +6 -0
- data/lib/auto/irc/std/commands.rb +99 -0
- data/lib/auto/irc/std/numerics.rb +216 -0
- data/lib/auto/rubyext/integer.rb +25 -0
- data/lib/auto/rubyext/string.rb +10 -0
- data/lib/auto/version.rb +18 -0
- data/lib/libauto.so +0 -0
- data/spec/api_events_spec.rb +68 -0
- data/spec/config_json_spec.rb +116 -0
- data/spec/config_other_spec.rb +29 -0
- data/spec/config_yaml_spec.rb +136 -0
- data/spec/helper.rb +19 -0
- data/spec/irc_object_entity_spec.rb +51 -0
- data/spec/logger_spec.rb +30 -0
- data/spec/plugin_base_spec.rb +35 -0
- data/spec/timers_spec.rb +42 -0
- metadata +238 -0
@@ -0,0 +1,99 @@
|
|
1
|
+
# Copyright (c) 2013, Autumn Perrault, et al. All rights reserved.
|
2
|
+
# This free software is distributed under the FreeBSD license (LICENSE.md).
|
3
|
+
|
4
|
+
# Namespace: IRC
|
5
|
+
module IRC
|
6
|
+
|
7
|
+
# Namespace: Object
|
8
|
+
module Object
|
9
|
+
|
10
|
+
# A class which represents an IRC message, its associated properties, and
|
11
|
+
# offers methods for working with the message.
|
12
|
+
#
|
13
|
+
# @since 4.0.0
|
14
|
+
# @author noxgirl
|
15
|
+
# @api IRC
|
16
|
+
#
|
17
|
+
# @!attribute [r] irc
|
18
|
+
# @return [IRC::Server] The server on which the message was received.
|
19
|
+
#
|
20
|
+
# @!attribute [r] sender
|
21
|
+
# @return [IRC::Object::User] The user from whom the message was received.
|
22
|
+
#
|
23
|
+
# @!attribute [r] body
|
24
|
+
# @return [Array<String>] The body of the message, divided into elements by its spaces.
|
25
|
+
#
|
26
|
+
# @!attribute [r] nature
|
27
|
+
# @return [Symbol] The nature of the message, +:notice+ or +:msg+.
|
28
|
+
#
|
29
|
+
# @!attribute [r] channel
|
30
|
+
# @return [nil] If this message was received privately and not through a channel, this is nil.
|
31
|
+
# @return [IRC::Object::Channel] If it was received through a channel, the channel in question.
|
32
|
+
# @see #in_channel?
|
33
|
+
class Message
|
34
|
+
|
35
|
+
attr_reader :irc, :sender, :body, :nature, :channel
|
36
|
+
|
37
|
+
# Process a new message.
|
38
|
+
#
|
39
|
+
# @param [IRC::Server] irc The server on which the message was received.
|
40
|
+
# @param [IRC::Object::User] sender The user from whom the message was received.
|
41
|
+
# @param [String] body The body of the message.
|
42
|
+
# @param [Symbol] nature The nature of the message: either a +:notice+ or a +:msg+.
|
43
|
+
# @param [IRC::Object::Channel] channel If it was received through a channel, the channel.
|
44
|
+
#
|
45
|
+
# @example
|
46
|
+
# message = IRC::Object::Message.new(irc, user, body, :msg, channel)
|
47
|
+
def initialize(irc, sender, body, nature=:notice, channel=nil)
|
48
|
+
|
49
|
+
@irc = irc
|
50
|
+
@sender = sender
|
51
|
+
@body = body
|
52
|
+
@nature = nature
|
53
|
+
@channel = channel
|
54
|
+
|
55
|
+
end
|
56
|
+
|
57
|
+
# Reply to this message.
|
58
|
+
#
|
59
|
+
# @param [String] msg The message with which to reply.
|
60
|
+
# @param [true, false] in_channel If the response should be in-channel (assuming it was received in a channel), specify +true+.
|
61
|
+
# If it should be private regardless of where it was received, specify +false+.
|
62
|
+
#
|
63
|
+
# @note Essentially reply() exists to simplify the API.
|
64
|
+
# Rather than necessitating that commands use endless, illegible conditional
|
65
|
+
# nests to determine what to do, reply() is available so the API will just
|
66
|
+
# use some common sense to do it for them.
|
67
|
+
#
|
68
|
+
# @example
|
69
|
+
# msg.reply("The bar is of foo, indeed.", true)
|
70
|
+
#
|
71
|
+
# @todo Unfinished.
|
72
|
+
def reply(msg, in_channel)
|
73
|
+
|
74
|
+
case [@channel.nil, in_channel, @nature]
|
75
|
+
|
76
|
+
# Respond in-channel if this was sent to a channel *and* in_channel
|
77
|
+
# is specified as true.
|
78
|
+
when false, true, :msg
|
79
|
+
irc.msg(@channel, msg)
|
80
|
+
|
81
|
+
# Likewise for channel notices.
|
82
|
+
when false, true, :notice
|
83
|
+
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
87
|
+
|
88
|
+
# Checks whether the message was received through a channel.
|
89
|
+
#
|
90
|
+
# @return [true, false]
|
91
|
+
def in_channel?; @channel.nil?; end
|
92
|
+
|
93
|
+
end # class Message
|
94
|
+
|
95
|
+
end # module Object
|
96
|
+
|
97
|
+
end # module IRC
|
98
|
+
|
99
|
+
# vim: set ts=4 sts=2 sw=2 et:
|
@@ -0,0 +1,139 @@
|
|
1
|
+
# Copyright (c) 2013, Autumn Perrault, et al. All rights reserved.
|
2
|
+
# This free software is distributed under the FreeBSD license (LICENSE.md).
|
3
|
+
|
4
|
+
module Auto
|
5
|
+
|
6
|
+
# Namespace: IRC
|
7
|
+
module IRC
|
8
|
+
|
9
|
+
# Namespace: Object
|
10
|
+
module Object
|
11
|
+
|
12
|
+
# A class which represents an individual user on IRC, and which provides
|
13
|
+
# useful data regarding said user, and methods using which to interact
|
14
|
+
# with the user.
|
15
|
+
#
|
16
|
+
# @api IRC
|
17
|
+
# @since 4.0.0
|
18
|
+
# @author noxgirl
|
19
|
+
#
|
20
|
+
# @!attribute irc
|
21
|
+
# @return [Auto::IRC::Server] The server on which the user is located.
|
22
|
+
#
|
23
|
+
# @!attribute nick
|
24
|
+
# @return [String] The user's nickname.
|
25
|
+
#
|
26
|
+
# @!attribute user
|
27
|
+
# @return [String] If known, the user's username or ident.
|
28
|
+
# @return [nil] If unknown.
|
29
|
+
# @see #user_known?
|
30
|
+
#
|
31
|
+
# @!attribute host
|
32
|
+
# @return [String] If known, the user's hostname or mask.
|
33
|
+
# @return [nil] If unknown.
|
34
|
+
# @see #host_known?
|
35
|
+
#
|
36
|
+
# @!attribute account
|
37
|
+
# @return [String] If the user is logged in, their account name.
|
38
|
+
# @see #logged_in?
|
39
|
+
#
|
40
|
+
# @!attribute away
|
41
|
+
# @return [true] If the user is away.
|
42
|
+
# @return [false] If the user is present.
|
43
|
+
class User < Entity
|
44
|
+
|
45
|
+
attr_reader :nick, :user, :host, :account, :away
|
46
|
+
|
47
|
+
# Process a new user.
|
48
|
+
#
|
49
|
+
# @param [Auto::IRC::Server] irc The server the user is on.
|
50
|
+
# @param [String] nickname The user's nickname.
|
51
|
+
# @param [String] username The user's username or ident.
|
52
|
+
# @param [String] hostname The user's hostname or mask.
|
53
|
+
# @param [true, false] away Whether the user is away: +true+ or +false+.
|
54
|
+
#
|
55
|
+
# @example
|
56
|
+
# user = Auto::IRC::Object::User.new(irc, 'missfoo', 'cowmilk', 'the.night.is.lovely', false)
|
57
|
+
def initialize(irc, nickname, username=nil, hostname=nil, away=false)
|
58
|
+
|
59
|
+
super(irc, :user, nickname) # Entity#initialize
|
60
|
+
@nick = nickname
|
61
|
+
@user = username
|
62
|
+
@host = hostname
|
63
|
+
@away = away
|
64
|
+
@account = nil
|
65
|
+
|
66
|
+
end
|
67
|
+
|
68
|
+
# If the user logs into an account, this is used to specify the name of
|
69
|
+
# the account with which ze has identified.
|
70
|
+
#
|
71
|
+
# @param [String] accountname The name of the account.
|
72
|
+
#
|
73
|
+
# @example
|
74
|
+
# user.login('root')
|
75
|
+
def login(accountname)
|
76
|
+
unless accountname.nil?
|
77
|
+
@account = accountname
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
# If the user logs out of hir account, this is used to update their
|
82
|
+
# logged-in status.
|
83
|
+
def logout
|
84
|
+
@account = nil
|
85
|
+
end
|
86
|
+
|
87
|
+
# Update the user's known away status.
|
88
|
+
#
|
89
|
+
# @param [true, false] new The user's new away status, which should be +true+ or +false+.
|
90
|
+
def away=(new)
|
91
|
+
if new == true or new == false
|
92
|
+
@away = new
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
# Update the user's known hostname or mask.
|
97
|
+
#
|
98
|
+
# @param [String] new The user's new hostname.
|
99
|
+
def host=(new); @host = new unless new.nil?; end
|
100
|
+
|
101
|
+
# Update the user's known nickname.
|
102
|
+
#
|
103
|
+
# @param [String] new The user's new nickname.
|
104
|
+
def nick=(new); @nick = new unless new.nil?; end
|
105
|
+
|
106
|
+
# Update the user's known username or ident.
|
107
|
+
#
|
108
|
+
# @param [String] new The user's new username.
|
109
|
+
def user=(new); @user = new unless new.nil?; end
|
110
|
+
|
111
|
+
# This will check whether the user's username is known.
|
112
|
+
#
|
113
|
+
# @return [true] If known.
|
114
|
+
# @return [false] If Unknown.
|
115
|
+
def user_known?; @user.nil? ? false : true; end
|
116
|
+
|
117
|
+
# This will check whether the user's hostname is known.
|
118
|
+
#
|
119
|
+
# @return [true] If known.
|
120
|
+
# @return [false] If Unknown.
|
121
|
+
def host_known?; @host.nil? ? false : true; end
|
122
|
+
|
123
|
+
# This will check whether the user is logged in.
|
124
|
+
#
|
125
|
+
# @return [true] If known.
|
126
|
+
# @return [false] If Unknown.
|
127
|
+
def logged_in?; @account.nil? ? false : true; end
|
128
|
+
|
129
|
+
def inspect; "#<Auto::IRC::Object::User: irc=#@irc nick=#@nick account=#@account>"; end
|
130
|
+
|
131
|
+
end # class User
|
132
|
+
|
133
|
+
end # module Object
|
134
|
+
|
135
|
+
end # module IRC
|
136
|
+
|
137
|
+
end # module Auto
|
138
|
+
|
139
|
+
# vim: set ts=4 sts=2 sw=2 et:
|
@@ -0,0 +1,164 @@
|
|
1
|
+
# Copyright (c) 2013, Autumn Perrault, et al. All rights reserved.
|
2
|
+
# This free software is distributed under the FreeBSD license (LICENSE.md).
|
3
|
+
|
4
|
+
require 'auto/irc/protocol/numerics'
|
5
|
+
|
6
|
+
# namespace Auto
|
7
|
+
module Auto
|
8
|
+
|
9
|
+
# namespace IRC
|
10
|
+
module IRC
|
11
|
+
autoload :SASL, 'auto/irc/sasl/mech'
|
12
|
+
|
13
|
+
# A class for parsing of data per the specifications of the IRC protocol,
|
14
|
+
# v3.1.
|
15
|
+
#
|
16
|
+
# @see http://tools.ietf.org/html/rfc1459
|
17
|
+
# @see http://ircv3.atheme.org/
|
18
|
+
#
|
19
|
+
# @since 4.0.0
|
20
|
+
class Protocol
|
21
|
+
|
22
|
+
# Construct a new IRC data parser.
|
23
|
+
#
|
24
|
+
# @param [Auto::IRC::Library] lib The IRC library instance.
|
25
|
+
def initialize lib
|
26
|
+
extend Auto::IRC::Protocol::Numerics
|
27
|
+
lib.events.on :receive, &method(:parse)
|
28
|
+
end
|
29
|
+
|
30
|
+
# Parse IRC data.
|
31
|
+
#
|
32
|
+
# @param [Auto::IRC::Server] irc The IRC connection.
|
33
|
+
# @param [String] raw The data received.
|
34
|
+
def parse irc, raw
|
35
|
+
|
36
|
+
params = raw.split(/\s+/)
|
37
|
+
command = (raw =~ /^:/ ? params[1] : params[0]).dc
|
38
|
+
|
39
|
+
# Check if we process this command.
|
40
|
+
if respond_to? "on_#{command}"
|
41
|
+
send("on_#{command}", irc, raw, params)
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
|
46
|
+
# AUTHENTICATE
|
47
|
+
#
|
48
|
+
# @param [Auto::IRC::Server] irc The IRC connection.
|
49
|
+
# @param [String] raw The data received.
|
50
|
+
# @param [Array<String>] params The data received divided by +\s+ through
|
51
|
+
# regexp.
|
52
|
+
def on_authenticate irc, raw, params
|
53
|
+
username = $m.conf['irc'][irc.s]['SASL']['username']
|
54
|
+
password = $m.conf['irc'][irc.s]['SASL']['password']
|
55
|
+
|
56
|
+
if irc.supp.sasl_method == :dh_blowfish
|
57
|
+
crypt = Auto::IRC::SASL::Mech::DHBlowfish.encrypt(username, password, params.last)
|
58
|
+
elsif irc.supp.sasl_method == :plain
|
59
|
+
crypt = Auto::IRC::SASL::Mech::Plain.encrypt(username, password, params.last)
|
60
|
+
end
|
61
|
+
|
62
|
+
while crypt.length >= 400
|
63
|
+
irc.snd "AUTHENTICATE #{crypt.slice!(0, 400)}"
|
64
|
+
end
|
65
|
+
|
66
|
+
if crypt.length > 0
|
67
|
+
irc.snd "AUTHENTICATE #{crypt}"
|
68
|
+
else
|
69
|
+
irc.snd('AUTHENTICATE +')
|
70
|
+
end
|
71
|
+
# And we're done!
|
72
|
+
end
|
73
|
+
|
74
|
+
# CAP
|
75
|
+
#
|
76
|
+
# @param [Auto::IRC::Server] irc The IRC connection.
|
77
|
+
# @param [String] raw The data received.
|
78
|
+
# @param [Array<String>] params The data received divided by +\s+ through
|
79
|
+
# regexp.
|
80
|
+
def on_cap irc, raw, params
|
81
|
+
case params[3]
|
82
|
+
|
83
|
+
when 'LS'
|
84
|
+
params[4].gsub!(/^:/, '')
|
85
|
+
cap_ls(irc, params[4..-1])
|
86
|
+
when 'ACK'
|
87
|
+
params[4].gsub!(/^:/, '')
|
88
|
+
cap_ack(irc, params[4..-1])
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
# PING
|
93
|
+
#
|
94
|
+
# Return a PONG.
|
95
|
+
#
|
96
|
+
# @param [Auto::IRC::Server] irc The IRC connection.
|
97
|
+
# @param [String] raw The data received.
|
98
|
+
# @param [Array<String>] params The data received divided by +\s+ through
|
99
|
+
# regexp.
|
100
|
+
def on_ping irc, raw, params
|
101
|
+
irc.snd("PONG #{params[1]}")
|
102
|
+
end
|
103
|
+
|
104
|
+
#######
|
105
|
+
private
|
106
|
+
#######
|
107
|
+
|
108
|
+
# CAP LS
|
109
|
+
#
|
110
|
+
# Currently, Auto's capabilities include the multi-prefix, sasl,
|
111
|
+
# account-notify, away-notify, and extended-join extensions.
|
112
|
+
#
|
113
|
+
# @param [Auto::IRC::Server] irc The IRC connection.
|
114
|
+
# @param [Array<String>] list List of capabilities.
|
115
|
+
def cap_ls irc, list
|
116
|
+
|
117
|
+
req = []
|
118
|
+
|
119
|
+
# Every extension possible will be used except SASL, which requires
|
120
|
+
# special configuration.
|
121
|
+
%w[multi-prefix account-notify away-notify extended-join].each do |ext|
|
122
|
+
req.push ext if list.include? ext
|
123
|
+
end
|
124
|
+
|
125
|
+
if $m.conf['irc'][irc.s]['SASL'] and list.include? 'sasl'
|
126
|
+
req.push 'sasl'
|
127
|
+
end
|
128
|
+
|
129
|
+
# Send CAP REQ.
|
130
|
+
irc.snd("CAP REQ :#{req.join(' ')}") unless req.empty?
|
131
|
+
|
132
|
+
end
|
133
|
+
|
134
|
+
# CAP ACK
|
135
|
+
#
|
136
|
+
# We must save all capabilities into +irc.supp.cap+, and initiate SASL
|
137
|
+
# if possible.
|
138
|
+
#
|
139
|
+
# @param [Auto::IRC::Server] irc The IRC connection.
|
140
|
+
# @param [Array<String>] list List of capabilities.
|
141
|
+
def cap_ack irc, list
|
142
|
+
|
143
|
+
irc.supp.cap = list
|
144
|
+
|
145
|
+
if list.include? 'sasl'
|
146
|
+
irc.supp.sasl_id << $m.clock.spawn($m.conf['irc'][irc.s]['SASL']['timeout']||10, :once, irc) do |s|
|
147
|
+
$m.error "SASL authentication on #{s} failed: authentication procedure timed out."
|
148
|
+
s.snd('AUTHENTICATE *')
|
149
|
+
s.cap_end
|
150
|
+
end
|
151
|
+
irc.authenticate :dh_blowfish
|
152
|
+
else
|
153
|
+
irc.snd('CAP END') # end capability negotiation and complete registration
|
154
|
+
end
|
155
|
+
|
156
|
+
end
|
157
|
+
|
158
|
+
end # class Protocol
|
159
|
+
|
160
|
+
end # module IRC
|
161
|
+
|
162
|
+
end # module Auto
|
163
|
+
|
164
|
+
# vim: set ts=4 sts=2 sw=2 et:
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# Copyright (c) 2013, Autumn Perrault, et al. All rights reserved.
|
2
|
+
# This free software is distributed under the FreeBSD license (LICENSE.md).
|
3
|
+
|
4
|
+
require 'auto/irc/std/numerics'
|
5
|
+
|
6
|
+
module Auto
|
7
|
+
|
8
|
+
module IRC
|
9
|
+
|
10
|
+
class Protocol
|
11
|
+
|
12
|
+
# An extension of {Auto::IRC::Protocol}, which parses numerics.
|
13
|
+
module Numerics
|
14
|
+
include Auto::IRC::Std::Numerics
|
15
|
+
|
16
|
+
# RPL_WELCOME
|
17
|
+
define_method("on_#{RPL_WELCOME}") do |irc, raw, params|
|
18
|
+
$m.info "Successfully connected to #{irc} IRC network!" # log
|
19
|
+
end
|
20
|
+
|
21
|
+
# RPL_MYINFO
|
22
|
+
define_method("on_#{RPL_MYINFO}") do |irc, raw, params|
|
23
|
+
irc.supp.server_name = params[3]
|
24
|
+
end
|
25
|
+
|
26
|
+
# RPL_ISUPPORT
|
27
|
+
define_method("on_#{RPL_ISUPPORT}") do |irc, raw, params|
|
28
|
+
irc.supp.isupport(irc, params[3..-5].join(' ')) # process the isupport data
|
29
|
+
unless irc.supp.connected
|
30
|
+
irc.supp.connected = true
|
31
|
+
$m.irc.events.call :connected, irc # emit the :connected event
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# RPL_SASLSUCCESS
|
36
|
+
define_method("on_#{RPL_SASLSUCCESS}") do |irc, raw, params|
|
37
|
+
$m.info "SASL authentication on #{irc} succeeded!"
|
38
|
+
irc.cap_end
|
39
|
+
end
|
40
|
+
|
41
|
+
# ERR_SASLFAIL
|
42
|
+
define_method("on_#{ERR_SASLFAIL}") do |irc, raw, params|
|
43
|
+
if irc.supp.sasl_method == :dh_blowfish
|
44
|
+
irc.authenticate # try again with the PLAIN mechanism
|
45
|
+
else
|
46
|
+
# ope, failed
|
47
|
+
$m.error "SASL authentication on #{irc} failed: received ERR_SASLFAIL from server."
|
48
|
+
irc.cap_end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
end # class Numerics
|
53
|
+
|
54
|
+
end # class Protocol
|
55
|
+
|
56
|
+
end # module IRC
|
57
|
+
|
58
|
+
end # module Auto
|
59
|
+
|
60
|
+
# vim: set ts=4 sts=2 sw=2 et:
|