gobbler 0.0.1 → 0.1.1
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/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: []
|