proximity_beacon 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 5066f0faf936b19814abed0927489672d61af198
4
+ data.tar.gz: f4e5e38ecde92667696149362c5c64138f991e00
5
+ SHA512:
6
+ metadata.gz: e4106203c588fc1b14d9c95031d11e91b8157a55629ff141152c8d73d654b35597baf1ffa91252729cd2129c27160ace14e61c70a69cef7dafd44f955d183f0a
7
+ data.tar.gz: f369a910cc31cd7892597302e754a02adebd728763a136cc01f7c3633e779b27d4f7035d5033714b05d5f628b247217cec7c72c9d99a88fa229556c25ccc20d9
data/.gitignore ADDED
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/.travis.yml ADDED
@@ -0,0 +1,4 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.2.0
4
+ before_install: gem install bundler -v 1.10.6
@@ -0,0 +1,13 @@
1
+ # Contributor Code of Conduct
2
+
3
+ As contributors and maintainers of this project, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities.
4
+
5
+ We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, or religion.
6
+
7
+ Examples of unacceptable behavior by participants include the use of sexual language or imagery, derogatory comments or personal attacks, trolling, public or private harassment, insults, or other unprofessional conduct.
8
+
9
+ Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct. Project maintainers who do not follow the Code of Conduct may be removed from the project team.
10
+
11
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by opening an issue or contacting one or more of the project maintainers.
12
+
13
+ This Code of Conduct is adapted from the [Contributor Covenant](http://contributor-covenant.org), version 1.0.0, available at [http://contributor-covenant.org/version/1/0/0/](http://contributor-covenant.org/version/1/0/0/)
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in proximity_beacon.gemspec
4
+ gemspec
data/README.md ADDED
@@ -0,0 +1,42 @@
1
+ # ProximityBeacon
2
+
3
+ This gem allows access to Google's Proximity Beacon API. You can register beacons,
4
+ list your beacons, add attachments, etc.
5
+
6
+ ## Installation
7
+
8
+ Add this line to your application's Gemfile:
9
+
10
+ ```ruby
11
+ gem 'proximity_beacon'
12
+ ```
13
+
14
+ And then execute:
15
+
16
+ $ bundle
17
+
18
+ Or install it yourself as:
19
+
20
+ $ gem install proximity_beacon
21
+
22
+ ## Usage
23
+
24
+ ```ruby
25
+ # get beacons list, using CLI oauth flow
26
+ client = ProximityBeacon::Client.new
27
+ beacons = client.beacons.list
28
+
29
+ # get attachments
30
+ attachments = client.attachements.list(beacons.first.name)
31
+ ```
32
+
33
+ ## Development
34
+
35
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
36
+
37
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
38
+
39
+ ## Contributing
40
+
41
+ Bug reports and pull requests are welcome on GitHub at https://github.com/RadiusNetworks/proximity_beacon_gem. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](contributor-covenant.org) code of conduct.
42
+
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "proximity_beacon"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start
data/bin/setup ADDED
@@ -0,0 +1,7 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+
5
+ bundle install
6
+
7
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,82 @@
1
+ module ProximityBeacon
2
+ class AdvertisedId < GoogleResource
3
+ camelcase_attr_accessor :type, :id
4
+
5
+ def bytes
6
+ @bytes ||= Base64.decode64(id)
7
+ end
8
+
9
+ def ids
10
+ case type
11
+ when "EDDYSTONE"
12
+ [id_field(0..9), id_field(10..15)]
13
+ when "IBEACON"
14
+ [id_field(0..15), id_field(16..17), id_field(18..19)]
15
+ when "ALTBEACON"
16
+ [id_field(0..15), id_field(16..17), id_field(18..19)]
17
+ end
18
+ end
19
+
20
+ def ibeacon_ids=(value)
21
+ self.type = "IBEACON"
22
+ uuid = value[0]
23
+ major = value[1].to_i
24
+ minor = value[2].to_i
25
+ bytes = [uuid.gsub("-", "")].pack("H*") + [major].pack("S>") + [minor].pack("S>")
26
+ self.id = Base64.strict_encode64(bytes)
27
+ end
28
+
29
+ def altbeacon_ids=(value)
30
+ self.type = "ALTBEACON"
31
+ uuid = value[0]
32
+ major = value[1].to_i
33
+ minor = value[2].to_i
34
+ bytes = [uuid.gsub("-", "")].pack("H*") + [major].pack("S>") + [minor].pack("S>")
35
+ self.id = Base64.strict_encode64(bytes)
36
+ end
37
+
38
+ def eddystone_ids=(value)
39
+ self.type = "EDDYSTONE"
40
+ namespace = value[0]
41
+ instance = value[1]
42
+ bytes = [namespace + instance].pack("H*")
43
+ self.id = Base64.strict_encode64(bytes)
44
+ end
45
+
46
+ def beacon_type_code
47
+ case type
48
+ when "EDDYSTONE"
49
+ 3
50
+ when "IBEACON"
51
+ 1
52
+ when "ALTBEACON"
53
+ 5
54
+ end
55
+ end
56
+
57
+ def to_beacon_name
58
+ "beacons/#{beacon_type_code}!#{bytes.unpack("H*")[0]}"
59
+ end
60
+
61
+ def inspect
62
+ "#<AdvertisedId type=#{type} ids=#{ids}>"
63
+ end
64
+
65
+ private
66
+
67
+ def id_field(range)
68
+ case
69
+ when range.size >= 6
70
+ bytes[range].unpack("H*")[0].upcase
71
+ when range.size == 2
72
+ bytes[range].unpack("S>")[0]
73
+ when range.size == 4
74
+ bytes[range].unpack("L>")[0]
75
+ when range.size == 1
76
+ bytes[range].unpack("C")[0]
77
+ else
78
+ bytes[range].unpack("H*")[0].upcase
79
+ end
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,46 @@
1
+ module ProximityBeacon
2
+ class Attachment < GoogleResource
3
+ camelcase_attr_accessor :attachment_name, :namespaced_type, :data
4
+
5
+ # convenience accessors
6
+ alias_method :name, :attachment_name
7
+ alias_method :name=, :attachment_name=
8
+
9
+ def initialize(*args)
10
+ self.namespaced_type = ""
11
+ super
12
+ end
13
+
14
+ def namespace
15
+ namespaced_type.split("/")[0]
16
+ end
17
+
18
+ def namespace=(value)
19
+ self.namespaced_type = [value, (type || "")].join("/")
20
+ end
21
+
22
+ def type
23
+ namespaced_type.split("/")[1]
24
+ end
25
+
26
+ def type=(value)
27
+ self.namespaced_type = [(namespace || ""), value].join("/")
28
+ end
29
+
30
+ def decoded_data
31
+ Base64.decode64(data)
32
+ end
33
+
34
+ def decoded_data=(value)
35
+ self.data = Base64.strict_encode64(value)
36
+ end
37
+
38
+ def id
39
+ name.split("/").last
40
+ end
41
+
42
+ def inspect
43
+ "#<Attachment name=\"#{name}\" namespaced_type=\"#{namespace}/#{type}\">"
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,35 @@
1
+ module ProximityBeacon
2
+ class Beacon < GoogleResource
3
+ camelcase_attr_accessor :beacon_name, :advertised_id, :status, :description, :place_id, :lat_lng,
4
+ :indoor_level, :expected_stability, :properties, :provisioning_key,
5
+ :ephemeral_id_registration
6
+
7
+ # convenience accessors
8
+ alias_method :name, :beacon_name
9
+ alias_method :name=, :beacon_name=
10
+
11
+ def advertised_id=(value)
12
+ if value.is_a? Hash
13
+ @advertised_id = AdvertisedId.new(value)
14
+ else
15
+ @advertised_id = value
16
+ end
17
+ end
18
+
19
+ def id
20
+ name.split("/")[1]
21
+ end
22
+
23
+ def namespace
24
+ advertised_id.ids[0]
25
+ end
26
+
27
+ def instance
28
+ advertised_id.ids[1]
29
+ end
30
+
31
+ def inspect
32
+ "#<Beacon name=\"#{name}\" description=\"#{description}\" advertised_id=#{advertised_id.inspect}>"
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,41 @@
1
+ module ProximityBeacon
2
+ class Client
3
+ class Attachments
4
+
5
+ attr_accessor :credentials
6
+
7
+ def initialize(credentials)
8
+ self.credentials = credentials
9
+ end
10
+
11
+ def list(beacon_name, params = {pageSize: 1000})
12
+ uri = URI(PROXIMITY_BEACON_ROOT + beacon_name + "/attachments")
13
+ response = Request.get(uri, credentials, params)
14
+ json = JSON.parse(response.body)
15
+ attachments_json = json["attachments"] || []
16
+ attachments_json.map {|attachment_json| Attachment.new(attachment_json) }
17
+ end
18
+
19
+ def create(attachment, beacon_name, params = nil)
20
+ uri = URI(PROXIMITY_BEACON_ROOT + beacon_name + "/attachments")
21
+ response = Request.post(uri, credentials, params) { |request|
22
+ request.body = attachment.to_json
23
+ request.add_field "Content-Type", "application/json"
24
+ }
25
+ Attachment.new(JSON.parse(response.body))
26
+ end
27
+
28
+ def delete(attachment_name, params = nil)
29
+ uri = URI(PROXIMITY_BEACON_ROOT + attachment_name)
30
+ response = Request.delete(uri, credentials, params)
31
+ JSON.parse(response.body)
32
+ end
33
+
34
+ def batch_delete(beacon_name, params = nil)
35
+ uri = URI(PROXIMITY_BEACON_ROOT + beacon_name + "/attachments:batchDelete")
36
+ response = Request.post(uri, credentials, params)
37
+ JSON.parse(response.body)
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,47 @@
1
+ module ProximityBeacon
2
+ class Client
3
+ class Beacons
4
+
5
+ BEACONS_URI = URI(PROXIMITY_BEACON_ROOT + "beacons")
6
+
7
+ attr_accessor :credentials
8
+
9
+ def initialize(credentials)
10
+ self.credentials = credentials
11
+ end
12
+
13
+ def list(params = {pageSize: 1000})
14
+ response = Request.get(BEACONS_URI, credentials, params)
15
+ json = JSON.parse(response.body)
16
+ beacons_json = json["beacons"] || []
17
+ beacons_json.map {|beacon_json| Beacon.new(beacon_json) }
18
+ end
19
+
20
+ def get(beacon_name, params = nil)
21
+ uri = URI(Client::PROXIMITY_BEACON_ROOT + beacon_name)
22
+ response = Request.get(uri, credentials, params)
23
+ json = JSON.parse(response.body)
24
+ Beacon.new(json)
25
+ end
26
+
27
+ def register(beacon, params = nil)
28
+ uri = URI(Client::PROXIMITY_BEACON_ROOT + "beacons:register")
29
+ response = Request.post(uri, credentials, params) { |request|
30
+ request.body = beacon.to_json
31
+ request.add_field "Content-Type", "application/json"
32
+ }
33
+ Beacon.new(JSON.parse(response.body))
34
+ end
35
+
36
+ def update(beacon, params = nil)
37
+ uri = URI(Client::PROXIMITY_BEACON_ROOT + beacon.name)
38
+ response = Request.put(uri, credentials, params) { |request|
39
+ request.body = beacon.to_json
40
+ request.add_field "Content-Type", "application/json"
41
+ }
42
+ json = JSON.parse(response.body)
43
+ Beacon.new(json)
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,22 @@
1
+ module ProximityBeacon
2
+ class Client
3
+ class Projects
4
+
5
+ CLOUD_RESOURCE_ROOT = "https://cloudresourcemanager.googleapis.com/v1beta1/"
6
+
7
+ attr_accessor :credentials
8
+
9
+ def initialize(credentials)
10
+ self.credentials = credentials
11
+ end
12
+
13
+ def list(params = nil)
14
+ uri = URI(CLOUD_RESOURCE_ROOT + "projects")
15
+ response = Request.get(uri, credentials, params)
16
+ json = JSON.parse(response.body)
17
+ json["projects"].map {|project_json| Project.new(project_json) }
18
+ end
19
+
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,87 @@
1
+ require 'uri'
2
+ require 'net/http'
3
+ require 'base64'
4
+
5
+ module ProximityBeacon
6
+ class Client
7
+ class Request
8
+ extend Forwardable
9
+
10
+ attr_accessor :method, :uri, :credentials
11
+ def_delegators :request, :add_field, :body=
12
+
13
+ def self.get(uri, credentials = nil, params = nil)
14
+ r = self.new(:get, uri, credentials, params)
15
+ r.perform {|r| yield r if block_given? }
16
+ end
17
+
18
+ def self.post(uri, credentials = nil, params = nil)
19
+ r = self.new(:post, uri, credentials, params)
20
+ r.perform {|r| yield r if block_given? }
21
+ end
22
+
23
+ def self.put(uri, credentials = nil, params = nil)
24
+ r = self.new(:put, uri, credentials, params)
25
+ r.perform {|r| yield r if block_given? }
26
+ end
27
+
28
+ def self.delete(uri, credentials = nil, params = nil)
29
+ r = self.new(:delete, uri, credentials, params)
30
+ r.perform {|r| yield r if block_given? }
31
+ end
32
+
33
+ def initialize(method, uri, credentials = nil, params = nil)
34
+ self.method = method
35
+ if params
36
+ url_params = params.map {|k,v| "#{k}=#{v}"}.join("&")
37
+ self.uri = URI(uri + "?#{url_params}")
38
+ else
39
+ self.uri = uri
40
+ end
41
+ self.credentials = credentials
42
+ yield self if block_given?
43
+ end
44
+
45
+ def perform
46
+ http_opts = {use_ssl: true}
47
+ response = Net::HTTP.start(uri.host, uri.port, http_opts) do |http|
48
+ add_field "Authorization", "Bearer #{credentials.access_token}" if credentials
49
+ add_field "Accept", "application/json"
50
+ yield self if block_given?
51
+ http.request request
52
+ end
53
+ if (200..299).include?(response.code.to_i)
54
+ return response
55
+ else
56
+ raise RequestError.new(response.code.to_i), "Error #{response.code} (#{response.msg}) - #{uri}\n#{response.body}"
57
+ end
58
+ end
59
+
60
+ private
61
+
62
+ def request
63
+ @request ||=
64
+ begin
65
+ case method
66
+ when :get
67
+ Net::HTTP::Get.new uri.request_uri
68
+ when :post
69
+ Net::HTTP::Post.new uri.request_uri
70
+ when :put
71
+ Net::HTTP::Put.new uri.request_uri
72
+ when :delete
73
+ Net::HTTP::Delete.new uri.request_uri
74
+ end
75
+ end
76
+ end
77
+ end
78
+
79
+ class RequestError < StandardError
80
+ attr_accessor :code
81
+ def initialize(code)
82
+ self.code = code
83
+ end
84
+ end
85
+
86
+ end
87
+ end
@@ -0,0 +1,66 @@
1
+ module ProximityBeacon
2
+ class Client
3
+
4
+ PROXIMITY_BEACON_ROOT = "https://proximitybeacon.googleapis.com/v1beta1/"
5
+
6
+ attr_accessor :credentials
7
+
8
+ def initialize(credentials = nil)
9
+ if credentials.nil?
10
+ # if no credentials are provided, we try to load them from file or
11
+ # initiate a CLI based oauth flow
12
+ self.credentials = Credentials.from_file || OAuth.new.get_credentials
13
+ if self.credentials.expired? && self.credentials.refresh_token
14
+ self.credentials = OAuth.new.refresh_credentials(self.credentials)
15
+ end
16
+ self.credentials.save
17
+ else
18
+ self.credentials = credentials
19
+ end
20
+ end
21
+
22
+ def eidparams
23
+ uri = URI(PROXIMITY_BEACON_ROOT + "eidparams")
24
+ response = Request.get(uri, credentials)
25
+ return JSON.parse(response.body)
26
+ end
27
+
28
+ def projects
29
+ Projects.new(credentials)
30
+ end
31
+
32
+ def beacons
33
+ Beacons.new(credentials)
34
+ end
35
+
36
+ def attachments
37
+ Attachments.new(credentials)
38
+ end
39
+
40
+ def getforobserved(eids, api_key = ENV["GOOGLE_API_KEY"])
41
+ uri = URI("#{PROXIMITY_BEACON_ROOT}beaconinfo:getforobserved?key=#{api_key}")
42
+ response = Request.post(uri) {|request|
43
+ observations = Array(eids).map {|eid|
44
+ {advertisedId: {type: "EDDYSTONE_EID", id: base64_eid(eid)}}
45
+ }
46
+ request.body = {
47
+ observations: observations,
48
+ namespacedTypes: "*",
49
+ }.to_json
50
+ request.add_field "Content-Type", "application/json"
51
+ }
52
+ JSON.parse(response.body)
53
+ end
54
+
55
+ private
56
+
57
+ def base64_eid(eid)
58
+ if eid.size == 16
59
+ Base64.strict_encode64([eid].pack("H*"))
60
+ else
61
+ Base64.strict_encode64(eid)
62
+ end
63
+ end
64
+
65
+ end
66
+ end
@@ -0,0 +1,38 @@
1
+ require 'yaml'
2
+
3
+ module ProximityBeacon
4
+ class Credentials
5
+
6
+ DEFAULT_FILE_STORE = File.expand_path("~/.proximity_beacon_credentials.yaml")
7
+ attr_accessor :access_token, :refresh_token, :expires_at
8
+
9
+ def self.from_file(file = DEFAULT_FILE_STORE)
10
+ return nil unless File.exist?(file)
11
+ self.new YAML.load_file(file)
12
+ end
13
+
14
+ def initialize(opts = {})
15
+ # convert string keys to symbols
16
+ opts = opts.inject({}){|memo,(k,v)| memo[k.to_sym] = v; memo}
17
+
18
+ self.access_token = opts[:access_token]
19
+ self.refresh_token = opts[:refresh_token]
20
+ self.expires_at = opts[:expires_at] || (Time.now + opts[:expires_in].to_i)
21
+ end
22
+
23
+ def save(file = DEFAULT_FILE_STORE)
24
+ data = {
25
+ access_token: access_token,
26
+ refresh_token: refresh_token,
27
+ expires_at: expires_at
28
+ }.to_yaml
29
+ File.open(file, 'w') {|f| f.write(data) }
30
+ end
31
+
32
+ def expired?
33
+ self.expires_at < Time.now
34
+ end
35
+
36
+ end
37
+ end
38
+
@@ -0,0 +1,67 @@
1
+ module ProximityBeacon
2
+ class GoogleResource
3
+
4
+ def self.camelcase_attr_accessor(*accessors)
5
+ accessors.each do |accessor|
6
+ attr_accessor accessor
7
+ alias_camelized_accessor(accessor)
8
+ end
9
+ end
10
+
11
+ def initialize(hash = {})
12
+ hash.each do |key, value|
13
+ self.send "#{key}=", value
14
+ end
15
+ end
16
+
17
+ def update(hash)
18
+ hash.each do |key, value|
19
+ self.send "#{key}=", value
20
+ end
21
+ end
22
+
23
+ def as_json
24
+ Hash[
25
+ self.class.json_attrs.map {|attr|
26
+ value = send(attr)
27
+ if value.nil?
28
+ nil
29
+ elsif value.is_a? GoogleResource
30
+ [attr, value.as_json]
31
+ else
32
+ [attr, value]
33
+ end
34
+ }.compact
35
+ ]
36
+ end
37
+
38
+ def to_json
39
+ as_json.to_json
40
+ end
41
+
42
+ private
43
+
44
+ class << self
45
+ attr_accessor :json_attrs
46
+ end
47
+
48
+
49
+ def self.alias_camelized_accessor(accessor)
50
+ self.json_attrs ||= []
51
+ camelized_accessor = camelize(accessor)
52
+ if camelized_accessor
53
+ define_method(camelized_accessor) { send(accessor) }
54
+ define_method("#{camelized_accessor}=") {|value| send("#{accessor}=", value) }
55
+ json_attrs << camelized_accessor
56
+ else
57
+ json_attrs << accessor.to_s
58
+ end
59
+ end
60
+
61
+ def self.camelize(string)
62
+ words = string.to_s.split("_")
63
+ return nil if words.count == 1
64
+ words[0] + words[1..-1].map(&:capitalize).join
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,84 @@
1
+ require 'json'
2
+ require 'uri'
3
+ require 'net/http'
4
+
5
+ module ProximityBeacon
6
+ class OAuth
7
+
8
+ SCOPES = [
9
+ "https://www.googleapis.com/auth/userlocation.beacon.registry",
10
+ "https://www.googleapis.com/auth/cloud-platform",
11
+ ]
12
+
13
+ REDIRECT_URI = "urn:ietf:wg:oauth:2.0:oob"
14
+ TOKEN_URI = URI("https://www.googleapis.com/oauth2/v4/token")
15
+
16
+ attr_accessor :client_id, :secret, :redirect_uri
17
+
18
+ def initialize(redirect_uri = REDIRECT_URI, client_id = ENV["GOOGLE_CLIENT_ID"], secret = ENV["GOOGLE_CLIENT_SECRET"])
19
+ if client_id.nil? || secret.nil?
20
+ raise ArgumentError, "No Google Client ID or Secret was set. These can set in the environment variables \"GOOGLE_CLIENT_ID\" and \"GOOGLE_CLIENT_SECRET\" respectively. Credentials must be created for your project at \"https://console.developers.google.com/apis/credentials\"."
21
+ end
22
+ self.client_id = client_id
23
+ self.secret = secret
24
+ self.redirect_uri = redirect_uri
25
+ end
26
+
27
+ def get_code
28
+ puts("Performing OAuth with Google...")
29
+ if RUBY_PLATFORM =~ /darwin/
30
+ system("open \"#{url}\"")
31
+ else
32
+ puts("Open this URL in your browser: \"#{url}\"\n\n")
33
+ end
34
+ printf "Copy and paste code from web browser here: "
35
+ code = STDIN.gets.chomp
36
+ end
37
+
38
+ def get_credentials(code = nil)
39
+ response = Client::Request.post(TOKEN_URI) {|request|
40
+ request.body = hash_to_params(
41
+ code: code || get_code,
42
+ client_id: client_id,
43
+ client_secret: secret,
44
+ redirect_uri: redirect_uri,
45
+ grant_type: "authorization_code",
46
+ )
47
+ }
48
+ Credentials.new(JSON.parse(response.body))
49
+ end
50
+
51
+ def refresh_credentials(credentials)
52
+ response = Client::Request.post(TOKEN_URI) {|request|
53
+ request.body = hash_to_params(
54
+ refresh_token: credentials.refresh_token,
55
+ client_id: client_id,
56
+ client_secret: secret,
57
+ grant_type: "refresh_token",
58
+ )
59
+ }
60
+ json = JSON.parse(response.body)
61
+ new_credentials = Credentials.new(json)
62
+ new_credentials.refresh_token = credentials.refresh_token
63
+ new_credentials
64
+ end
65
+
66
+ def url
67
+ params = hash_to_params(
68
+ scope: SCOPES.join("%20"),
69
+ redirect_uri: redirect_uri,
70
+ response_type: "code",
71
+ client_id: client_id,
72
+ )
73
+ "https://accounts.google.com/o/oauth2/v2/auth?#{params}"
74
+ end
75
+
76
+ private
77
+
78
+ def hash_to_params(hash)
79
+ hash.map {|k,v| "#{k}=#{v}"}.join("&")
80
+ end
81
+
82
+ end
83
+ end
84
+
@@ -0,0 +1,11 @@
1
+ module ProximityBeacon
2
+ class Project < GoogleResource
3
+ camelcase_attr_accessor :project_id, :project_number, :lifecycle_state, :name, :create_time
4
+
5
+ alias_method :id, :project_id
6
+ alias_method :id=, :project_id=
7
+ alias_method :number, :project_number
8
+ alias_method :number=, :project_number=
9
+
10
+ end
11
+ end
@@ -0,0 +1,3 @@
1
+ module ProximityBeacon
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,21 @@
1
+ require 'json'
2
+ require 'uri'
3
+ require 'net/http'
4
+ require 'base64'
5
+
6
+ require "proximity_beacon/version"
7
+ require "proximity_beacon/client"
8
+ require "proximity_beacon/client/beacons"
9
+ require "proximity_beacon/client/attachments"
10
+ require "proximity_beacon/client/projects"
11
+ require "proximity_beacon/client/request"
12
+ require "proximity_beacon/credentials"
13
+ require "proximity_beacon/oauth"
14
+ require "proximity_beacon/google_resource"
15
+ require "proximity_beacon/project"
16
+ require "proximity_beacon/beacon"
17
+ require "proximity_beacon/advertised_id"
18
+ require "proximity_beacon/attachment"
19
+
20
+ module ProximityBeacon
21
+ end
@@ -0,0 +1,24 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'proximity_beacon/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "proximity_beacon"
8
+ spec.version = ProximityBeacon::VERSION
9
+ spec.authors = ["Radius Networks"]
10
+ spec.email = ["support@radiusnetworks.com"]
11
+
12
+ spec.summary = %q{Allows access to Google's Proximity Beacon API}
13
+ spec.description = %q{This gem allows you to register beacons, add attachments, etc.}
14
+ spec.homepage = "https://github.com/RadiusNetworks/proximity_beacon"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
17
+ spec.bindir = "exe"
18
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.10"
22
+ spec.add_development_dependency "rake", "~> 10.0"
23
+ spec.add_development_dependency "rspec"
24
+ end
metadata ADDED
@@ -0,0 +1,109 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: proximity_beacon
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Radius Networks
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2016-05-18 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.10'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.10'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ description: This gem allows you to register beacons, add attachments, etc.
56
+ email:
57
+ - support@radiusnetworks.com
58
+ executables: []
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - ".gitignore"
63
+ - ".rspec"
64
+ - ".travis.yml"
65
+ - CODE_OF_CONDUCT.md
66
+ - Gemfile
67
+ - README.md
68
+ - Rakefile
69
+ - bin/console
70
+ - bin/setup
71
+ - lib/proximity_beacon.rb
72
+ - lib/proximity_beacon/advertised_id.rb
73
+ - lib/proximity_beacon/attachment.rb
74
+ - lib/proximity_beacon/beacon.rb
75
+ - lib/proximity_beacon/client.rb
76
+ - lib/proximity_beacon/client/attachments.rb
77
+ - lib/proximity_beacon/client/beacons.rb
78
+ - lib/proximity_beacon/client/projects.rb
79
+ - lib/proximity_beacon/client/request.rb
80
+ - lib/proximity_beacon/credentials.rb
81
+ - lib/proximity_beacon/google_resource.rb
82
+ - lib/proximity_beacon/oauth.rb
83
+ - lib/proximity_beacon/project.rb
84
+ - lib/proximity_beacon/version.rb
85
+ - proximity_beacon.gemspec
86
+ homepage: https://github.com/RadiusNetworks/proximity_beacon
87
+ licenses: []
88
+ metadata: {}
89
+ post_install_message:
90
+ rdoc_options: []
91
+ require_paths:
92
+ - lib
93
+ required_ruby_version: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - ">="
96
+ - !ruby/object:Gem::Version
97
+ version: '0'
98
+ required_rubygems_version: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ version: '0'
103
+ requirements: []
104
+ rubyforge_project:
105
+ rubygems_version: 2.4.6
106
+ signing_key:
107
+ specification_version: 4
108
+ summary: Allows access to Google's Proximity Beacon API
109
+ test_files: []