vetinari 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8caa318b353a259ce354a4f33ac6512929a70ddc
4
- data.tar.gz: 6b0c114d8756323c6c93c7945e44b5c1392ee852
3
+ metadata.gz: a7b2a839017a8a6ad9cb366e4983223d18d79125
4
+ data.tar.gz: e9283985e9363ac330abaf31f07965ec26ef3049
5
5
  SHA512:
6
- metadata.gz: edd9ea43bb5a3636a2a4dec5246c205c40d18c310d24782e4d43cfce515fa89558c83ae2f261b823053d45456265f38aca52e0d9d7a2ade0969894ba1f3a601d
7
- data.tar.gz: ce1804db1898b39dfc6869dac32f98b3c2b1a9846e02a8ef8881c504e7b48bcaa71101b3ddad80a3d72009be0f106bcf14e1de00336cce6f9e223f5852d3d7d8
6
+ metadata.gz: e8faa48002d977fe10bed20ed4aa6e0f39669c0abdae838be9e13fa7d713e42c2361c63e0c499211e13bc68f63eb488ab14347d1110dc7a022f3a5beb6e19e43
7
+ data.tar.gz: 2c6726ab26892d11914ec986ae1ec5e7afe57c5dd35fa1164c9004c98dd4c19645a27dfb013d84c06db7f71681c5d4805b15cf0650f8f1b809a4ef34c522abde
data/Gemfile CHANGED
@@ -1,2 +1,4 @@
1
1
  source 'https://rubygems.org'
2
2
  gemspec
3
+
4
+ gem 'celluloid', github: 'celluloid/celluloid'
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # Vetinari [![Gem Version](https://badge.fury.io/rb/vetinari.png)](http://badge.fury.io/rb/vetinari)
1
+ # Vetinari [![Gem Version](https://badge.fury.io/rb/vetinari.png)](http://badge.fury.io/rb/vetinari) [![Dependency Status](https://gemnasium.com/tbuehlmann/vetinari.png)](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(/ /)
@@ -27,6 +27,10 @@ module Vetinari
27
27
  @container.remove(@event, @uuid)
28
28
  end
29
29
 
30
+ def remove_and_terminate
31
+ @container.remove(@event, @uuid, true)
32
+ end
33
+
30
34
  def inspect
31
35
  event = @event.inspect
32
36
  options = @options.inspect
@@ -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
 
@@ -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
- unless @channels.has_channel?(channel_name)
37
- channel = Channel.new(channel_name, @actor)
38
- channel.join key
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
@@ -1,3 +1,3 @@
1
1
  module Vetinari
2
- VERSION = Gem::Version.new('0.1.0')
2
+ VERSION = Gem::Version.new('0.2.0')
3
3
  end
@@ -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
@@ -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', '~> 2.13'
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.1.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-14 00:00:00.000000000 Z
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: '2.13'
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: '2.13'
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