ubi 0.0.5 → 0.0.7

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9a9073e8291c6e092b1f3585191aa4c2c91e524d
4
- data.tar.gz: ceee4c37c817147c7f4a8f0d4627b3c5108ccbf5
3
+ metadata.gz: 7fdab4d682e936e1a133a4dc7be3d8b8e94e5911
4
+ data.tar.gz: a159c4494b80dd627fe1e977beea018dc85dcd4f
5
5
  SHA512:
6
- metadata.gz: 796e569c777e65d7a8aca7ceb5cb9579fc5f52bfdef22a16cb8b54ec2b48854e0ee207c66d90e2c6bead5fa5622ae328760cf8bad111859059695002871ad6c3
7
- data.tar.gz: 7791238d12cf001ed5e2d36d86645e42debe21f3a968ed9cc3c21e18636dcba4c1c44ce7714e526f78330827cb812826c3d261f4542a17729799452b75aa996e
6
+ metadata.gz: 2dfc19bf88633329bbe9ed38ff7181c5f9d772217319b03d4dc1c8ef8ef7bd5375590acf7ef3545ed6472d62b7a2e7b1ee1646fe1be1f1bd399db6ae90102a8f
7
+ data.tar.gz: f921d122f54a59b8997e36decfdd3072fff344d1b0d8b241fe0cd797e06427a8dbc6524d08c2ab3035ead12f9738ac0d4dbaf649663b7591d578d37791fb69cc
data/Rakefile CHANGED
@@ -6,4 +6,4 @@ require 'rubocop/rake_task'
6
6
  RSpec::Core::RakeTask.new
7
7
  RuboCop::RakeTask.new
8
8
 
9
- task default: [:rubocop, :spec]
9
+ task default: [:spec]
data/lib/ubi.rb CHANGED
@@ -1,15 +1,14 @@
1
- require 'pry'
2
- require 'thor'
3
- require 'net/http'
4
- require 'net/https'
1
+ # require 'net/http'
2
+ # require 'net/https'
5
3
  require 'uri'
6
- require 'open-uri'
4
+ # require 'open-uri'
7
5
  require 'json'
8
6
  require 'phonelib'
9
7
  require 'nokogiri'
10
8
  require 'active_model'
11
9
  require 'active_support'
12
10
  require 'active_support/core_ext/hash'
11
+ require 'public_suffix'
13
12
  require 'ubi/version'
14
13
 
15
14
  # Ubiquous getters
@@ -1,42 +1,54 @@
1
- require 'polipus'
1
+ require 'retriever'
2
2
 
3
3
  module Ubi
4
4
  # Base for araneas (spiders)
5
5
  class Aranea
6
6
  OPTIONS = {
7
- workers: 3,
8
7
  user_agent: "Ubi v#{Ubi::VERSION}",
9
- depth_limit: 1
10
-
11
- # storage: MemoryStore
8
+ depth_limit: 3,
9
+ logger: Logger.new(STDOUT),
10
+ # redis_options: {
11
+ # host: 'localhost',
12
+ # db: 5,
13
+ # driver: 'hiredis'
14
+ # },
12
15
  }
13
- attr_accessor :thema, :url, :datum
16
+ attr_accessor :thema, :url, :datum, :html, :text, :opts
14
17
 
15
18
  def initialize(thema, url, opts = {})
16
19
  @thema = thema
17
20
  @url = url
18
- @opts = opts
21
+ @opts = OPTIONS.merge(opts)
22
+ @datum = []
23
+ @html = []
24
+ @text = ''
19
25
  end
20
26
 
21
27
  delegate :name, to: :thema
22
28
 
23
29
  def crawl!
24
- Polipus.crawler(name, url, OPTIONS.merge(@opts)) do |crawler|
25
- # In-place page processing
26
- crawler.on_page_downloaded do |page|
27
- # A nokogiri object
28
- puts "'#{page.doc.css('title').text}' (#{page.url})"
29
- end
30
+ @last_run = Time.now
31
+
32
+ puts "Crawler start #{name} #{url}"
33
+ Retriever::PageIterator.new(url, opts) do |page|
34
+ parse page.source
35
+ p [page.title, page.h1, page.h2]
30
36
  end
31
37
  end
32
38
 
33
- def parser(chunk)
34
- Nokogiri::HTML(chunk)
39
+ def parse(chunk)
40
+ @datum << chunk
41
+ @html << Nokogiri::HTML(chunk)
42
+ @text << html.last.text
43
+ end
44
+
45
+ def work
46
+ crawl! unless @last_run
47
+ true
35
48
  end
36
49
 
37
- def datum
38
- crawl! unless @datum
39
- @datum
50
+ def to_s
51
+ "#{thema} html: #{html.size} txt: #{text.size}"
40
52
  end
41
- end
42
- end
53
+ end # Aranea
54
+ end # Ubi
@@ -5,10 +5,11 @@ module Ubi
5
5
  attr_accessor :thema
6
6
 
7
7
  def initialize(query)
8
- @thema = Thema.new(query)
9
- start_with_search
10
- social_search
8
+ @thema = Thema.new(query[:name], query[:urls])
9
+ query[:urls] ? fetch_pages : start_with_search
10
+ social_search if query[:mail]
11
11
  other_search
12
+ do_the_twist
12
13
  end
13
14
 
14
15
  def start_with_search
@@ -23,6 +24,16 @@ module Ubi
23
24
  def other_search
24
25
  end
25
26
 
27
+ def fetch_pages
28
+ thema.araneas.each(&:work)
29
+ end
30
+
31
+ def do_the_twist
32
+ thema.araneas.each { |a| thema.try_datum(a) }
33
+ # pp thema.spec
34
+ # binding.pry if binding.respond_to?(:pry)
35
+ end
36
+
26
37
  delegate :spec, to: :thema
27
38
  end
28
39
  end
@@ -1,3 +1,5 @@
1
+ require 'pry'
2
+ require 'thor'
1
3
  require 'paint'
2
4
 
3
5
  module Ubi
@@ -14,7 +16,19 @@ module Ubi
14
16
  LONG
15
17
  option :address, type: :string # 'Subject\'s address'
16
18
  def find(name)
17
- Ubi::Artifex.new(name).spec
19
+ Ubi::Artifex.new(name: name).spec
20
+ end
21
+
22
+ # desc 'init', 'creates settings on ~'
23
+ desc 'site', 'Lookup in site'
24
+ long_desc <<-LONG
25
+
26
+ Find data on URL
27
+
28
+ LONG
29
+ option :address, type: :string # 'Subject\'s address'
30
+ def site(*url)
31
+ Ubi::Artifex.new(urls: url).spec
18
32
  end
19
33
  end
20
34
  end
@@ -24,6 +24,11 @@ module Ubi
24
24
  format
25
25
  end
26
26
 
27
+ def ==(other)
28
+ return unless other.respond_to?(:text)
29
+ text == other.text
30
+ end
31
+
27
32
  class << self
28
33
  #
29
34
  # Account for memorias
@@ -37,6 +42,7 @@ module Ubi
37
42
  def extract_text(datum)
38
43
  case datum
39
44
  when String then datum
45
+ when Ubi::Aranea then datum.text
40
46
  when Nokogiri::HTML then datum.data.text
41
47
  # when PDF / DOC / IMG (tesseract it =) then datum.data.text
42
48
  else fail "Can't parse `#{datum.class}`"
@@ -79,11 +85,6 @@ module Ubi
79
85
  def plural
80
86
  "#{key}s"
81
87
  end
82
-
83
- def ==(other)
84
- return unless other.respond_to?(:key)
85
- key == other.key
86
- end
87
88
  end
88
89
  end
89
90
  end
@@ -38,7 +38,8 @@ module Ubi
38
38
 
39
39
  def fetch_possible
40
40
  parse_zip
41
- @region = clean.scan(/\W([A-Z]{2})\W/).first.first
41
+ @region = clean.scan(/\W([A-Z]{2})\W/).first
42
+ @region = @region.first if @region
42
43
  @number = clean.scan(/\d+/).join(' ')
43
44
  end
44
45
  #
@@ -53,7 +54,7 @@ module Ubi
53
54
  end
54
55
 
55
56
  def format(location = :br)
56
- text.sub(*self.class.formats[location])
57
+ text #.sub(*self.class.formats[location])
57
58
  end
58
59
 
59
60
  class << self
@@ -85,7 +86,7 @@ module Ubi
85
86
  end
86
87
 
87
88
  def regex(hint)
88
- /((?:#{REGEXES[hint][:prefix].join('|')}).*)/i
89
+ /(\b(?:#{REGEXES[hint][:prefix].join('|')})\s.*)\b/i
89
90
  end
90
91
 
91
92
  def plural
@@ -2,6 +2,16 @@ module Ubi
2
2
  module Memoria
3
3
  # An Electronic Mail
4
4
  class Email < Base
5
+ #
6
+ # Clean up regex on init
7
+ #
8
+ def initialize(text, _hint = nil, opts = {})
9
+ text = text.downcase.gsub(/^\(|\.$/, '')
10
+ @text = text
11
+ # @addr = text
12
+ @opts = opts
13
+ end
14
+
5
15
  #
6
16
  #
7
17
  # Class methods
@@ -15,7 +25,7 @@ module Ubi
15
25
  ([a-z0-9!#$%&'*+/=?^_`{|}~-]+
16
26
  (?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@
17
27
  (?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+
18
- (?:[a-z0-9-]*[a-z0-9])?)
28
+ (?:[a-z0-9-]*[a-z0-9])?)(?:\W|\s|$)
19
29
  }x
20
30
  end
21
31
  end
@@ -0,0 +1,25 @@
1
+ module Ubi
2
+ module Memoria
3
+ # Show me your papers!
4
+
5
+ class Image < Base
6
+ attr_reader :size
7
+
8
+ def parser
9
+ @size = []
10
+ end
11
+ #
12
+ #
13
+ # Class methods
14
+ #
15
+ class << self
16
+ #
17
+ # Email regex
18
+ #
19
+ def regex(_hint)
20
+ /\.(jpg|png|svg)$/i
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -9,16 +9,20 @@ module Ubi
9
9
  end
10
10
 
11
11
  def format
12
+ number && number.e164
13
+ end
14
+
15
+ def national
12
16
  number && number.national
13
17
  end
14
18
 
15
- def rfc
19
+ def international
16
20
  number && number.international
17
21
  end
18
22
 
19
23
  class << self
20
24
  # http://rubular.com/r/tEHB6KcZzk
21
- def regex(hint = nil)
25
+ def regex(_hint = nil)
22
26
  /
23
27
  (?:^|\s)((?:\+\(?\d{1,3}\W)?[\._\-\/\s]*
24
28
  \(?\s*?\d{2,3}\s*?\)?[\._\-\/\s]*\d{3,5}
@@ -2,10 +2,27 @@ module Ubi
2
2
  module Memoria
3
3
  # A site, url and title?
4
4
  class Site < Base
5
+ attr_accessor :link, :uri
6
+
7
+ def initialize(text, _hint = nil, opts = {})
8
+ text = text.downcase.gsub(/^\(|\.$/, '')
9
+ text = "http://#{text}" unless text =~ %r{^\w{3,5}://}
10
+ @text = text
11
+ @link = tld_parser
12
+ @opts = opts
13
+ end
14
+
15
+ def tld_parser
16
+ @uri = URI.parse(text)
17
+ @link = PublicSuffix.parse(uri.host)
18
+ rescue PublicSuffix::DomainInvalid
19
+ nil
20
+ end
21
+
5
22
  #
6
23
  # Prefix http:// if there isn't one defined
7
24
  def format
8
- text =~ /^http/ ? text : "http://#{text}"
25
+ text
9
26
  end
10
27
 
11
28
  class << self
@@ -11,7 +11,7 @@ module Ubi
11
11
  }
12
12
  end
13
13
 
14
- def regex
14
+ def regex(url = nil)
15
15
  %r{https?://(?:\w+\.)*(#{url}/.*)}
16
16
  end
17
17
  end
@@ -11,7 +11,7 @@ module Ubi
11
11
  }
12
12
  end
13
13
 
14
- def regex
14
+ def regex(url)
15
15
  %r{https?://(?:\w+\.)*(#{url}/.*)}
16
16
  end
17
17
  end
@@ -12,6 +12,8 @@ module Ubi
12
12
  def initialize(name, urls = [], opts = {})
13
13
  @name = name
14
14
  @urls = urls
15
+ @name ||= urls.first.split('.').first.gsub(%r{^\w+://}, '')
16
+ @urls = @urls.map { |url| url =~ %r{://} ? url : "http://#{url}" }
15
17
  @opts = opts
16
18
  @cache = Ubi.memorias.reduce({}) { |a, e| a.merge(e => opts[e]) }
17
19
  reduce_names
@@ -22,36 +24,38 @@ module Ubi
22
24
  end
23
25
 
24
26
  def reduce_names
27
+ return unless name
25
28
  @ascii = name.mb_chars.downcase
26
29
  @downcase = name.mb_chars.downcase
27
30
  @clean = @downcase.gsub(/\W/, ' ')
28
31
  end
29
32
 
33
+ # Define memorias on thema
30
34
  Ubi.memorias.each do |memoria|
31
35
  define_method memoria.plural do
32
- instance_variable_get('@' + memoria.plural) ||
33
- instance_variable_set('@' + memoria.plural, [])
36
+ instance_variable_get("@#{memoria.plural}") ||
37
+ instance_variable_set("@#{memoria.plural}", [])
34
38
  end
35
39
  end
36
40
 
37
- def [](arg)
38
- @cache[arg]
39
- end
40
-
41
41
  def spec
42
42
  puts self
43
43
  Ubi.memorias.each do |memoria|
44
- print Paint[memoria.name, :black]
45
- puts self[memoria.key]
44
+ d = send(memoria.plural)
45
+ puts Paint["#{memoria.name} (#{d.size})", :black]
46
+ puts d
46
47
  end
47
48
  end
48
49
 
49
- def try_consultor(a)
50
- a = a.new(self)
50
+ def try_datum(a)
51
51
  Ubi.memorias.each do |m|
52
- puts Paint["Trying to find #{m} in #{a.class}", :green]
53
- @cache[m] = matches = m.parse(a.datum)
54
- puts matches if matches && !matches.empty?
52
+ print Paint["Trying to find #{m} in page ", :green]
53
+ matches = m.parse(a)
54
+ puts Paint[matches.size, :black]
55
+ next unless matches && !matches.empty?
56
+ matches.each do |match|
57
+ send(m.plural) << match unless send(m.plural).include?(match)
58
+ end
55
59
  end
56
60
  end
57
61
 
@@ -1,4 +1,4 @@
1
1
  # :nodoc:
2
2
  module Ubi
3
- VERSION = '0.0.5'
3
+ VERSION = '0.0.7'
4
4
  end
@@ -38,5 +38,4 @@ RSpec.configure do |config|
38
38
  # # VCR.use_cassette(vcr) { example.run }
39
39
  # puts Paint[" [#{Time.now - t}s]", :black]
40
40
  # end
41
- # config.before(:each) { Polipus::SignalHandler.disable }
42
41
  end
@@ -8,7 +8,7 @@ describe Aranea do
8
8
 
9
9
  it 'should use only one url' do
10
10
  aranea = Thema.new('Rock', ['r1.com', 'r2.com']).araneas.first
11
- expect(aranea.url).to eq('r1.com')
11
+ expect(aranea.url).to eq('http://r1.com')
12
12
  end
13
13
 
14
14
  # it 'should crawl a domain VCR ruby-lang', :vcr do
@@ -12,6 +12,24 @@ describe Memoria::Email do
12
12
  end
13
13
  end
14
14
 
15
+ describe 'parsed' do
16
+ def parse(site)
17
+ Memoria::Email.parse(site).first.to_s
18
+ end
19
+
20
+ describe 'http' do
21
+ let(:parsed) { 'hoho@fubah.com' }
22
+
23
+ it { expect(parse('hoho@fubah.com')).to eq(parsed) }
24
+ it { expect(parse('hoho@fubah.com.')).to eq(parsed) }
25
+ it { expect(parse('"hoho@fubah.com"')).to eq(parsed) }
26
+ it { expect(parse('( hoho@fubah.com )')).to eq(parsed) }
27
+ it { expect(parse('(hoho@fubah.com)')).to eq(parsed) }
28
+ it { expect(parse('(hoho@fubah.com.)')).to eq(parsed) }
29
+ it { expect(parse('hoho@fubah.com/')).to eq(parsed) }
30
+ end
31
+ end
32
+
15
33
  describe 'valid' do
16
34
  %w(
17
35
  foo@foo.com
@@ -1,6 +1,10 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Memoria::Phone do
4
+ def parse(phone)
5
+ Memoria::Phone.parse(phone).first.to_s
6
+ end
7
+
4
8
  describe 'simple test' do
5
9
  subject { Memoria::Phone.new('+551112345678') }
6
10
 
@@ -29,11 +33,11 @@ describe Memoria::Phone do
29
33
  end
30
34
  end
31
35
 
32
- describe 'parsed landlines' do
33
- def parse(phone)
34
- Memoria::Phone.parse(phone).first.rfc
35
- end
36
+ describe 'random tests' do
37
+ it { expect(parse('(16) 3919-0723')).to eq('+551639190723') }
38
+ end
36
39
 
40
+ describe 'parsed landlines' do
37
41
  let(:parsed) { '+1112345678' }
38
42
 
39
43
  load_fixture('phone.txt').each_line do |l|
@@ -44,11 +48,7 @@ describe Memoria::Phone do
44
48
  end
45
49
 
46
50
  describe 'parsed mobiles txt' do
47
- def parse(phone)
48
- Memoria::Phone.parse(phone).first.rfc
49
- end
50
-
51
- let(:parsed) { '+55 11 99814-5678' }
51
+ let(:parsed) { '+5511998145678' }
52
52
 
53
53
  load_fixture('mobile.txt').each_line do |l|
54
54
  it "Should parse phone #{l}" do
@@ -58,11 +58,7 @@ describe Memoria::Phone do
58
58
  end
59
59
 
60
60
  describe 'parsed mobiles' do
61
- def parse(phone)
62
- Memoria::Phone.parse(phone).first.rfc
63
- end
64
-
65
- let(:parsed) { '+55 11 98234-5678' }
61
+ let(:parsed) { '+5511982345678' }
66
62
 
67
63
  it { expect(parse('11982345678')).to eq(parsed) }
68
64
  it { expect(parse('11 982345678')).to eq(parsed) }
@@ -8,7 +8,7 @@ describe Memoria::Site do
8
8
  it { is_expected.to be_an Array }
9
9
 
10
10
  it 'should have text reader method' do
11
- expect(subject[0].text).to eq('somesite.com')
11
+ expect(subject[0].text).to eq('http://somesite.com')
12
12
  end
13
13
  end
14
14
 
@@ -21,6 +21,8 @@ describe Memoria::Site do
21
21
  let(:parsed) { 'http://fubah.com' }
22
22
 
23
23
  it { expect(parse('fubah.com')).to eq(parsed) }
24
+ it { expect(parse('fubah.com.')).to eq(parsed) }
25
+ it { expect(parse('(fubah.com.)')).to eq(parsed) }
24
26
  it { expect(parse('@fubah.com')).to eq(parsed) } # 'http://@fubah.com') }
25
27
  it { expect(parse('fu@fubah.com')).to eq(parsed) } # 'http://fu@fubah.com') }
26
28
  it { expect(parse('http://fubah.com')).to eq(parsed) }
@@ -6,7 +6,7 @@ describe Thema do
6
6
  end
7
7
 
8
8
  it 'should accept urls too' do
9
- expect(Thema.new('Hard Rock', ['hr.com']).urls).to include('hr.com')
9
+ expect(Thema.new('Hard Rock', ['hr.com']).urls).to include('http://hr.com')
10
10
  end
11
11
 
12
12
  it 'should convert urls to aranea' do
@@ -26,9 +26,12 @@ Gem::Specification.new do |s|
26
26
  s.add_dependency 'paint'
27
27
  s.add_dependency 'phonelib'
28
28
  # s.add_dependency 'addressie', '~> 0.0.0'
29
- s.add_dependency 'polipus'
30
29
  s.add_dependency 'nokogiri'
30
+ s.add_dependency 'whatlanguage'
31
31
  s.add_dependency 'geopolitical'
32
+ s.add_dependency 'public_suffix'
33
+ s.add_dependency 'rubyretriever'
34
+ s.add_dependency 'charlock_holmes'
32
35
 
33
36
  s.add_development_dependency 'vcr'
34
37
  s.add_development_dependency 'rspec'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ubi
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.5
4
+ version: 0.0.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Marcos Piccinini
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-08-22 00:00:00.000000000 Z
11
+ date: 2015-08-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: thor
@@ -53,7 +53,7 @@ dependencies:
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
55
  - !ruby/object:Gem::Dependency
56
- name: polipus
56
+ name: nokogiri
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - ">="
@@ -67,7 +67,7 @@ dependencies:
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
69
  - !ruby/object:Gem::Dependency
70
- name: nokogiri
70
+ name: whatlanguage
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
73
  - - ">="
@@ -94,6 +94,48 @@ dependencies:
94
94
  - - ">="
95
95
  - !ruby/object:Gem::Version
96
96
  version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: public_suffix
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: rubyretriever
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :runtime
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: charlock_holmes
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :runtime
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
97
139
  - !ruby/object:Gem::Dependency
98
140
  name: vcr
99
141
  requirement: !ruby/object:Gem::Requirement
@@ -171,6 +213,7 @@ files:
171
213
  - lib/ubi/memorias/address.rb
172
214
  - lib/ubi/memorias/document.rb
173
215
  - lib/ubi/memorias/email.rb
216
+ - lib/ubi/memorias/image.rb
174
217
  - lib/ubi/memorias/phone.rb
175
218
  - lib/ubi/memorias/site.rb
176
219
  - lib/ubi/memorias/social.rb
@@ -212,7 +255,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
212
255
  version: '0'
213
256
  requirements: []
214
257
  rubyforge_project:
215
- rubygems_version: 2.4.5
258
+ rubygems_version: 2.4.5.1
216
259
  signing_key:
217
260
  specification_version: 4
218
261
  summary: Find devices connected in LAN