rsynology 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in rsynology.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Jack Chen (chendo)
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,69 @@
1
+ # RSynology
2
+
3
+ This gems lets you interact the Synology DSM via their API.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'rsynology'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install rsynology
18
+
19
+ ## Usage
20
+
21
+ ```ruby
22
+ require 'rsynology'
23
+ client = RSynology::Client.new("https://<DSM host>:5001/", verify_ssl: false)
24
+ client.login!("username", "password")
25
+ pp client.endpoints['SYNO.SurveillanceStation.Event'].query
26
+
27
+ {"events"=>
28
+ [{"camera_id"=>2,
29
+ "event_size"=>3.739612579345703,
30
+ "frame_count"=>114,
31
+ "start_time"=>2013-02-26 22:02:16 +1100,
32
+ "stop_time"=>2013-02-26 22:02:30 +1100,
33
+ "video_codec"=>"MJPEG",
34
+ "id"=>24823,
35
+ "mode"=>1,
36
+ "status"=>0},
37
+ {"camera_id"=>2,
38
+ "event_size"=>3.819374084472656,
39
+ "frame_count"=>117,
40
+ "start_time"=>2013-02-26 22:02:02 +1100,
41
+ "stop_time"=>2013-02-26 22:02:16 +1100,
42
+ "video_codec"=>"MJPEG",
43
+ "id"=>24822,
44
+ "mode"=>1,
45
+ "status"=>0}],
46
+ "offset"=>0,
47
+ "total"=>11523}
48
+ ```
49
+
50
+ ## Status
51
+
52
+ ### Implemented APIs
53
+
54
+ * SYNO.API.Auth
55
+ * SYNO.SurveillanceStation.Event
56
+
57
+ Adding new APIs is pretty trivial. See either `auth.rb` or `surveillence_station_event.rb` in `lib/rsynology/client/`. Pull requests welcome!
58
+
59
+ ## Contributing
60
+
61
+ 1. Fork it
62
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
63
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
64
+ 4. Push to the branch (`git push origin my-new-feature`)
65
+ 5. Create new Pull Request
66
+
67
+ ## License
68
+
69
+ MIT! See `LICENSE.txt`
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,76 @@
1
+ module RSynology
2
+ class Client
3
+ class API
4
+ attr_reader :client, :options, :endpoint, :minVersion, :maxVersion
5
+
6
+ def self.api_name
7
+ raise NotImplementedError
8
+ end
9
+
10
+ def initialize(client, options)
11
+ @client = client
12
+ @options = options
13
+ @endpoint = options['path']
14
+ @minVersion = options['minVersion']
15
+ @maxVersion = options['maxVersion']
16
+ end
17
+
18
+ def api_name
19
+ self.class.api_name
20
+ end
21
+
22
+ def request(method, params, version = maxVersion)
23
+ params = {
24
+ method: method,
25
+ version: maxVersion,
26
+ api: api_name
27
+ }.merge(params)
28
+ client.request(endpoint, params)
29
+ end
30
+
31
+ protected
32
+
33
+ class UnknownError < StandardError; end
34
+ class InvalidParameters < ArgumentError; end
35
+ class APINotFound < ArgumentError; end
36
+ class MethodNotFound < ArgumentError; end
37
+ class APIVersionNotSupported < ArgumentError; end
38
+ class AccessDenied < StandardError; end
39
+ class ConnectionTimedOut < StandardError; end
40
+ class MultipleLoginsDetected < StandardError; end
41
+ class UnhandledErrorCode < StandardError; end
42
+
43
+ def handle_response(response)
44
+ if response['success']
45
+ response['data']
46
+ else
47
+ handle_error(response['error'])
48
+ end
49
+ end
50
+
51
+ def handle_error(error)
52
+ error_code = error['code']
53
+ case error_code
54
+ when 100
55
+ raise UnknownError
56
+ when 101
57
+ raise InvalidParameters
58
+ when 102
59
+ raise APINotFound
60
+ when 103
61
+ raise MethodNotFound
62
+ when 104
63
+ raise APIVersionNotSupported
64
+ when 105
65
+ raise AccessDenied
66
+ when 106
67
+ raise ConnectionTimedOut
68
+ when 107
69
+ raise MultipleLoginsDetected
70
+ else
71
+ raise UnhandledErrorCode, error_code
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,50 @@
1
+ module RSynology
2
+ class Client
3
+ class Auth < API
4
+ attr_reader :client, :endpoint, :maxVersion
5
+
6
+ class AuthenticationFailed < StandardError; end
7
+
8
+ def self.api_name
9
+ 'SYNO.API.Auth'
10
+ end
11
+
12
+ def login(account, password, session = nil, format = 'sid')
13
+ params = {
14
+ account: account,
15
+ passwd: password,
16
+ format: format,
17
+ }
18
+ params.merge!(session: session) if session
19
+
20
+ response = request("Login", params)
21
+
22
+ raise AuthenticationFailed if !response['success']
23
+
24
+ client.session_id = response['data']['sid']
25
+ end
26
+
27
+ def logout(session)
28
+ client.request(endpoint, {session: session})
29
+ end
30
+
31
+ protected
32
+
33
+ class AccountNotSpecified < ArgumentError; end
34
+ class InvalidPassword < StandardError; end
35
+ class AccountDisabledOrGuest < StandardError; end
36
+
37
+ def handle_error(error)
38
+ case error['code']
39
+ when 101
40
+ raise AccountNotSpecified
41
+ when 400
42
+ raise InvalidPassword
43
+ when 401
44
+ raise AccountDisabledOrGuest
45
+ end
46
+ super
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,50 @@
1
+ require 'hashie/trash'
2
+
3
+ module RSynology
4
+ class Client
5
+ class SurveillanceStationEvent < API
6
+
7
+ class Event < Hashie::Trash
8
+ TIME_TRANSFORM = lambda { |epoch| Time.at(epoch) }
9
+ property :id
10
+ property :camera_id, from: :cameraId
11
+ property :event_size, from: :eventSize
12
+ property :frame_count, from: :frameCount
13
+ property :mode
14
+ property :start_time, from: :startTime, with: TIME_TRANSFORM
15
+ property :stop_time, from: :stopTime, with: TIME_TRANSFORM
16
+ property :status
17
+ property :video_codec, from: :videoCodec
18
+
19
+ def duration
20
+ stop_time - start_time
21
+ end
22
+ end
23
+
24
+ def self.api_name
25
+ 'SYNO.SurveillanceStation.Event'
26
+ end
27
+
28
+ def query(params = {})
29
+ default_params = {
30
+ offset: 0,
31
+ limit: 10,
32
+ mode: nil,
33
+ locked: nil,
34
+ camera_ids: nil,
35
+ from_time: nil,
36
+ to_time: nil
37
+ }
38
+
39
+ merged_params = default_params.merge(params).reject do |k, v|
40
+ v.nil?
41
+ end
42
+
43
+ resp = request("Query", merged_params)
44
+ event_collection = handle_response(resp)
45
+ event_collection['events'].map! { |event_data| Event.new(event_data) }
46
+ event_collection
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,64 @@
1
+ require 'faraday'
2
+ require 'faraday_middleware'
3
+
4
+ module RSynology
5
+ class Client
6
+ attr_reader :connection
7
+ attr_accessor :session_id
8
+
9
+ class RequestFailed < StandardError; end
10
+
11
+ def initialize(url, options = {})
12
+ faraday_options = {url: url}
13
+ faraday_options[:ssl] = {verify: false} if options[:verify_ssl] == false
14
+
15
+ @connection = Faraday.new(faraday_options) do |faraday|
16
+ faraday.adapter Faraday.default_adapter # make requests with Net::HTTP
17
+ faraday.use FaradayMiddleware::ParseJson
18
+ faraday.use FaradayMiddleware::Mashify
19
+ end
20
+ end
21
+
22
+ def login!(account, password, session = nil, format = 'sid')
23
+ endpoints['SYNO.API.Auth'].login(account, password, session, format)
24
+ end
25
+
26
+ def endpoints
27
+ # Returns a hash of endpoints. Will return nil if no support
28
+ @endpoints ||= begin
29
+ resp = request('query.cgi', {
30
+ api: 'SYNO.API.Info',
31
+ method: 'Query',
32
+ version: 1,
33
+ query: 'SYNO.'
34
+ })
35
+ {}.tap do |result|
36
+ resp['data'].each do |endpoint, options|
37
+ next unless supported_apis[endpoint]
38
+ result[endpoint] = supported_apis[endpoint].new(self, options)
39
+ end
40
+ end
41
+ end
42
+ end
43
+
44
+ def request(endpoint, params)
45
+ params = params.merge(_sid: session_id) if session_id
46
+ resp = connection.get("/webapi/#{endpoint}", params)
47
+ resp.body
48
+ end
49
+
50
+ private
51
+
52
+ def supported_apis
53
+ @supported_apis ||= {}.tap do |apis|
54
+ self.class.constants.each do |symbol|
55
+ next if symbol == :API
56
+ const = self.class.const_get(symbol)
57
+ if const.respond_to?(:api_name)
58
+ apis[const.api_name] = const
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,3 @@
1
+ module RSynology
2
+ VERSION = "0.0.1"
3
+ end
data/lib/rsynology.rb ADDED
@@ -0,0 +1,4 @@
1
+ Dir[File.join(File.dirname(__FILE__), 'rsynology', '**', '*.rb')].each { |f| require f }
2
+ module RSynology
3
+
4
+ end
data/rsynology.gemspec ADDED
@@ -0,0 +1,23 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'rsynology/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "rsynology"
8
+ gem.version = RSynology::VERSION
9
+ gem.authors = ["Jack Chen (chendo)"]
10
+ gem.email = ["gems+rsynology@chen.do"]
11
+ gem.description = %q{A gem to access the API exposed by Synology DSM apps}
12
+ gem.summary = %q{A gem to access the API exposed by Synology DSM apps}
13
+ gem.homepage = ""
14
+
15
+ gem.files = `git ls-files`.split($/)
16
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
+ gem.require_paths = ["lib"]
19
+
20
+ gem.add_dependency('faraday', '~> 0.8.5')
21
+ gem.add_dependency('faraday_middleware')
22
+ gem.add_dependency('hashie')
23
+ end
metadata ADDED
@@ -0,0 +1,105 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rsynology
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Jack Chen (chendo)
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-03-02 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: faraday
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: 0.8.5
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: 0.8.5
30
+ - !ruby/object:Gem::Dependency
31
+ name: faraday_middleware
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: hashie
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ description: A gem to access the API exposed by Synology DSM apps
63
+ email:
64
+ - gems+rsynology@chen.do
65
+ executables: []
66
+ extensions: []
67
+ extra_rdoc_files: []
68
+ files:
69
+ - .gitignore
70
+ - Gemfile
71
+ - LICENSE.txt
72
+ - README.md
73
+ - Rakefile
74
+ - lib/rsynology.rb
75
+ - lib/rsynology/client.rb
76
+ - lib/rsynology/client/api.rb
77
+ - lib/rsynology/client/auth.rb
78
+ - lib/rsynology/client/surveillance_station_event.rb
79
+ - lib/rsynology/version.rb
80
+ - rsynology.gemspec
81
+ homepage: ''
82
+ licenses: []
83
+ post_install_message:
84
+ rdoc_options: []
85
+ require_paths:
86
+ - lib
87
+ required_ruby_version: !ruby/object:Gem::Requirement
88
+ none: false
89
+ requirements:
90
+ - - ! '>='
91
+ - !ruby/object:Gem::Version
92
+ version: '0'
93
+ required_rubygems_version: !ruby/object:Gem::Requirement
94
+ none: false
95
+ requirements:
96
+ - - ! '>='
97
+ - !ruby/object:Gem::Version
98
+ version: '0'
99
+ requirements: []
100
+ rubyforge_project:
101
+ rubygems_version: 1.8.23
102
+ signing_key:
103
+ specification_version: 3
104
+ summary: A gem to access the API exposed by Synology DSM apps
105
+ test_files: []