vetinari 0.1.0 → 0.2.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.
- checksums.yaml +4 -4
- data/Gemfile +2 -0
- data/README.md +1 -1
- data/lib/vetinari/bot.rb +8 -0
- data/lib/vetinari/callback.rb +4 -0
- data/lib/vetinari/callback_container.rb +5 -1
- data/lib/vetinari/channel.rb +41 -2
- data/lib/vetinari/irc.rb +47 -3
- data/lib/vetinari/version.rb +1 -1
- data/spec/callback_spec.rb +9 -0
- data/spec/join_spec.rb +75 -0
- data/spec/rename_spec.rb +60 -0
- data/vetinari.gemspec +1 -1
- metadata +10 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a7b2a839017a8a6ad9cb366e4983223d18d79125
|
4
|
+
data.tar.gz: e9283985e9363ac330abaf31f07965ec26ef3049
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e8faa48002d977fe10bed20ed4aa6e0f39669c0abdae838be9e13fa7d713e42c2361c63e0c499211e13bc68f63eb488ab14347d1110dc7a022f3a5beb6e19e43
|
7
|
+
data.tar.gz: 2c6726ab26892d11914ec986ae1ec5e7afe57c5dd35fa1164c9004c98dd4c19645a27dfb013d84c06db7f71681c5d4805b15cf0650f8f1b809a4ef34c522abde
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Vetinari [](http://badge.fury.io/rb/vetinari)
|
1
|
+
# Vetinari [](http://badge.fury.io/rb/vetinari) [](https://gemnasium.com/tbuehlmann/vetinari)
|
2
2
|
Vetinari is a Domain Specific Language for writing IRC Bots using the [Celluloid::IO](https://github.com/celluloid/celluloid-io "Celluloid::IO") library.
|
3
3
|
|
4
4
|
## Requirements
|
data/lib/vetinari/bot.rb
CHANGED
@@ -346,6 +346,14 @@ module Vetinari
|
|
346
346
|
env[:user].renamed_to(env.delete(:new_nick))
|
347
347
|
end
|
348
348
|
|
349
|
+
on :topic do |env|
|
350
|
+
# TODO: Update existing users with user/host information.
|
351
|
+
env.delete(:user)
|
352
|
+
env.delete(:host)
|
353
|
+
env[:channel] = @channels[env.delete(:channel)]
|
354
|
+
env[:user] = @users[env.delete(:nick)]
|
355
|
+
end
|
356
|
+
|
349
357
|
# Response to MODE command, giving back the channel modes.
|
350
358
|
on 324 do |env|
|
351
359
|
split = env[:params].split(/ /)
|
data/lib/vetinari/callback.rb
CHANGED
@@ -35,12 +35,16 @@ module Vetinari
|
|
35
35
|
callback
|
36
36
|
end
|
37
37
|
|
38
|
-
def remove(event, uuid)
|
38
|
+
def remove(event, uuid, terminate = false)
|
39
39
|
@mutex.synchronize do
|
40
40
|
if @callbacks.key?(event)
|
41
41
|
hash = @callbacks[event].delete(uuid)
|
42
42
|
|
43
43
|
if hash
|
44
|
+
if terminate && hash[:callback].alive?
|
45
|
+
hash[:callback].async.terminate
|
46
|
+
end
|
47
|
+
|
44
48
|
# https://github.com/celluloid/celluloid/issues/197
|
45
49
|
# callback.soft_terminate
|
46
50
|
|
data/lib/vetinari/channel.rb
CHANGED
@@ -4,9 +4,9 @@ module Vetinari
|
|
4
4
|
#
|
5
5
|
# Example:
|
6
6
|
# {'ponder' => {:user => #<User nick="Ponder">, :modes => ['v', 'o']}}
|
7
|
-
#
|
8
|
-
# TODO: Actor?
|
9
7
|
class Channel
|
8
|
+
include Celluloid
|
9
|
+
|
10
10
|
attr_reader :name, :users, :users_with_modes, :modes, :lists
|
11
11
|
|
12
12
|
def initialize(name, bot)
|
@@ -95,11 +95,50 @@ module Vetinari
|
|
95
95
|
end
|
96
96
|
|
97
97
|
def join(key = nil)
|
98
|
+
if @bot.channels.has_channel?(@name)
|
99
|
+
return Future.new { :already_joined }
|
100
|
+
end
|
101
|
+
|
102
|
+
condition = Celluloid::Condition.new
|
103
|
+
callbacks = Set.new
|
104
|
+
|
105
|
+
callbacks << @bot.on(:join) do |env|
|
106
|
+
if env[:channel].name == @name
|
107
|
+
condition.signal :joined
|
108
|
+
callbacks.each { |cb| cb.remove_and_terminate }
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
raw_messages = {
|
113
|
+
475 => :locked,
|
114
|
+
471 => :full,
|
115
|
+
474 => :banned,
|
116
|
+
473 => :invite_only
|
117
|
+
}
|
118
|
+
|
119
|
+
raw_messages.each do |raw, msg|
|
120
|
+
callbacks << @bot.on(raw) do |env|
|
121
|
+
channel_name = env[:params].split(' ')[1]
|
122
|
+
|
123
|
+
if channel_name == @name
|
124
|
+
condition.signal msg
|
125
|
+
callbacks.each { |cb| cb.remove_and_terminate }
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
after(5) do
|
131
|
+
condition.signal :timeout
|
132
|
+
callbacks.each { |cb| cb.remove_and_terminate }
|
133
|
+
end
|
134
|
+
|
98
135
|
if key
|
99
136
|
@bot.raw "JOIN #{@name} #{key}"
|
100
137
|
else
|
101
138
|
@bot.raw "JOIN #{@name}"
|
102
139
|
end
|
140
|
+
|
141
|
+
Future.new { condition.wait }
|
103
142
|
end
|
104
143
|
|
105
144
|
def part(message = nil)
|
data/lib/vetinari/irc.rb
CHANGED
@@ -7,7 +7,41 @@ module Vetinari
|
|
7
7
|
end
|
8
8
|
|
9
9
|
def rename(nick)
|
10
|
+
if nick.length > @config.isupport['NICKLEN']
|
11
|
+
nick = nick.slice(0, @config.isupport['NICKLEN'])
|
12
|
+
end
|
13
|
+
|
14
|
+
return Celluloid::Future.new { nick } if @user.nick == nick
|
15
|
+
|
16
|
+
condition = Celluloid::Condition.new
|
17
|
+
callbacks = Set.new
|
18
|
+
|
19
|
+
callbacks << on(:nick_change) do |env|
|
20
|
+
if env[:user].bot?
|
21
|
+
condition.signal env[:user].nick
|
22
|
+
callbacks.each { |cb| cb.remove_and_terminate }
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
raw_messages = {
|
27
|
+
432 => :erroneous_nickname,
|
28
|
+
433 => :nickname_in_use
|
29
|
+
}
|
30
|
+
|
31
|
+
raw_messages.each do |raw, msg|
|
32
|
+
callbacks << on(raw) do |env|
|
33
|
+
condition.signal(msg)
|
34
|
+
callbacks.each { |cb| cb.remove_and_terminate }
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
after(5) do
|
39
|
+
condition.signal(:timeout)
|
40
|
+
callbacks.each { |cb| cb.remove_and_terminate }
|
41
|
+
end
|
42
|
+
|
10
43
|
raw "NICK :#{nick}"
|
44
|
+
Celluloid::Future.new { condition.wait }
|
11
45
|
end
|
12
46
|
|
13
47
|
def away(message = nil)
|
@@ -33,9 +67,19 @@ module Vetinari
|
|
33
67
|
end
|
34
68
|
|
35
69
|
def join(channel_name, key = nil)
|
36
|
-
|
37
|
-
|
38
|
-
|
70
|
+
channel = Channel.new(channel_name, @actor)
|
71
|
+
channel.join(key)
|
72
|
+
end
|
73
|
+
|
74
|
+
def message(receiver, message)
|
75
|
+
channel = @config.isupport['CHANTYPES'].any? do |chantype|
|
76
|
+
receiver.start_with?(chantype)
|
77
|
+
end
|
78
|
+
|
79
|
+
if channel
|
80
|
+
Channel.new(receiver, @actor).message(message)
|
81
|
+
else
|
82
|
+
User.new(receiver, @actor).message(message)
|
39
83
|
end
|
40
84
|
end
|
41
85
|
end
|
data/lib/vetinari/version.rb
CHANGED
data/spec/callback_spec.rb
CHANGED
@@ -16,4 +16,13 @@ describe 'Callback' do
|
|
16
16
|
cb.remove
|
17
17
|
expect(callbacks[:channel]).to have(1).callback
|
18
18
|
end
|
19
|
+
|
20
|
+
it 'can be removed and terminated' do
|
21
|
+
cb = subject.on(:channel)
|
22
|
+
expect(callbacks[:channel]).to have(2).callback
|
23
|
+
expect(cb.alive?).to be_true
|
24
|
+
cb.remove_and_terminate
|
25
|
+
expect(callbacks[:channel]).to have(1).callback
|
26
|
+
expect(cb.alive?).to be_false
|
27
|
+
end
|
19
28
|
end
|
data/spec/join_spec.rb
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'Bot#join' do
|
4
|
+
subject { Vetinari::Bot.new { |c| c.verbose = false } }
|
5
|
+
|
6
|
+
before(:each) do
|
7
|
+
subject.parse(':server 001 Vetinari :Welcome message')
|
8
|
+
subject.parse(':server 376 Vetinari :End of /MOTD command.')
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'returns a Future' do
|
12
|
+
expect(subject.join('#mended_drum')).to be_a(Celluloid::Future)
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'returns :joined if joined' do
|
16
|
+
future = subject.join('#mended_drum')
|
17
|
+
|
18
|
+
Thread.new do
|
19
|
+
subject.parse(':Vetinari!foo@bar JOIN #mended_drum')
|
20
|
+
end
|
21
|
+
|
22
|
+
expect(future.value).to be(:joined)
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'returns :already_joined if already in the channel' do
|
26
|
+
subject.parse(':Vetinari!foo@bar JOIN #mended_drum')
|
27
|
+
future = subject.join('#mended_drum')
|
28
|
+
expect(future.value).to be(:already_joined)
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'returns :locked if channel is locked' do
|
32
|
+
future = subject.join('#mended_drum')
|
33
|
+
|
34
|
+
Thread.new do
|
35
|
+
subject.parse(':server 475 Vetinari #mended_drum :Cannot join channel (+k) - bad key')
|
36
|
+
end
|
37
|
+
|
38
|
+
expect(future.value).to be(:locked)
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'returns :full if channel is full' do
|
42
|
+
future = subject.join('#mended_drum')
|
43
|
+
|
44
|
+
Thread.new do
|
45
|
+
subject.parse(':server 471 Vetinari #mended_drum :Cannot join channel (+l) - channel is full, try again later')
|
46
|
+
end
|
47
|
+
|
48
|
+
expect(future.value).to be(:full)
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'returns :banned if the bot is banned from the channel' do
|
52
|
+
future = subject.join('#mended_drum')
|
53
|
+
|
54
|
+
Thread.new do
|
55
|
+
subject.parse(':server 474 Vetinari #mended_drum :Cannot join channel (+b) - you are banned')
|
56
|
+
end
|
57
|
+
|
58
|
+
expect(future.value).to be(:banned)
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'returns :banned if the bot is banned from the channel' do
|
62
|
+
future = subject.join('#mended_drum')
|
63
|
+
|
64
|
+
Thread.new do
|
65
|
+
subject.parse(':server 473 Vetinari #mended_drum :Cannot join channel (+i) - you must be invited')
|
66
|
+
end
|
67
|
+
|
68
|
+
expect(future.value).to be(:invite_only)
|
69
|
+
end
|
70
|
+
|
71
|
+
it 'returns :timeout if no answer comes from the server' do
|
72
|
+
future = subject.join('#mended_drum')
|
73
|
+
expect(future.value).to be(:timeout)
|
74
|
+
end
|
75
|
+
end
|
data/spec/rename_spec.rb
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'Bot#rename' do
|
4
|
+
subject { Vetinari::Bot.new { |c| c.verbose = false } }
|
5
|
+
|
6
|
+
before(:each) do
|
7
|
+
subject.parse(':server 001 Vetinari :Welcome message')
|
8
|
+
subject.parse(':server 376 Vetinari :End of /MOTD command.')
|
9
|
+
subject.parse(':server 005 Vetinari NICKLEN=10')
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'returns a Future' do
|
13
|
+
expect(subject.rename('Havelock')).to be_a(Celluloid::Future)
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'returns the current nickname if no changes would happen' do
|
17
|
+
future = subject.rename('Vetinari')
|
18
|
+
expect(future.value).to be_a(String)
|
19
|
+
expect(future.value).to eq('Vetinari')
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'returns String if renamed' do
|
23
|
+
future = subject.rename('Havelock')
|
24
|
+
|
25
|
+
Thread.new do
|
26
|
+
subject.parse(':Vetinari!foo@bar NICK :Havelock')
|
27
|
+
end
|
28
|
+
|
29
|
+
expect(future.value).to be_a(String)
|
30
|
+
expect(future.value).to eq('Havelock')
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'returns :erroneous_nickname if nickname is erroneous' do
|
34
|
+
future = subject.rename('NickServ')
|
35
|
+
|
36
|
+
Thread.new do
|
37
|
+
subject.parse(':server 432 Vetinari NickServ :Erroneous Nickname')
|
38
|
+
end
|
39
|
+
|
40
|
+
expect(future.value).to be_a(Symbol)
|
41
|
+
expect(future.value).to eq(:erroneous_nickname)
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'returns :nickname_in_use if nickname is taken' do
|
45
|
+
future = subject.rename('TheLibrarian')
|
46
|
+
|
47
|
+
Thread.new do
|
48
|
+
subject.parse(':server 433 Vetinari TheLibrarian :Nickname is already in use.')
|
49
|
+
end
|
50
|
+
|
51
|
+
expect(future.value).to be_a(Symbol)
|
52
|
+
expect(future.value).to eq(:nickname_in_use)
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'slices the nick if it is too long' do
|
56
|
+
bare = subject.bare_object
|
57
|
+
expect(bare).to receive(:raw).with('NICK :1234567890').once
|
58
|
+
subject.rename('1234567890over')
|
59
|
+
end
|
60
|
+
end
|
data/vetinari.gemspec
CHANGED
@@ -26,5 +26,5 @@ Gem::Specification.new do |spec|
|
|
26
26
|
spec.add_development_dependency 'bundler', '~> 1.3'
|
27
27
|
spec.add_development_dependency 'pry', '~> 0.9'
|
28
28
|
spec.add_development_dependency 'rake', '~> 10.0'
|
29
|
-
spec.add_development_dependency 'rspec', '
|
29
|
+
spec.add_development_dependency 'rspec', '2.14.0.rc1'
|
30
30
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: vetinari
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tobias Bühlmann
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-05-
|
11
|
+
date: 2013-05-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: celluloid-io
|
@@ -70,16 +70,16 @@ dependencies:
|
|
70
70
|
name: rspec
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
|
-
- -
|
73
|
+
- - '='
|
74
74
|
- !ruby/object:Gem::Version
|
75
|
-
version:
|
75
|
+
version: 2.14.0.rc1
|
76
76
|
type: :development
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
|
-
- -
|
80
|
+
- - '='
|
81
81
|
- !ruby/object:Gem::Version
|
82
|
-
version:
|
82
|
+
version: 2.14.0.rc1
|
83
83
|
description: |2
|
84
84
|
Vetinari is a multithreaded IRC Bot Framework using the Celluloid::IO
|
85
85
|
library.
|
@@ -119,6 +119,8 @@ files:
|
|
119
119
|
- spec/channel_spec.rb
|
120
120
|
- spec/default_callbacks_spec.rb
|
121
121
|
- spec/isupport_spec.rb
|
122
|
+
- spec/join_spec.rb
|
123
|
+
- spec/rename_spec.rb
|
122
124
|
- spec/spec_helper.rb
|
123
125
|
- spec/user_management_spec.rb
|
124
126
|
- spec/user_spec.rb
|
@@ -153,6 +155,8 @@ test_files:
|
|
153
155
|
- spec/channel_spec.rb
|
154
156
|
- spec/default_callbacks_spec.rb
|
155
157
|
- spec/isupport_spec.rb
|
158
|
+
- spec/join_spec.rb
|
159
|
+
- spec/rename_spec.rb
|
156
160
|
- spec/spec_helper.rb
|
157
161
|
- spec/user_management_spec.rb
|
158
162
|
- spec/user_spec.rb
|