presence 0.0.1 → 0.0.2

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/.simplecov CHANGED
@@ -10,5 +10,6 @@ SimpleCov.formatter = SimpleCov::Formatter::QualityFormatter
10
10
 
11
11
  SimpleCov.start do
12
12
  add_filter '/spec/'
13
- add_group 'CLI', 'lib/duple/cli'
13
+ add_group 'CLI', 'lib/presence/cli'
14
+ add_group 'Listeners', 'lib/presence/listeners'
14
15
  end
data/Rakefile CHANGED
@@ -13,7 +13,7 @@ begin
13
13
  cane.abc_max = 15
14
14
  cane.style_measure = 100
15
15
  cane.style_glob = '{lib}/**/*.rb'
16
- cane.gte = {'coverage/covered_percent' => 50}
16
+ cane.gte = {'coverage/covered_percent' => 80}
17
17
  end
18
18
  rescue LoadError
19
19
  warn "cane not available, quality task not provided."
data/bin/presence_scan CHANGED
@@ -8,14 +8,28 @@ if File.exists?(File.join(File.expand_path('../..', __FILE__), '.git'))
8
8
  end
9
9
 
10
10
  require 'presence'
11
+
11
12
  # Presence::CLI::Root.start
12
13
 
14
+ # Usage: presence [OPTIONS]
15
+ #
16
+ # presence --start 10.0.1.1 --end 10.0.1.30
17
+ # presence --prefix 192.168.0
18
+ # presence --verbose
19
+ # presence --quiet
20
+ # presence --once
21
+ # presence --loop
22
+ # presence --listener Carnegie::Listener
23
+
24
+ # --once
13
25
  # s = Presence::Scanner.new
14
26
  # s.register_listener(Presence::Logger.new)
15
27
  # s.register_listener(Presence::Tracker.new)
16
28
  # s.scan
17
29
 
30
+ # --loop
18
31
  Presence::Scanner.scan_loop do |s|
32
+ # s.options[:octet_range] = (30..32)
19
33
  s.register_listener(Presence::Logger.new)
20
34
  s.register_listener(Presence::Tracker.new)
21
35
  end
@@ -2,7 +2,8 @@ module Presence
2
2
  # Wrapper class for shell command execution.
3
3
  class Commands
4
4
  def arping(ip)
5
- result = run("sudo arping -c 1 #{ip}")
5
+ cmd = "sudo arping -c 1 #{ip}"
6
+ result = run(cmd)
6
7
  [cmd, result]
7
8
  end
8
9
 
@@ -0,0 +1,83 @@
1
+ require "net/https"
2
+ require "uri"
3
+
4
+ module Presence
5
+
6
+ # Scanner listener that sends an HTTP notification whenever a new client
7
+ # connects or when a connected client disconnects. This listener is intended
8
+ # to be used with Presence::Tracker when scanning in a loop.
9
+ class HTTPNotifier
10
+
11
+ def initialize(options = nil)
12
+ options ||= {}
13
+ @options = {
14
+ use_ssl: false,
15
+ verify_mode: OpenSSL::SSL::VERIFY_PEER
16
+ }.merge(options)
17
+ end
18
+
19
+ def listener_registered(l, scanner)
20
+ @scanner ||= scanner
21
+ end
22
+
23
+ def mac_connected(mac, ip)
24
+ notify(:mac_connected, { mac: mac, ip: ip })
25
+ end
26
+
27
+ def mac_disconnected(mac, old_ip)
28
+ notify(:mac_disconnected, { mac: mac, ip: old_ip })
29
+ end
30
+
31
+ protected
32
+
33
+ def notify_uri
34
+ @notify_uri ||= URI.parse(@options[:url])
35
+ end
36
+
37
+ def notify(event, params)
38
+ request = prepare_request(event, params)
39
+ do_request(request)
40
+ end
41
+
42
+ def do_request(request)
43
+ response = nil
44
+
45
+ begin
46
+ http = prepare_http
47
+ response = http.request(request)
48
+ check_response(response)
49
+ rescue SocketError,
50
+ Timeout::Error,
51
+ Errno::ECONNREFUSED,
52
+ Errno::EHOSTDOWN,
53
+ Errno::EHOSTUNREACH,
54
+ Errno::ETIMEDOUT => e
55
+ @scanner.dispatch(:http_notification_failed, e.class.name, e.message)
56
+ end
57
+
58
+ response
59
+ end
60
+
61
+ def prepare_request(event, params)
62
+ request = Net::HTTP::Post.new(notify_uri.request_uri, @options[:headers])
63
+ request.set_form_data(params.merge(event: event))
64
+ if @options[:username]
65
+ request.basic_auth(@options[:username], @options[:password])
66
+ end
67
+ request
68
+ end
69
+
70
+ def prepare_http
71
+ http = Net::HTTP.new(notify_uri.host, notify_uri.port)
72
+ http.use_ssl = @options[:use_ssl]
73
+ http.verify_mode = @options[:verify_mode]
74
+ http
75
+ end
76
+
77
+ def check_response(response)
78
+ unless (200..206).map(&:to_s).include?(response.code)
79
+ @scanner.dispatch(:http_notification_failed, response.code, response.body)
80
+ end
81
+ end
82
+ end
83
+ end
@@ -5,61 +5,88 @@ module Presence
5
5
  # default, it uses a Logger instance that writes to stdout. To enable more
6
6
  # verbose output, set:
7
7
  #
8
- # logger.level = ::Logger::INFO
8
+ # logger.log.level = ::Logger::INFO
9
9
  #
10
10
  # or:
11
11
  #
12
- # logger.level = ::Logger::DEBUG
12
+ # logger.log.level = ::Logger::DEBUG
13
13
  #
14
- # To write to a file or some other outlet, pass an instance of Logger to the
14
+ # To write to a file or some other outlet, pass a Ruby Logger instance to the
15
15
  # constructor.
16
16
  class Logger
17
- attr_accessor :logger
17
+ attr_accessor :log
18
18
 
19
19
  def initialize(log = nil)
20
20
  if log.nil?
21
- log = ::Logger.new(STDOUT)
21
+ log = ::Logger.new($stdout)
22
22
  log.level = ::Logger::WARN
23
23
  log.formatter = proc do |severity, datetime, progname, msg|
24
24
  "#{msg}\n"
25
25
  end
26
26
  end
27
- self.logger = log
27
+ self.log = log
28
28
  end
29
29
 
30
30
  def listener_registered(listener, scanner)
31
- logger.info "Registered listener: <#{listener.class}> for: #{scanner}"
31
+ log.info "Registered listener: <#{listener.class}> for: #{scanner}"
32
32
  end
33
33
 
34
34
  def scan_started(ip_prefix, range)
35
- logger.info "Checking range: #{ip_prefix}.#{range.first} to #{ip_prefix}.#{range.last}"
35
+ log.info "Scanning range: #{ip_prefix}.#{range.first} to #{ip_prefix}.#{range.last}"
36
36
  end
37
37
 
38
38
  def scan_finished(ip_prefix, range)
39
- logger.info "Scan finished."
39
+ log.info "Scan finished."
40
40
  end
41
41
 
42
42
  def ip_scanned(ip, cmd, result)
43
- logger.debug " - Checked #{ip} with #{cmd}"
43
+ log.debug " - Checked #{ip} with #{cmd}"
44
44
  result.split("\n").each do |l|
45
- logger.debug " #{l}"
45
+ log.debug " #{l}"
46
46
  end
47
47
  end
48
48
 
49
49
  def localhost_found(ip, mac)
50
- logger.debug " * Found localhost!"
50
+ log.debug " * Found localhost!"
51
51
  end
52
52
 
53
53
  def mac_found(ip, mac)
54
- logger.debug
55
- logger.debug " * Found #{mac} at #{ip}"
56
- logger.debug
54
+ log.debug " * Found #{mac} at #{ip}"
57
55
  end
58
56
 
59
57
  def mac_not_found(ip)
60
- logger.debug
61
- logger.debug " * No MAC found at #{ip}"
62
- logger.debug
58
+ log.debug " * No MAC found at #{ip}"
59
+ end
60
+
61
+ protected
62
+
63
+ def log_unknown_event(method_sym, *arguments)
64
+ # puts "method_sym = #{method_sym}"
65
+ # puts "arguments = #{arguments.inspect}"
66
+ # puts "log = #{log}"
67
+ # raise 'hell'
68
+ log.warn("#{method_sym}: #{arguments.inspect}")
69
+ end
70
+
71
+ # Always log events, even if there is no explicit handler. Generate a
72
+ # method at runtime so we don't have to do method_missing every time.
73
+ def method_missing(method_sym, *arguments, &block)
74
+ arg_names = arguments.each_with_index.map { |arg, i| "arg#{i}" }
75
+ arg_list = arg_names.join(',')
76
+ instance_eval <<-RUBY
77
+ def #{method_sym}(#{arg_list})
78
+ log_unknown_event(:#{method_sym}, #{arg_list})
79
+ end
80
+ RUBY
81
+ # def method_sym(arg1, arg2, ...)
82
+ # log_unknown_event(:method_sym, arg1, arg2, ...)
83
+ # end
84
+ send(method_sym, *arguments)
85
+ end
86
+
87
+ # Respond to anything.
88
+ def respond_to_missing?(method_sym, include_private = false)
89
+ true
63
90
  end
64
91
  end
65
92
  end
@@ -7,20 +7,23 @@ module Presence
7
7
  # list of MAC addresses on the network and detect when a new client connects
8
8
  # or when a connected client disconnects.
9
9
  class Tracker
10
+
10
11
  def initialize
11
12
  @mac_history = {}
12
13
  @current_list = Presence::MACList.new
13
14
  end
14
15
 
15
16
  def listener_registered(l, scanner)
16
- scanner.register_listener(@current_list) if l == self
17
+ @scanner ||= scanner
18
+ @scanner.register_listener(@current_list) if l == self
17
19
  end
18
20
 
19
21
  def mac_found(ip, mac)
20
22
  if @mac_history[mac].nil?
21
- mac_connected(mac, ip)
23
+ dispatch(:mac_connected, mac, ip)
22
24
  elsif @mac_history[mac] != ip
23
- mac_changed(mac, @mac_history[mac], ip)
25
+ old_ip = @mac_history[mac]
26
+ dispatch(:mac_changed, mac, old_ip, ip)
24
27
  end
25
28
  @mac_history[mac] = ip
26
29
  end
@@ -29,25 +32,14 @@ module Presence
29
32
  macs_left = @mac_history.keys - @current_list.macs_found.keys
30
33
  macs_left.each do |mac|
31
34
  old_ip = @mac_history[mac]
32
- mac_disconnected(mac, old_ip)
35
+ dispatch(:mac_disconnected, mac, old_ip)
33
36
  @mac_history.delete(mac)
34
37
  end
35
38
  @current_list.macs_found.clear
36
39
  end
37
40
 
38
- def mac_connected(mac, ip)
39
- puts " ** #{mac} connected as #{ip}"
40
- # Do something interesting.
41
- end
42
-
43
- def mac_changed(mac, old_ip, new_ip)
44
- puts " ** #{mac} changed ip from: #{old_ip} to #{new_ip}"
45
- # Do something interesting.
46
- end
47
-
48
- def mac_disconnected(mac, old_ip)
49
- puts " ** #{mac} disconnected from #{old_ip}"
50
- # Do something interesting.
41
+ def dispatch(event, *args)
42
+ @scanner.dispatch(event, *args)
51
43
  end
52
44
  end
53
45
  end
@@ -82,12 +82,11 @@ module Presence
82
82
  class << self
83
83
  def check_env
84
84
  commands = Commands.new
85
- if commands.run('which ifconfig').size == 0
86
- raise Presence::InvalidEnvironment.new("Unsupported platform: ifconfig not found.")
87
- end
88
- if commands.run('which arping').size == 0
89
- raise Presence::InvalidEnvironment.new("Unsupported platform: arping not found.")
90
- raise Presence::InvalidEnvironment.new("Install arping first: brew install arping")
85
+ required_commands = %w{ifconfig arping}
86
+ required_commands.each do |cmd|
87
+ if commands.run("which #{cmd}").size == 0
88
+ raise Presence::InvalidEnvironment.new("Unsupported platform: #{cmd} not found.")
89
+ end
91
90
  end
92
91
  end
93
92
 
@@ -1,3 +1,3 @@
1
1
  module Presence
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
data/lib/presence.rb CHANGED
@@ -7,3 +7,4 @@ require 'presence/listeners/mac_list'
7
7
  require 'presence/listeners/mac_printer'
8
8
  require 'presence/listeners/nmapper'
9
9
  require 'presence/listeners/tracker'
10
+ require 'presence/listeners/http_notifier'
@@ -0,0 +1,69 @@
1
+ require 'spec_helper'
2
+
3
+ describe Presence::HTTPNotifier do
4
+ let(:username) { nil }
5
+ let(:password) { nil }
6
+ let(:notifier) {
7
+ Presence::HTTPNotifier.new(
8
+ url: 'http://example.com/presence_events.json',
9
+ username: username,
10
+ password: password
11
+ )
12
+ }
13
+
14
+ let(:scanner) { stub(Presence::Scanner) }
15
+ before { notifier.listener_registered(notifier, scanner) }
16
+
17
+ let(:http) { stub(Net::HTTP, :use_ssl= => nil, :verify_mode= => nil) }
18
+ let(:response) { stub(code: '200') }
19
+ before {
20
+ http.stub(:request).and_return(response)
21
+ Net::HTTP.stub(:new).with('example.com', 80).and_return(http)
22
+ }
23
+
24
+ context 'with a username and password' do
25
+ let(:username) { 'margot' }
26
+ let(:password) { 'poppie' }
27
+
28
+ it 'sends the username and password in the request' do
29
+ http.should_receive(:request) do |r|
30
+ r['authorization'].should == 'Basic bWFyZ290OnBvcHBpZQ=='
31
+ response
32
+ end
33
+ notifier.mac_connected('AA:BB:CC:DD:EE:FF', '10.0.1.49')
34
+ end
35
+ end
36
+
37
+ it 'dispatches an error notification if the request returns an error code' do
38
+ response.should_receive(:code).at_least(1).times.and_return('400')
39
+ response.should_receive(:body).and_return('Invalid request')
40
+ scanner.should_receive(:dispatch).with(:http_notification_failed, '400', 'Invalid request')
41
+
42
+ notifier.mac_connected('AA:BB:CC:DD:EE:FF', '10.0.1.49')
43
+ end
44
+
45
+ it 'dispatches an error notification if the request raises a network error' do
46
+ http.should_receive(:request).and_raise(SocketError.new('bad things occurred'))
47
+ scanner.should_receive(:dispatch).with(:http_notification_failed, 'SocketError', 'bad things occurred')
48
+
49
+ notifier.mac_connected('AA:BB:CC:DD:EE:FF', '10.0.1.49')
50
+ end
51
+
52
+ it 'sends a POST request on mac_connected' do
53
+ http.should_receive(:request) do |r|
54
+ r.method.should == 'POST'
55
+ r.body.should == 'mac=AA%3ABB%3ACC%3ADD%3AEE%3AFF&ip=10.0.1.49&event=mac_connected'
56
+ response
57
+ end
58
+ notifier.mac_connected('AA:BB:CC:DD:EE:FF', '10.0.1.49')
59
+ end
60
+
61
+ it 'sends a POST request on mac_disconnected' do
62
+ http.should_receive(:request) do |r|
63
+ r.method.should == 'POST'
64
+ r.body.should == 'mac=AA%3ABB%3ACC%3ADD%3AEE%3AFF&ip=10.0.1.49&event=mac_disconnected'
65
+ response
66
+ end
67
+ notifier.mac_disconnected('AA:BB:CC:DD:EE:FF', '10.0.1.49')
68
+ end
69
+ end
@@ -0,0 +1,103 @@
1
+ require 'spec_helper'
2
+
3
+ describe Presence::Logger do
4
+ let(:level) { ::Logger::INFO }
5
+ let(:io) { StringIO.new }
6
+ let(:log) {
7
+ log = ::Logger.new(io)
8
+ log.level = level
9
+ log.formatter = proc do |severity, datetime, progname, msg|
10
+ "#{msg}\n"
11
+ end
12
+ log
13
+ }
14
+ let(:logger) { Presence::Logger.new(log) }
15
+
16
+ context 'with no ::Logger specified' do
17
+ let(:log) { nil }
18
+
19
+ it 'logs warnings to stdout by default' do
20
+ result = capture_stdout do |variable|
21
+ logger.log.warn('Run, baby, run!')
22
+ end
23
+ result.should == "Run, baby, run!\n"
24
+ end
25
+
26
+ it 'does not log info by default' do
27
+ result = capture_stdout do |variable|
28
+ logger.log.info('Run, baby, run!')
29
+ end
30
+ result.should == ''
31
+ end
32
+ end
33
+
34
+ context 'with DEBUG logging' do
35
+ let(:level) { ::Logger::DEBUG }
36
+
37
+ it 'logs ip_scanned events' do
38
+ logger.ip_scanned('10.0.1.1', 'sudo arping', 'nada')
39
+ io.string.should == " - Checked 10.0.1.1 with sudo arping\n nada\n"
40
+ end
41
+
42
+ it 'logs localhost_found events' do
43
+ logger.localhost_found('10.0.1.1', 'AA:BB:CC:DD:EE:FF')
44
+ io.string.should == " * Found localhost!\n"
45
+ end
46
+
47
+ it 'logs mac_found events' do
48
+ logger.mac_found('10.0.1.1', 'aa:bb:cc:dd:ee:ff')
49
+ io.string.should == " * Found aa:bb:cc:dd:ee:ff at 10.0.1.1\n"
50
+ end
51
+
52
+ it 'logs mac_not_found events' do
53
+ logger.mac_not_found('10.0.1.1')
54
+ io.string.should == " * No MAC found at 10.0.1.1\n"
55
+ end
56
+
57
+ it 'logs unknown events' do
58
+ logger.respond_to?(:miracle_occurred).should be_true
59
+ logger.miracle_occurred('256.256.256.256', 'GG:GG:GG:GG:GG:GG', 49)
60
+ io.string.should == "miracle_occurred: [\"256.256.256.256\", \"GG:GG:GG:GG:GG:GG\", 49]\n"
61
+ end
62
+
63
+ end
64
+
65
+ context 'with INFO logging' do
66
+ let(:level) { ::Logger::INFO }
67
+
68
+ it 'logs listener_registered events' do
69
+ logger.listener_registered(logger, 'Scanner')
70
+ io.string.should == "Registered listener: <Presence::Logger> for: Scanner\n"
71
+ end
72
+
73
+ it 'logs scan_started events' do
74
+ logger.scan_started('10.0.1', (1..255))
75
+ io.string.should == "Scanning range: 10.0.1.1 to 10.0.1.255\n"
76
+ end
77
+
78
+ it 'logs scan_finished events' do
79
+ logger.scan_finished('10.0.1', (1..255))
80
+ io.string.should == "Scan finished.\n"
81
+ end
82
+
83
+ it 'does not log ip_scanned events' do
84
+ logger.ip_scanned('10.0.1.1', 'sudo arping', 'nada')
85
+ io.string.should == ''
86
+ end
87
+
88
+ it 'does not log localhost_found events' do
89
+ logger.localhost_found('10.0.1.1', 'aa:bb:cc:dd:ee:ff')
90
+ io.string.should == ''
91
+ end
92
+
93
+ it 'does not log mac_found events' do
94
+ logger.mac_found('10.0.1.1', 'aa:bb:cc:dd:ee:ff')
95
+ io.string.should == ''
96
+ end
97
+
98
+ it 'does not log mac_not_found events' do
99
+ logger.mac_not_found('10.0.1.1')
100
+ io.string.should == ''
101
+ end
102
+ end
103
+ end
@@ -10,7 +10,7 @@ describe Presence::Scanner do
10
10
 
11
11
  let(:commands) {
12
12
  commands = stub(Presence::Commands)
13
- Presence::Commands.should_receive(:new).and_return(commands)
13
+ Presence::Commands.stub(:new).and_return(commands)
14
14
  commands
15
15
  }
16
16
  let(:listener) {
@@ -28,6 +28,63 @@ describe Presence::Scanner do
28
28
  commands.stub(:arping).with(ip).and_return([arping_cmd, mac])
29
29
  }
30
30
 
31
+ describe '.check_env' do
32
+ before {
33
+ commands.stub(:run).with('which ifconfig').and_return('/sbin/ifconfig')
34
+ commands.stub(:run).with('which arping').and_return('/usr/local/sbin/arping')
35
+ }
36
+
37
+ it 'checks for ifconfig' do
38
+ commands.should_receive(:run).with('which ifconfig').and_return('/sbin/ifconfig')
39
+ Presence::Scanner.check_env
40
+ end
41
+
42
+ it 'raises an exception if ifconfig is not found' do
43
+ commands.should_receive(:run).with('which ifconfig').and_return('')
44
+ expect {
45
+ Presence::Scanner.check_env
46
+ }.to raise_error(Presence::InvalidEnvironment, "Unsupported platform: ifconfig not found.")
47
+ end
48
+
49
+ it 'checks for arping' do
50
+ commands.should_receive(:run).with('which arping').and_return('/usr/local/sbin/arping')
51
+ Presence::Scanner.check_env
52
+ end
53
+
54
+ it 'raises an exception if arping is not found' do
55
+ commands.should_receive(:run).with('which arping').and_return('')
56
+ expect {
57
+ Presence::Scanner.check_env
58
+ }.to raise_error(Presence::InvalidEnvironment, "Unsupported platform: arping not found.")
59
+ end
60
+ end
61
+
62
+ describe '.scan_loop' do
63
+ let(:scanner) { mock(Presence::Scanner) }
64
+ before { Presence::Scanner.should_receive(:new).and_return(scanner) }
65
+
66
+ it 'scans until interrupted' do
67
+ scanner.should_receive(:scan)
68
+ scanner.should_receive(:scan)
69
+ scanner.should_receive(:scan).and_raise(Interrupt.new)
70
+ Presence::Scanner.scan_loop
71
+ end
72
+
73
+ it 'yields the scanner instance to a block' do
74
+ scanner.stub(:scan).and_raise(Interrupt.new)
75
+ scanner.should_receive(:register_listener)
76
+ Presence::Scanner.scan_loop do |s|
77
+ s.register_listener(Object.new)
78
+ end
79
+ end
80
+ end
81
+
82
+ describe '#to_s' do
83
+ it 'overrides to_s' do
84
+ scanner.to_s.should == "<Presence::Scanner ip_prefix: '10.0.1' octet_range: (30..32)>"
85
+ end
86
+ end
87
+
31
88
  describe '#scan' do
32
89
  it 'dispatches a scan_started event' do
33
90
  listener.should_receive(:scan_started).with('10.0.1', octet_range)
@@ -0,0 +1,4 @@
1
+ require 'spec_helper'
2
+
3
+ describe Presence::Tracker do
4
+ end
@@ -0,0 +1,33 @@
1
+ module Presence
2
+ module IOSpecHelpers
3
+ def suppress_output
4
+ @original_stdout, $stdout = $stdout, StringIO.new
5
+ @original_stderr, $stderr = $stderr, StringIO.new
6
+ end
7
+
8
+ def reset_output
9
+ $stdout = @original_stdout
10
+ $stderr = @original_stderr
11
+ end
12
+
13
+ def capture_stdout
14
+ original_stdout, $stdout = $stdout, StringIO.new
15
+ yield
16
+ $stdout.string
17
+ ensure
18
+ $stdout = original_stdout
19
+ end
20
+
21
+ def capture_stderr
22
+ original_stderr, $stderr = $stderr, StringIO.new
23
+ yield
24
+ $stderr.string
25
+ ensure
26
+ $stderr = original_stderr
27
+ end
28
+ end
29
+ end
30
+
31
+ RSpec.configure do |config|
32
+ config.include Presence::IOSpecHelpers
33
+ end
metadata CHANGED
@@ -2,14 +2,14 @@
2
2
  name: presence
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.0.1
5
+ version: 0.0.2
6
6
  platform: ruby
7
7
  authors:
8
8
  - Jason Wadsworth
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-11-23 00:00:00.000000000 Z
12
+ date: 2012-11-24 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  prerelease: false
@@ -94,6 +94,7 @@ files:
94
94
  - lib/presence.rb
95
95
  - lib/presence/commands.rb
96
96
  - lib/presence/errors.rb
97
+ - lib/presence/listeners/http_notifier.rb
97
98
  - lib/presence/listeners/logger.rb
98
99
  - lib/presence/listeners/mac_list.rb
99
100
  - lib/presence/listeners/mac_printer.rb
@@ -102,8 +103,12 @@ files:
102
103
  - lib/presence/scanner.rb
103
104
  - lib/presence/version.rb
104
105
  - presence.gemspec
106
+ - spec/presence/http_notifier_spec.rb
107
+ - spec/presence/logger_spec.rb
105
108
  - spec/presence/scanner_spec.rb
109
+ - spec/presence/tracker_spec.rb
106
110
  - spec/spec_helper.rb
111
+ - spec/support/io_spec_helpers.rb
107
112
  homepage: https://github.com/subakva/presence
108
113
  licenses: []
109
114
  post_install_message:
@@ -129,5 +134,9 @@ signing_key:
129
134
  specification_version: 3
130
135
  summary: Plays theme music when d8:d1:cb:b3:af:c4 arrives.
131
136
  test_files:
137
+ - spec/presence/http_notifier_spec.rb
138
+ - spec/presence/logger_spec.rb
132
139
  - spec/presence/scanner_spec.rb
140
+ - spec/presence/tracker_spec.rb
133
141
  - spec/spec_helper.rb
142
+ - spec/support/io_spec_helpers.rb