gobbler 0.0.1 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +30 -12
- data/gobbler.gemspec +1 -1
- data/lib/gobbler.rb +111 -2
- data/lib/gobbler/base.rb +29 -0
- data/lib/gobbler/checkpoint.rb +31 -0
- data/lib/gobbler/client_version.rb +9 -0
- data/lib/gobbler/dashboard.rb +14 -0
- data/lib/gobbler/folder.rb +35 -0
- data/lib/gobbler/machine.rb +22 -0
- data/lib/gobbler/mappable.rb +29 -0
- data/lib/gobbler/project.rb +42 -0
- data/lib/gobbler/quota.rb +28 -0
- data/lib/gobbler/referral.rb +14 -0
- data/lib/gobbler/version.rb +1 -1
- data/lib/gobbler/volume.rb +29 -0
- metadata +14 -3
data/README.md
CHANGED
@@ -1,9 +1,6 @@
|
|
1
1
|
# Gobbler
|
2
2
|
|
3
|
-
Access to Gobbler API
|
4
|
-
|
5
|
-
_PLEASE NOTE_: This should only be used for testing for now. It's only
|
6
|
-
an experiement and could rapidly change and break as we work on it.
|
3
|
+
Access to Gobbler API via Ruby
|
7
4
|
|
8
5
|
## Installation
|
9
6
|
|
@@ -19,14 +16,35 @@ Or install it yourself as:
|
|
19
16
|
|
20
17
|
$ gem install gobbler
|
21
18
|
|
22
|
-
##
|
19
|
+
## Documentation
|
20
|
+
|
21
|
+
Documentation is available at [rdoc.info](http://rdoc.info/gems/gobbler/frames)
|
22
|
+
|
23
|
+
## Exmaple Usage
|
24
|
+
|
25
|
+
require 'gobbler'
|
26
|
+
|
27
|
+
## Set up authentication and sign in
|
28
|
+
Gobbler.config(email: "...", password: "...")
|
29
|
+
|
30
|
+
## Get the high-level metrics for your account
|
31
|
+
puts Gobbler::Dashboard.list
|
32
|
+
|
33
|
+
## Get a list of all project names
|
34
|
+
puts Gobbler.projects.collect(&:name)
|
35
|
+
|
36
|
+
## Get a list of all files in a project
|
37
|
+
project = Gobbler.projects.first
|
38
|
+
checkpoint = project.last_checkpoint
|
23
39
|
|
24
|
-
|
40
|
+
checkpoint.assets.each do |asset|
|
41
|
+
puts asset["relative_path"]
|
42
|
+
end
|
25
43
|
|
26
|
-
##
|
44
|
+
## Get a list of all machines that you have signed into gobbler with
|
45
|
+
puts Gobbler.machines
|
27
46
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
5. Create new Pull Request
|
47
|
+
## Get a list of the cities that each of your drives was last seen in
|
48
|
+
Gobbler.volumes.each do |volume|
|
49
|
+
puts "#{volume.volume_name} : #{volume.city}"
|
50
|
+
end
|
data/gobbler.gemspec
CHANGED
@@ -10,7 +10,7 @@ Gem::Specification.new do |gem|
|
|
10
10
|
gem.email = ["dan@gobbler.com"]
|
11
11
|
gem.description = %q{Access to the Gobbler API}
|
12
12
|
gem.summary = %q{Access to the Gobbler API}
|
13
|
-
gem.homepage = ""
|
13
|
+
gem.homepage = "https://github.com/gobbler/gobbler"
|
14
14
|
|
15
15
|
gem.files = `git ls-files`.split($/)
|
16
16
|
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
data/lib/gobbler.rb
CHANGED
@@ -1,5 +1,114 @@
|
|
1
|
-
require
|
1
|
+
require 'json'
|
2
|
+
require 'net/http'
|
3
|
+
require 'uri'
|
4
|
+
require 'base64'
|
5
|
+
|
2
6
|
|
3
7
|
module Gobbler
|
4
|
-
|
8
|
+
|
9
|
+
require 'gobbler/base'
|
10
|
+
require 'gobbler/mappable'
|
11
|
+
|
12
|
+
require 'gobbler/checkpoint'
|
13
|
+
require 'gobbler/client_version'
|
14
|
+
require 'gobbler/dashboard'
|
15
|
+
require 'gobbler/folder'
|
16
|
+
require 'gobbler/machine'
|
17
|
+
require 'gobbler/volume'
|
18
|
+
require 'gobbler/project'
|
19
|
+
require 'gobbler/quota'
|
20
|
+
require 'gobbler/referral'
|
21
|
+
|
22
|
+
class << self
|
23
|
+
|
24
|
+
@@api_server = "api.gobbler.com"
|
25
|
+
@@client_version = "dev"
|
26
|
+
@@machine_serial = "api"
|
27
|
+
@@config = {}
|
28
|
+
@@keys = {}
|
29
|
+
|
30
|
+
# Set the configuration
|
31
|
+
#
|
32
|
+
# Options are passed as a Hash of symbols
|
33
|
+
# @option opts [String] :email Email of Gobbler account
|
34
|
+
# @option opts [String] :password Password of Gobbler account
|
35
|
+
def config(opts)
|
36
|
+
opts.each {|k,v| opts[k.to_sym] ||= opts[k]}
|
37
|
+
@@config = opts
|
38
|
+
@@api_server = opts[:api_server] if opts[:api_server]
|
39
|
+
@@client_version = opts[:client_version] if opts[:client_version]
|
40
|
+
@@machine_serial = opts[:machine_serial] if opts[:machine_serial]
|
41
|
+
login! if opts[:email] && opts[:password]
|
42
|
+
end
|
43
|
+
|
44
|
+
# @return [Boolean] Login successful, will raise an error if it was not
|
45
|
+
def login!
|
46
|
+
raise "No credentials" if @@config[:email].nil? || @@config[:password].nil?
|
47
|
+
|
48
|
+
authentication = {
|
49
|
+
machine_info: { serial: @@machine_serial },
|
50
|
+
authentication: {
|
51
|
+
provider: "gobbler",
|
52
|
+
credentials: {
|
53
|
+
email: @@config[:email],
|
54
|
+
password: @@config[:password]
|
55
|
+
}
|
56
|
+
}
|
57
|
+
}
|
58
|
+
|
59
|
+
response = request("client_user/login", authentication)
|
60
|
+
@@keys[:cookie] = response[:http_response]["Set-Cookie"].split('; ')[0]
|
61
|
+
@@keys[:client_key] = response["client_key"]
|
62
|
+
|
63
|
+
raise "Can't Login" if @@keys[:client_key].nil?
|
64
|
+
|
65
|
+
return true
|
66
|
+
end
|
67
|
+
|
68
|
+
# @return [Hash] Hash from the JSON API server response
|
69
|
+
def request(uri, body = nil)
|
70
|
+
uri = URI.parse("https://#{api_server}/#{uri}")
|
71
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
72
|
+
http.use_ssl = true
|
73
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
74
|
+
|
75
|
+
if body
|
76
|
+
request = Net::HTTP::Post.new(uri.request_uri)
|
77
|
+
request.body = body.to_json unless body.nil?
|
78
|
+
else
|
79
|
+
request = Net::HTTP::Get.new(uri.request_uri)
|
80
|
+
end
|
81
|
+
|
82
|
+
request["Content-type"] = "application/json"
|
83
|
+
request["Cookie"] = cookie
|
84
|
+
request["x-mam-client-version"] = client_version
|
85
|
+
request["x-mam-client-key"] = client_key
|
86
|
+
|
87
|
+
response = http.request(request)
|
88
|
+
raise unless response.code == "200"
|
89
|
+
JSON.parse(response.body).merge(http_response: response)
|
90
|
+
end
|
91
|
+
|
92
|
+
# @return [Hash] The unpacked JSON string
|
93
|
+
def unpack(str)
|
94
|
+
return [] if str.nil? || str == ""
|
95
|
+
decoded = Base64.decode64(str)
|
96
|
+
unzipped = Zlib::GzipReader.new(StringIO.new(decoded)).read
|
97
|
+
JSON.parse(unzipped)
|
98
|
+
end
|
99
|
+
|
100
|
+
# @return [Boolean] If you are currently signed into the Gobbler API
|
101
|
+
def signed_in?
|
102
|
+
!client_key.nil? && client_key != ""
|
103
|
+
end
|
104
|
+
|
105
|
+
private
|
106
|
+
|
107
|
+
def api_server; @@api_server; end
|
108
|
+
def client_key; @@keys[:client_key]; end
|
109
|
+
def client_version; @@client_version; end
|
110
|
+
def cookie; @@keys[:cookie]; end
|
111
|
+
def machine_serial; @@machine_serial; end
|
112
|
+
end
|
113
|
+
|
5
114
|
end
|
data/lib/gobbler/base.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
module Gobbler
|
2
|
+
class Base
|
3
|
+
attr_accessor :json
|
4
|
+
|
5
|
+
def self.get(guid)
|
6
|
+
list.find {|p| p.guid == guid}
|
7
|
+
end
|
8
|
+
|
9
|
+
def initialize(json)
|
10
|
+
@json = json
|
11
|
+
end
|
12
|
+
|
13
|
+
def base_attr; json; end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def method_missing(method, *args, &block)
|
18
|
+
if base_attr.keys.include?(method.to_s) || method == :assets
|
19
|
+
if method == :assets && base_attr.keys.include?("assets_packed")
|
20
|
+
::Gobbler.unpack(base_attr["assets_packed"])
|
21
|
+
else
|
22
|
+
base_attr[method.to_s]
|
23
|
+
end
|
24
|
+
else
|
25
|
+
super(method, *args, &block)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Gobbler
|
2
|
+
class Checkpoint < Base
|
3
|
+
|
4
|
+
# Gets the checkpoint for a project
|
5
|
+
#
|
6
|
+
# @option opts [String] :project_id The id of the project to get
|
7
|
+
# @option opts [Integer] :checkpoint The number of the checkpoint
|
8
|
+
# @return [Checkpoint] the checkpoint
|
9
|
+
def self.get(opts)
|
10
|
+
raise unless opts[:project_id] && opts[:checkpoint]
|
11
|
+
new(::Gobbler.request("v1/projects/#{opts[:project_id]}/checkpoints/#{opts[:checkpoint]}"))
|
12
|
+
end
|
13
|
+
|
14
|
+
# @return [Project] The {Project} that this is a checkpoint for
|
15
|
+
def project
|
16
|
+
::Gobbler::Project.get(json["project"])
|
17
|
+
end
|
18
|
+
|
19
|
+
# Email this version of the project to a list of recipieints
|
20
|
+
# @param recipieints [String] A comma-separated list of email addresses
|
21
|
+
# @return [Hash] The sevrer response
|
22
|
+
def email_to(recipients, opts = {})
|
23
|
+
opts[:checkpoint] = num
|
24
|
+
project.email_to(recipients, opts)
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def base_attr; json["checkpoint"]; end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Gobbler
|
2
|
+
|
3
|
+
# Alias for {Gobbler::Dashboard.get}
|
4
|
+
# @return [Dashboard] Metrics for your account
|
5
|
+
def self.dashboard; Dashboard.get; end
|
6
|
+
|
7
|
+
class Dashboard < Base
|
8
|
+
|
9
|
+
# @return [Dashboard] Metrics for your account
|
10
|
+
def self.get
|
11
|
+
new(::Gobbler.request "account/dashboard.json")
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Gobbler
|
2
|
+
|
3
|
+
# Alias for {Folder.get}
|
4
|
+
# @param guid [String] The guid of the folder
|
5
|
+
# @return [Folder]
|
6
|
+
def self.folder(guid); Folder.get(guid); end
|
7
|
+
|
8
|
+
# Alias for {Folder.list}
|
9
|
+
# @return [Array<Folder>] An array of Folders
|
10
|
+
def self.folders(opts = {}); Folder.list(opts); end
|
11
|
+
|
12
|
+
class Folder < Base
|
13
|
+
|
14
|
+
# @return [Array<Folder>] An array of Folders
|
15
|
+
def self.list(opts = {})
|
16
|
+
opts[:offset] ||= 0
|
17
|
+
::Gobbler.request("client_catalog/sync_ask_folder", options: opts)["updates"].map {|folder| new(folder)}
|
18
|
+
end
|
19
|
+
|
20
|
+
# @return [String] The guid for the folder
|
21
|
+
def guid
|
22
|
+
user_data_guid
|
23
|
+
end
|
24
|
+
|
25
|
+
# @return [Volume] The volume that this folder is on
|
26
|
+
def volume
|
27
|
+
::Gobbler::Volume.get(volume_guid)
|
28
|
+
end
|
29
|
+
|
30
|
+
# @return [Hash] The assets for this folder
|
31
|
+
def assets
|
32
|
+
::Gobbler.unpack json["dir"]["assets_packed"]
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Gobbler
|
2
|
+
|
3
|
+
# Alias for {Gobbler::Machine.get}
|
4
|
+
# @param guid [String] The guid of the machine
|
5
|
+
# @return [Machine]
|
6
|
+
def self.machine(guid); Machine.get(guid); end
|
7
|
+
|
8
|
+
# Alias for {Gobbler::Machine.list}
|
9
|
+
# @return [Array<Machine>] An array of Folders
|
10
|
+
def self.machines(opts = {}); Machine.list(opts); end
|
11
|
+
|
12
|
+
class Machine < Base
|
13
|
+
include Mappable
|
14
|
+
|
15
|
+
# @return [Array<Machine>] Machines that have been connected to your account
|
16
|
+
def self.list(opts = {})
|
17
|
+
opts[:offset] ||= 0
|
18
|
+
::Gobbler.request("client_machine/sync_ask", options: opts)["updates"].map {|machine| new(machine)}
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Gobbler
|
2
|
+
module Mappable
|
3
|
+
def self.included(base)
|
4
|
+
base.extend(Gobbler::Mappable::ClassMethods)
|
5
|
+
end
|
6
|
+
|
7
|
+
def city; last_location["city"] unless last_location.nil?; end
|
8
|
+
def lat; last_location["lat"] unless last_location.nil?; end
|
9
|
+
def lng; last_location["lng"] unless last_location.nil?; end
|
10
|
+
def coordinates; [lat, lng]; end
|
11
|
+
def zip; last_location["zip"] unless last_location.nil?; end
|
12
|
+
|
13
|
+
module ClassMethods
|
14
|
+
def valid_locations; list.collect(&:coordinates).reject {|c| c == [nil,nil] || c == [0.0,0.0]}; end
|
15
|
+
|
16
|
+
def google_maps_url(opts = {})
|
17
|
+
opts[:size] ||= "1500x1200"
|
18
|
+
opts[:sensor] ||= "true"
|
19
|
+
url = "http://maps.googleapis.com/maps/api/staticmap?size=#{opts[:size]}"
|
20
|
+
url += "&" + valid_locations.map {|c| "markers=color:green%7Clabel:X%7C#{c[0]},#{c[1]}"}.join("&")
|
21
|
+
url += "&sensor=#{opts[:sensor]}"
|
22
|
+
end
|
23
|
+
|
24
|
+
def open_map!(opts = {})
|
25
|
+
system "open '#{google_maps_url(opts)}'"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module Gobbler
|
2
|
+
|
3
|
+
# Alias for {Gobbler::Project.get}
|
4
|
+
# @param guid [String] The guid of the project
|
5
|
+
# @return [Project]
|
6
|
+
def self.project(guid); Project.get(guid); end
|
7
|
+
|
8
|
+
# Alias for {Gobbler::Project.list}
|
9
|
+
# @return [Array<Project>] An array of Backed up projects
|
10
|
+
def self.projects(opts = {}); Project.list(opts); end
|
11
|
+
|
12
|
+
# Projects that you have backed up with Gobbler
|
13
|
+
class Project < Base
|
14
|
+
|
15
|
+
# @return [Array<Project>] an array of Gobbler Projects
|
16
|
+
def self.list(opts = {})
|
17
|
+
opts[:offset] ||= 0
|
18
|
+
::Gobbler.request("client_project/sync_ask", options: opts)["updates"].map {|project| new(project)}
|
19
|
+
end
|
20
|
+
|
21
|
+
# Get the last checkpoint for a project
|
22
|
+
# @return [Checkpoint]
|
23
|
+
def last_checkpoint
|
24
|
+
::Gobbler::Checkpoint.get(project_id: guid, checkpoint: current_checkpoint["num"])
|
25
|
+
end
|
26
|
+
|
27
|
+
# @return [Array<Checkpoint>] an array of Checkpoints for this project
|
28
|
+
def checkpoints
|
29
|
+
(1..current_checkpoint["num"]).map do |checkpoint_num|
|
30
|
+
::Gobbler::Checkpoint.get(project_id: guid, checkpoint: checkpoint_num)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# @return [Hash] The information about the email sent
|
35
|
+
def email_to(recipients, opts = {})
|
36
|
+
params = {guid: guid, recipients: recipients}
|
37
|
+
params[:is_public] = opts[:public] if opts[:public] == true
|
38
|
+
params[:checkpoint] = opts[:checkpoint] if opts[:checkpoint]
|
39
|
+
::Gobbler.request("client_mailbox/send_project", params)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Gobbler
|
2
|
+
|
3
|
+
# Alias for {Quota.get}
|
4
|
+
def self.quota; Quota.get; end
|
5
|
+
|
6
|
+
class Quota < Base
|
7
|
+
|
8
|
+
# @return [Quota] The transfer and storage quota for your account
|
9
|
+
def self.get
|
10
|
+
new(::Gobbler.request("v1/quotas"))
|
11
|
+
end
|
12
|
+
|
13
|
+
# @return [Integer] The total bytes you can sending (note -1 represents unlimted)
|
14
|
+
def transfer
|
15
|
+
quotas["limits"]["transfer"]
|
16
|
+
end
|
17
|
+
|
18
|
+
# @return [Boolean] If your account has unlimited sending
|
19
|
+
def unlimited_transfer?
|
20
|
+
transfer == -1
|
21
|
+
end
|
22
|
+
|
23
|
+
# @return [Integer] The total bytes you can backup (note -1 represents unlimted)
|
24
|
+
def storage
|
25
|
+
quotas["limits"]["storage"]
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Gobbler
|
2
|
+
|
3
|
+
# Alias for {Referral.list}
|
4
|
+
# @return [Array<Referral>] All referrals
|
5
|
+
def self.referrals; Referral.list; end
|
6
|
+
|
7
|
+
class Referral < Base
|
8
|
+
|
9
|
+
# @return [Array<Referrals>] All referrals
|
10
|
+
def self.list
|
11
|
+
::Gobbler.request("account/referrals.json")["referrals"].map {|ref| new(ref)}
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
data/lib/gobbler/version.rb
CHANGED
@@ -0,0 +1,29 @@
|
|
1
|
+
module Gobbler
|
2
|
+
|
3
|
+
# Alias for {Volume.get}
|
4
|
+
# @param guid [String] The guid of the volume
|
5
|
+
# @return [Volume]
|
6
|
+
def self.volume(guid); Volume.get(guid); end
|
7
|
+
|
8
|
+
# Alias for {Volume.list}
|
9
|
+
# @return [Array<Volume>] An array of Volumes
|
10
|
+
def self.volumes(opts = {}); Volume.list(opts); end
|
11
|
+
|
12
|
+
class Volume < Base
|
13
|
+
include Mappable
|
14
|
+
|
15
|
+
# @option opts [Integer] :limit The number of records to return
|
16
|
+
# @option opts [Integer] :offset The number of records to offset the
|
17
|
+
# results (useful for paging)
|
18
|
+
# @return [Array<Volume>] an array of volumes
|
19
|
+
def self.list(opts = {})
|
20
|
+
opts[:offset] ||= 0
|
21
|
+
::Gobbler.request("client_volume/sync_ask", options: opts)["updates"].map {|volume| new(volume)}
|
22
|
+
end
|
23
|
+
|
24
|
+
# @return [Boolean] If the volume is currently connected to a machine
|
25
|
+
def connected?
|
26
|
+
currently_connected
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gobbler
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.1.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-08-
|
12
|
+
date: 2013-08-08 00:00:00.000000000 Z
|
13
13
|
dependencies: []
|
14
14
|
description: Access to the Gobbler API
|
15
15
|
email:
|
@@ -25,8 +25,19 @@ files:
|
|
25
25
|
- Rakefile
|
26
26
|
- gobbler.gemspec
|
27
27
|
- lib/gobbler.rb
|
28
|
+
- lib/gobbler/base.rb
|
29
|
+
- lib/gobbler/checkpoint.rb
|
30
|
+
- lib/gobbler/client_version.rb
|
31
|
+
- lib/gobbler/dashboard.rb
|
32
|
+
- lib/gobbler/folder.rb
|
33
|
+
- lib/gobbler/machine.rb
|
34
|
+
- lib/gobbler/mappable.rb
|
35
|
+
- lib/gobbler/project.rb
|
36
|
+
- lib/gobbler/quota.rb
|
37
|
+
- lib/gobbler/referral.rb
|
28
38
|
- lib/gobbler/version.rb
|
29
|
-
|
39
|
+
- lib/gobbler/volume.rb
|
40
|
+
homepage: https://github.com/gobbler/gobbler
|
30
41
|
licenses: []
|
31
42
|
post_install_message:
|
32
43
|
rdoc_options: []
|