zephyrus 0.1.0

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: d767155594140e1d9015b8719daef8a282b9b923
4
+ data.tar.gz: 65da044b30406b4867358ea7ec5ce9cd8aa4e196
5
+ SHA512:
6
+ metadata.gz: b2ab7e5dee75cb06be4ab5e2068ea6c840c0f97d7f6645c4621c9894de45cc6f7116b2e7506e1804ba746818b9663e0dc48a589792debf099cd38975ece296a8
7
+ data.tar.gz: 72c9705d9e91e571f18c8198909803ebc514f1be962c9870b24a0d55f9119a5c7ee0454d6bdafbdff3c652b6e1751c9dd33f0270e6e38e80bf8cc9dd19fd5743
@@ -0,0 +1,49 @@
1
+ require 'singleton'
2
+
3
+ module Zephyrus
4
+
5
+ def self.configuration( &block )
6
+ Configuration.instance().instance_eval( &block ) unless block.nil?
7
+ Configuration.instance()
8
+ end
9
+
10
+ class Configuration
11
+
12
+ include Singleton
13
+
14
+ def self.reloadable?
15
+ false
16
+ end
17
+
18
+ def self.define_attribute( attribute_name, options = {} )
19
+
20
+ class_eval(
21
+ "def #{attribute_name}( *arguments ); " +
22
+ "@#{attribute_name} = arguments.first unless arguments.empty?; " +
23
+ "@#{attribute_name} || " +
24
+ ( options[ :default ].nil? ?
25
+ "nil" :
26
+ ( options[ :default ].is_a?( String ) ?
27
+ "'#{options[ :default ]}'" :
28
+ "#{options[ :default ]}" ) ) + ";" +
29
+ "end",
30
+ __FILE__,
31
+ __LINE__
32
+ )
33
+ end
34
+
35
+ # the api uri; DO NOT COMMIT A MODIFIED DEFAULT
36
+ define_attribute :api_uri, default: 'https://zephyrus.boxxspring.com'
37
+ define_attribute :api_credentials
38
+
39
+ def from_hash( configuration )
40
+
41
+ configuration.each_pair do | name, value |
42
+ self.instance_variable_set( "@#{name}", value )
43
+ end
44
+
45
+ end
46
+
47
+ end
48
+
49
+ end
@@ -0,0 +1,147 @@
1
+ module Zephyrus
2
+
3
+ class Operation
4
+
5
+ def initialize( path, parameters = {} )
6
+ @path = path
7
+ @parameters = ( parameters || {} ).deep_dup
8
+ @key = nil
9
+ end
10
+
11
+ def key
12
+ return @key ||= begin
13
+ result = 0
14
+ query = @parameters.to_param
15
+ if ( @path.present? || @query.present? )
16
+ query = query.split( '&' ).sort.join( '&' )
17
+ addressable = Addressable::URI.new
18
+ addressable.path = @path
19
+ addressable.query = query unless query.blank?
20
+ result = FNV.new.fnv1a_32( addressable.to_s )
21
+ end
22
+ result
23
+ end
24
+ end
25
+
26
+ def where( parameters )
27
+ self.spawn( parameters )
28
+ end
29
+
30
+ def destroy
31
+ result = nil
32
+ Zephyrus::Request.new.tap do | request |
33
+ response = request.destroy( @path, @parameters )
34
+ if response.present?
35
+ result = response.resources
36
+ end
37
+ end
38
+ result
39
+ end
40
+
41
+ def order( by, direction = 'desc' )
42
+ self.spawn( sort_by: by, sort_direction: direction )
43
+ end
44
+
45
+ def limit( _limit )
46
+ self.spawn( count: _limit )
47
+ end
48
+
49
+ def offset( _offset )
50
+ self.spawn( offset: _offset )
51
+ end
52
+
53
+ def include( *arguments )
54
+ self.spawn( :include => self.normalize_include( *arguments ) )
55
+ end
56
+
57
+ def query( &block )
58
+ result = nil
59
+ Zephyrus::Request.new.tap do | request |
60
+ request.get( @path, @parameters ).tap do | response |
61
+ result = response.resources
62
+ if block_given?
63
+ case block.arity
64
+ when 0; yield
65
+ when 1; yield result
66
+ when 2; yield result, response
67
+ end
68
+ end
69
+ end
70
+ end
71
+ result
72
+ end
73
+
74
+ def read( &block )
75
+ response = nil
76
+ result = nil
77
+ self.query do | _result, _response |
78
+ result = _result
79
+ response = _response
80
+ end
81
+ if response.success?
82
+ result = result.first if result.present? && result.is_a?( Enumerable )
83
+ if block_given?
84
+ case block.arity
85
+ when 0; yield
86
+ when 1; yield result
87
+ when 2; yield result, response
88
+ end
89
+ end
90
+ end
91
+ result
92
+ end
93
+
94
+ def write( node, objects, &block )
95
+ result = nil
96
+ Zephyrus::Request.new.tap do | request |
97
+ serializer = Zephyrus::Serializer.new( objects )
98
+ response = request.post( @path, @parameters, serializer.serialize( node ) )
99
+ if response.present?
100
+ result = response.resources
101
+ if block_given?
102
+ case block.arity
103
+ when 0; yield
104
+ when 1; yield result
105
+ when 2; yield result, response
106
+ end
107
+ end
108
+ end
109
+ end
110
+ result
111
+ end
112
+
113
+ protected; def spawn( parameters )
114
+ Zephyrus::Operation.new(
115
+ @path,
116
+ @parameters.deep_merge( parameters || {} )
117
+ )
118
+ end
119
+
120
+ protected; def normalize_include( *arguments )
121
+
122
+ includes = {}
123
+ arguments.each do | argument |
124
+ case argument
125
+ when Array
126
+ argument.each do | value |
127
+ includes.deep_merge!( self.normalize_include( value ) )
128
+ end
129
+ when Hash
130
+ argument.each do | key, value |
131
+ if !includes.include?( key ) || includes[ key ] === true
132
+ includes[ key ] = self.normalize_include( value )
133
+ else
134
+ includes[ key ].deep_merge!( self.normalize_include( value ) )
135
+ end
136
+ end
137
+ else
138
+ includes[ argument ] = true
139
+ end
140
+ end
141
+ includes
142
+
143
+ end
144
+
145
+ end
146
+
147
+ end
@@ -0,0 +1,136 @@
1
+ module Zephyrus
2
+
3
+ class Parser
4
+
5
+ def initialize( content = {} )
6
+ @content = content
7
+ yield self if block_given?
8
+ end
9
+
10
+ def name
11
+ @content.include?( '$this' ) ?
12
+ @content[ '$this' ][ 'name' ] :
13
+ nil
14
+ end
15
+
16
+ def type_name
17
+ @content.include?( '$this' ) ?
18
+ @content[ '$this' ][ 'type_name' ] :
19
+ nil
20
+ end
21
+
22
+ def type_name?( name )
23
+ self.type_name == name.to_s
24
+ end
25
+
26
+ def key
27
+ 'id'
28
+ end
29
+
30
+ def keys
31
+ @content.include?( '$this' ) ?
32
+ @content[ '$this' ][ 'ids' ] :
33
+ nil
34
+ end
35
+
36
+ def associations
37
+ @content.include?( '$associations' ) ?
38
+ @content[ '$associations' ] :
39
+ nil
40
+ end
41
+
42
+ def resources
43
+ result = nil
44
+ unless self.name.blank?
45
+ result = self.keys.map do | key |
46
+ self.resource_by( name, key, { 'type_name' => self.type_name } )
47
+ end
48
+ end
49
+ result
50
+ end
51
+
52
+ def resource_by( name, key, options = {} )
53
+
54
+ @resources_index ||= Hash.new { | hash, key | hash[ key ] = {} }
55
+ @resource_index_mutex ||= Hash.new { | hash, key | hash[ key ] = [] }
56
+
57
+ @resources_index[ name ][ key ] ||= begin
58
+
59
+ # lock the resource index for this name/key combination
60
+ # note: this prevents zephyrus objects that are associated with
61
+ # themselves from causing a stack overflow
62
+ return nil if @resource_index_mutex[ name ].include?( key )
63
+ @resource_index_mutex[ name ].push( key )
64
+
65
+ result = nil
66
+ resource_attributes = resource_attribute_index[ name ][ key ]
67
+ if resource_attributes.present?
68
+ type_name = resource_attributes[ 'type_name' ]
69
+ klass = nil
70
+ klass = ( Zephyrus.const_get( type_name.camelize ) rescue nil ) \
71
+ if type_name.present?
72
+ if klass.nil?
73
+ type_name = options[ 'type_name' ]
74
+ klass = ( Zephyrus.const_get( type_name.camelize ) rescue nil ) \
75
+ if type_name.present?
76
+ end
77
+ if klass.present?
78
+ result = klass.new(
79
+ resource_attributes,
80
+ self.resource_associations_by( name, key )
81
+ )
82
+ end
83
+ end
84
+
85
+ # unlock the resource index for this name/key combination
86
+ @resource_index_mutex[ name ].delete( key )
87
+
88
+ result
89
+
90
+ end
91
+
92
+ end
93
+
94
+ def resource_associations_by( name, key )
95
+ result = Hash.new { | hash, key | hash[ key ] = [] }
96
+ associations = self.associations
97
+ if associations && associations.include?( name )
98
+ association = associations[ name ].detect do | association |
99
+ association[ 'id' ] == key
100
+ end
101
+ if association.present?
102
+ association.each do | key, value |
103
+ unless key == 'id'
104
+ type_name = value[ 'type_name' ]
105
+ result[ key ] = ( value[ 'ids' ] || [] ).map do | associated_id |
106
+ self.resource_by(
107
+ key,
108
+ associated_id,
109
+ { 'type_name' => type_name }
110
+ )
111
+ end
112
+ result[ key ].compact!
113
+ end
114
+ end
115
+ end
116
+ end
117
+ result
118
+ end
119
+
120
+ def resource_attribute_index
121
+ @resource_attribute_index ||= begin
122
+ index = Hash.new { | hash, key | hash[ key ] = {} }
123
+ @content.each do | key, resources_attributes |
124
+ unless key[0] == '$'
125
+ resources_attributes.each do | resource_attributes |
126
+ index[ key ][ resource_attributes[ 'id' ] ] = resource_attributes
127
+ end
128
+ end
129
+ end
130
+ index
131
+ end
132
+ end
133
+
134
+ end
135
+
136
+ end
@@ -0,0 +1,96 @@
1
+ require 'net/https'
2
+ require 'addressable/uri'
3
+
4
+ module Zephyrus
5
+
6
+ class Request
7
+
8
+ def initialize( default_parameters = {} )
9
+
10
+ # parse the API uri
11
+ uri = URI.parse( Zephyrus.configuration.api_uri )
12
+
13
+ # construct http request
14
+ @http = Net::HTTP.new( uri.host, uri.port )
15
+
16
+ # use ssl when https is the uri scheme
17
+ @http.use_ssl = ( uri.scheme == 'https' )
18
+ @http.verify_mode = OpenSSL::SSL::VERIFY_NONE
19
+
20
+ # retain the default parameters
21
+ @default_parameters = default_parameters.stringify_keys
22
+
23
+ end
24
+
25
+ def destroy( path, parameters = {} )
26
+
27
+ begin
28
+
29
+ request = Net::HTTP::Delete.new(
30
+ compose_request_path( path, parameters ),
31
+ { 'Content-Type' =>'application/json' }
32
+ )
33
+
34
+ response = Response.new( @http.request( request ) )
35
+
36
+ rescue Timeout::Error
37
+ response = nil
38
+ end
39
+
40
+ response
41
+
42
+ end
43
+
44
+ def get( path, parameters = {} )
45
+
46
+ response = nil
47
+
48
+ begin
49
+ response = Response.new(
50
+ @http.get( compose_request_path( path, parameters ) )
51
+ )
52
+ rescue Timeout::Error
53
+ response = nil
54
+ end
55
+
56
+ response
57
+
58
+ end
59
+
60
+ def post( path, parameters = {}, body = {} )
61
+
62
+ response = nil
63
+
64
+ begin
65
+
66
+ request = Net::HTTP::Post.new(
67
+ compose_request_path( path, parameters ),
68
+ { 'Content-Type' =>'application/json' }
69
+ )
70
+ request.body = body.to_json
71
+
72
+ response = Response.new( @http.request( request ) )
73
+
74
+ rescue Timeout::Error
75
+ response = nil
76
+ end
77
+
78
+ response
79
+
80
+ end
81
+
82
+ protected; def compose_request_path( path, parameters = {} )
83
+
84
+ parameters = @default_parameters.merge( parameters.stringify_keys )
85
+ addressable = Addressable::URI.new
86
+
87
+ addressable.path = path
88
+ addressable.query = parameters.to_param unless parameters.blank?
89
+
90
+ addressable.to_s
91
+
92
+ end
93
+
94
+ end
95
+
96
+ end
@@ -0,0 +1,7 @@
1
+ module Zephyrus
2
+
3
+ class AttributeError < Error
4
+ field :attribute
5
+ end
6
+
7
+ end
@@ -0,0 +1,67 @@
1
+ module Zephyrus
2
+
3
+ class Base
4
+
5
+ class << self
6
+
7
+ def inherited( subclass )
8
+ subclass.fields = {}.merge( self.fields )
9
+ end
10
+
11
+ def field( name, options = {} )
12
+
13
+ self.fields[ name.to_sym ] = options.merge( name: name )
14
+
15
+ class_eval(
16
+ "def #{name}(); " +
17
+ "@#{name}.is_a?( FalseClass ) ? @#{name} : (" +
18
+ "@#{name} || " +
19
+ ( options[ :default ].nil? ?
20
+ "nil" :
21
+ ( options[ :default ].is_a?( String ) ?
22
+ "'#{options[ :default ]}'" :
23
+ "#{options[ :default ]}" ) ) + ");" +
24
+ "end;" +
25
+ " " +
26
+ "attr_writer :#{name};",
27
+ __FILE__,
28
+ __LINE__
29
+ )
30
+
31
+ end
32
+
33
+ def has_one( name, options = {} )
34
+ define_method name do
35
+ associations = self.instance_variable_get( "@_#{name.to_s.pluralize}" )
36
+ associations.present? ? associations.first : options[ :default ]
37
+ end
38
+ end
39
+
40
+ def has_many( name, options = {} )
41
+ define_method name do
42
+ self.instance_variable_get( "@_#{name}" ) || options[ :default ] || []
43
+ end
44
+ end
45
+
46
+ end
47
+
48
+ class_attribute :fields, instance_writer: false
49
+ self.fields = {}
50
+
51
+ field :type_name
52
+ has_many :errors
53
+
54
+ def initialize( attributes = {}, associations = {} )
55
+ self.type_name = self.class.name.gsub( /Zephyrus::/, '' ).underscore
56
+ attributes.each do | key, value |
57
+ send( "#{key}=", value ) if respond_to?( "#{key}=" )
58
+ end
59
+ associations.each do | key, value |
60
+ self.instance_variable_set( "@_#{key}", value )
61
+ end
62
+ yield self if block_given?
63
+ end
64
+
65
+ end
66
+
67
+ end
@@ -0,0 +1,7 @@
1
+ module Zephyrus
2
+
3
+ class Error < Base
4
+ field :message
5
+ end
6
+
7
+ end
@@ -0,0 +1,6 @@
1
+ module Zephyrus
2
+
3
+ class ForbiddenError < Error
4
+ end
5
+
6
+ end
@@ -0,0 +1,13 @@
1
+ module Zephyrus
2
+ class Input < Base
3
+ field :id
4
+ field :created_at
5
+ field :updated_at
6
+ field :state
7
+ field :key
8
+ field :uid
9
+ field :uuid
10
+
11
+ has_many :outputs
12
+ end
13
+ end
@@ -0,0 +1,6 @@
1
+ module Zephyrus
2
+
3
+ class MalformedParameterError < Error
4
+ end
5
+
6
+ end
@@ -0,0 +1,6 @@
1
+ module Zephyrus
2
+
3
+ class MissingParameterError < Error
4
+ end
5
+
6
+ end
@@ -0,0 +1,6 @@
1
+ module Zephyrus
2
+
3
+ class NotFoundError < Error
4
+ end
5
+
6
+ end
@@ -0,0 +1,12 @@
1
+ module Zephyrus
2
+ class Output < Base
3
+ field :id
4
+ field :created_at
5
+ field :updated_at
6
+ field :key
7
+ field :uid
8
+ field :uuid
9
+ field :state
10
+ field :input_id
11
+ end
12
+ end
@@ -0,0 +1,10 @@
1
+
2
+ module Zephyrus
3
+ class RecordingOutput < Output
4
+
5
+ field :recording
6
+ field :instance_id
7
+ field :last_recording_started_at
8
+
9
+ end
10
+ end
@@ -0,0 +1,9 @@
1
+ module Zephyrus
2
+ class RoutingOutput < Output
3
+
4
+ field :url
5
+ field :authentication_username
6
+ field :authentication_password
7
+
8
+ end
9
+ end
@@ -0,0 +1,13 @@
1
+
2
+ module Zephyrus
3
+ class TranscodingOutput < Output
4
+
5
+ field :mime_type
6
+ field :video_bitrate
7
+ field :audio_bitrate
8
+ field :height
9
+ field :width
10
+ field :audio_sample_rate
11
+
12
+ end
13
+ end
@@ -0,0 +1,51 @@
1
+ module Zephyrus
2
+
3
+ class Response
4
+
5
+ attr_reader :code
6
+ attr_reader :body
7
+ attr_reader :resources
8
+
9
+ def initialize( http_response )
10
+
11
+ @success = http_response.is_a?( Net::HTTPOK )
12
+
13
+ @code = http_response.code
14
+ @resources = []
15
+
16
+ @body = decode_response_body( http_response )
17
+
18
+ if ( @body && @body.respond_to?( :keys ) )
19
+ Zephyrus::Parser.new( @body ) do | parser |
20
+ @resources = parser.resources
21
+ @success = !parser.type_name?( :error )
22
+ end
23
+ else
24
+ @success = false
25
+ @resources << Zephyrus::Error.new(
26
+ message: "#{@code}: #{http_response.message}."
27
+ )
28
+ end
29
+ end
30
+
31
+ def success?
32
+ @success
33
+ end
34
+
35
+ def failure?
36
+ not @success
37
+ end
38
+
39
+ protected; def decode_response_body( http_response )
40
+ body = http_response.body
41
+
42
+ if body.present?
43
+ JSON.parse( body ) rescue nil
44
+ else
45
+ nil
46
+ end
47
+ end
48
+
49
+ end
50
+
51
+ end
@@ -0,0 +1,31 @@
1
+ module Zephyrus
2
+
3
+ class Serializer
4
+
5
+ def initialize( payload = [], options = {} )
6
+ @payload = [ payload ].flatten
7
+ @options = options
8
+ end
9
+
10
+ def serialize( node, options = {} )
11
+ result = {}
12
+ result[ node ] = @payload.map do | object |
13
+ node_object = {}
14
+ node_object[ :type_name ] = (
15
+ object.respond_to?( :type_name ) ?
16
+ object.type_name :
17
+ object.class.name.gsub( /Zephyrus::/, '' ).underscore
18
+ )
19
+ if object.respond_to?( :fields )
20
+ object.fields.each do | name, options |
21
+ node_object[ name.to_sym ] = object.send( name )
22
+ end
23
+ end
24
+ node_object
25
+ end
26
+ result
27
+ end
28
+
29
+ end
30
+
31
+ end
@@ -0,0 +1,3 @@
1
+ module Zephyrus
2
+ VERSION = '0.1.0'
3
+ end
data/lib/zephyrus.rb ADDED
@@ -0,0 +1,28 @@
1
+ require 'active_support'
2
+ require 'active_support/all'
3
+ require 'fnv'
4
+
5
+ require 'zephyrus/configuration'
6
+ require 'zephyrus/response'
7
+ require 'zephyrus/request'
8
+ require 'zephyrus/parser'
9
+ require 'zephyrus/serializer'
10
+ require 'zephyrus/operation'
11
+
12
+ require 'zephyrus/resources/base'
13
+
14
+ # Errors
15
+ require 'zephyrus/resources/error'
16
+ require 'zephyrus/resources/forbidden_error'
17
+ require 'zephyrus/resources/attribute_error'
18
+ require 'zephyrus/resources/missing_parameter_error'
19
+ require 'zephyrus/resources/attribute_error'
20
+ require 'zephyrus/resources/malformed_parameter_error'
21
+ require 'zephyrus/resources/not_found_error'
22
+
23
+ # Resources
24
+ require 'zephyrus/resources/input'
25
+ require 'zephyrus/resources/output'
26
+ require 'zephyrus/resources/routing_output'
27
+ require 'zephyrus/resources/transcoding_output'
28
+ require 'zephyrus/resources/recording_output'
metadata ADDED
@@ -0,0 +1,119 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: zephyrus
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Asher Kory
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-05-04 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activesupport
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '4.2'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '4.2'
27
+ - !ruby/object:Gem::Dependency
28
+ name: addressable
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: fnv
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '0.2'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '0.2'
55
+ - !ruby/object:Gem::Dependency
56
+ name: pry
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 0.10.1
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 0.10.1
69
+ description: The zephyrus gem implements a client to the Sportsrocket Zephyrus API
70
+ email: asher@sportsrocket.com
71
+ executables: []
72
+ extensions: []
73
+ extra_rdoc_files: []
74
+ files:
75
+ - lib/zephyrus.rb
76
+ - lib/zephyrus/configuration.rb
77
+ - lib/zephyrus/operation.rb
78
+ - lib/zephyrus/parser.rb
79
+ - lib/zephyrus/request.rb
80
+ - lib/zephyrus/resources/attribute_error.rb
81
+ - lib/zephyrus/resources/base.rb
82
+ - lib/zephyrus/resources/error.rb
83
+ - lib/zephyrus/resources/forbidden_error.rb
84
+ - lib/zephyrus/resources/input.rb
85
+ - lib/zephyrus/resources/malformed_parameter_error.rb
86
+ - lib/zephyrus/resources/missing_parameter_error.rb
87
+ - lib/zephyrus/resources/not_found_error.rb
88
+ - lib/zephyrus/resources/output.rb
89
+ - lib/zephyrus/resources/recording_output.rb
90
+ - lib/zephyrus/resources/routing_output.rb
91
+ - lib/zephyrus/resources/transcoding_output.rb
92
+ - lib/zephyrus/response.rb
93
+ - lib/zephyrus/serializer.rb
94
+ - lib/zephyrus/version.rb
95
+ homepage: http://sportsrocket.com
96
+ licenses:
97
+ - MS-RL
98
+ metadata: {}
99
+ post_install_message:
100
+ rdoc_options: []
101
+ require_paths:
102
+ - lib
103
+ required_ruby_version: !ruby/object:Gem::Requirement
104
+ requirements:
105
+ - - ">="
106
+ - !ruby/object:Gem::Version
107
+ version: '0'
108
+ required_rubygems_version: !ruby/object:Gem::Requirement
109
+ requirements:
110
+ - - ">="
111
+ - !ruby/object:Gem::Version
112
+ version: '0'
113
+ requirements: []
114
+ rubyforge_project:
115
+ rubygems_version: 2.6.8
116
+ signing_key:
117
+ specification_version: 4
118
+ summary: Sportsrocket SDK for interacting with Zephyrus
119
+ test_files: []