instamsg-ruby 0.0.1 → 0.0.11

Sign up to get free protection for your applications and to get access to all the features.
@@ -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, 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 instamsg-ruby.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2015 InstaMsg
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
data/README.md ADDED
@@ -0,0 +1,2 @@
1
+ # instamsg-ruby
2
+ This is a ruby server library for InstaMsg api.
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+
@@ -0,0 +1,35 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'lib/instamsg/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "instamsg-ruby"
8
+ spec.version = Instamsg::VERSION
9
+ spec.platform = Gem::Platform::RUBY
10
+ spec.authors = ["Instamsg"]
11
+ spec.email = ["support@sensegrow.com"]
12
+
13
+ if spec.respond_to?(:metadata)
14
+ spec.metadata['allowed_push_host'] = "TODO: Set to 'http://mygemserver.com' to prevent pushes to rubygems.org, or delete to allow pushes to any server."
15
+ end
16
+
17
+ spec.summary = %q{Instamsg api client.}
18
+ spec.description = %q{Wrapper for instamsg.io REST api}
19
+ spec.homepage = "http://github.com/instamsg/instamsg-ruby"
20
+ spec.license = "MIT"
21
+
22
+ spec.files = `git ls-files`.split("\n")
23
+ spec.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
24
+ spec.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
25
+ spec.require_paths = ["lib"]
26
+
27
+ spec.add_dependency "httpclient", "~> 2.5"
28
+ spec.add_dependency "jruby-openssl" if defined?(JRUBY_VERSION)
29
+
30
+ spec.add_development_dependency "rspec", "~> 2.0"
31
+ spec.add_development_dependency "webmock"
32
+ spec.add_development_dependency "em-http-request", "~> 1.1.0"
33
+ spec.add_development_dependency "bundler", "~> 1.8"
34
+ spec.add_development_dependency "rake", "~> 10.0"
35
+ end
data/lib/instamsg.rb ADDED
@@ -0,0 +1,40 @@
1
+ autoload 'Logger', 'logger'
2
+ require 'uri'
3
+ require 'forwardable'
4
+ require 'instamsg/client'
5
+ # Used for configuring API credentials and creating client objects
6
+ #
7
+ module Instamsg
8
+
9
+ class Error < RuntimeError; end
10
+ class AuthenticationError < Error; end
11
+ class ConfigurationError < Error; end
12
+ class HTTPError < Error; attr_accessor :original_error; end
13
+ class << self
14
+
15
+ extend Forwardable
16
+ def_delegators :default_client, :scheme, :host, :port, :key, :secret, :http_proxy, :bearer_token
17
+ def_delegators :default_client, :scheme=, :host=, :port=, :key=, :secret=, :http_proxy=, :bearer_token=
18
+ def_delegators :default_client, :bearer_token, :access_token, :url
19
+ def_delegators :default_client, :encrypted=, :url=
20
+ def_delegators :default_client, :timeout=, :connect_timeout=, :send_timeout=, :receive_timeout=, :keep_alive_timeout=
21
+ def_delegators :default_client, :get, :get_async, :post, :post_async, :authenticate
22
+
23
+ attr_writer :logger
24
+ def logger
25
+ @logger ||= begin
26
+ log = Logger.new($stdout)
27
+ log.level = Logger::INFO
28
+ log
29
+ end
30
+ end
31
+ def default_client
32
+ @default_client ||= Instamsg::Client.new
33
+ end
34
+ end
35
+ if ENV['INSTAMSG_URL']
36
+ self.url = ENV['INSTAMSG_URL']
37
+ end
38
+ end
39
+ require 'instamsg/request'
40
+ require 'instamsg/resource'
@@ -0,0 +1,173 @@
1
+ require 'httpclient'
2
+ require "base64"
3
+
4
+ module Instamsg
5
+ class Client
6
+ attr_accessor :scheme, :host, :port, :key, :secret, :bearer_token
7
+ attr_reader :http_proxy, :proxy
8
+ attr_writer :connect_timeout, :send_timeout, :response_timeout,
9
+ :keep_alive_timeout
10
+
11
+ def initialize(options = {})
12
+ default = {
13
+ :scheme => 'https',
14
+ :host => 'platform.instamsg.io',
15
+ :port => 443,
16
+ }.merge(options)
17
+ @scheme, @host, @port, @key, @secret, @bearer_token = default.values_at(
18
+ :scheme, :host, :port, :key, :secret, :bearer_token
19
+ )
20
+
21
+ @http_proxy = nil
22
+ self.http_proxy = default[:http_proxy] if default[:http_proxy]
23
+
24
+ @connect_timeout = 15
25
+ @send_timeout = 100
26
+ @response_timeout = 180
27
+ @keep_alive_timeout = 180
28
+ end
29
+
30
+ def url(path = nil)
31
+ URI::Generic.build({
32
+ :scheme => @scheme,
33
+ :host => @host,
34
+ :port => @port,
35
+ :path => "#{path}"
36
+ })
37
+ end
38
+
39
+ def access_token
40
+ @access_token ||= "Basic " + Base64.encode64(@key + ":" + @secret).delete("\n")
41
+ end
42
+
43
+ def bearer_token
44
+ "Bearer " + @bearer_token
45
+ end
46
+
47
+ def url=(url)
48
+ uri = URI.parse(url)
49
+ @scheme = uri.scheme
50
+ @key = uri.user
51
+ @secret = uri.password
52
+ @host = uri.host
53
+ @port = uri.port
54
+ end
55
+
56
+ def http_proxy=(http_proxy)
57
+ @http_proxy = http_proxy
58
+ uri = URI.parse(http_proxy)
59
+ @proxy = {
60
+ :scheme => uri.scheme,
61
+ :host => uri.host,
62
+ :port => uri.port,
63
+ :user => uri.user,
64
+ :password => uri.password
65
+ }
66
+ @http_proxy
67
+ end
68
+
69
+ def encrypted=(boolean)
70
+ @scheme = boolean ? 'https' : 'http'
71
+ @port = boolean ? 8601 : 8600
72
+ end
73
+
74
+ def encrypted?
75
+ @scheme == 'https'
76
+ end
77
+
78
+ def timeout=(value)
79
+ @connect_timeout, @send_timeout, @response_timeout = value, value, value
80
+ end
81
+
82
+ def resource(path)
83
+ Resource.new(self, path)
84
+ end
85
+
86
+ def authenticate(path, params = {})
87
+ Resource.new(self, path).authenticate(params)
88
+ end
89
+
90
+ def invalidate(path, params = {})
91
+ Resource.new(self, path).authenticate(params)
92
+ end
93
+
94
+ def get(path, params = {})
95
+ Resource.new(self, path).get(params)
96
+ end
97
+
98
+ def get_async(path, params = {})
99
+ Resource.new(self, path).get_async(params)
100
+ end
101
+
102
+ def post(path, params = {})
103
+ Resource.new(self, path).post(params)
104
+ end
105
+
106
+ def post_async(path, params = {})
107
+ Resource.new(self, path).post_async(params)
108
+ end
109
+
110
+ def put(path, params = {})
111
+ Resource.new(self, path).put(params)
112
+ end
113
+
114
+ def put_async(path, params = {})
115
+ Resource.new(self, path).put_async(params)
116
+ end
117
+
118
+ def delete(path, params = {})
119
+ Resource.new(self, path).delete(params)
120
+ end
121
+
122
+ def delete_async(path, params = {})
123
+ Resource.new(self, path).delete_aysnc(params)
124
+ end
125
+
126
+ def get_file(path, params= {})
127
+ Resource.new(self, path).download(params)
128
+ end
129
+
130
+ def put_file(path, params= {})
131
+ Resource.new(self, path).upload(params)
132
+ end
133
+
134
+ def http_sync_client
135
+ @client ||= begin
136
+ HTTPClient.new(@http_proxy).tap do |c|
137
+ c.connect_timeout = @connect_timeout
138
+ c.send_timeout = @send_timeout
139
+ c.receive_timeout = @response_timeout
140
+ c.keep_alive_timeout = @keep_alive_timeout
141
+ end
142
+ end
143
+ end
144
+
145
+ def http_async_client(uri)
146
+ begin
147
+ unless defined?(EventMachine) && EventMachine.reactor_running?
148
+ raise Error, "Must use event machine for async request."
149
+ end
150
+ require 'em-http' unless defined?(EventMachine::HttpRequest)
151
+
152
+ conn_options = {
153
+ :connect_timeout => @connect_timeout,
154
+ :inactivity_timeout => @response_timeout,
155
+ }
156
+
157
+ if defined?(@proxy)
158
+ proxy_options = {
159
+ :host => @proxy[:host],
160
+ :port => @proxy[:port]
161
+ }
162
+ if @proxy[:user]
163
+ proxy_options[:authorization] = [@proxy[:user], @proxy[:password]]
164
+ end
165
+ conn_options[:proxy] = proxy_options
166
+ end
167
+
168
+ EventMachine::HttpRequest.new(uri, conn_options)
169
+ end
170
+ end
171
+
172
+ end
173
+ end
@@ -0,0 +1,140 @@
1
+ require 'openssl'
2
+ module Instamsg
3
+ class Request
4
+ attr_reader :body, :params
5
+
6
+ def initialize(client, verb, uri, token, params, body = nil)
7
+ @client, @verb, @uri = client, verb, uri
8
+ @head = {}
9
+ @body = body
10
+ if @body
11
+ @head['Content-Type'] = 'application/json'
12
+ end
13
+ @head['Authorization'] = token
14
+ @params = params
15
+ end
16
+
17
+ def send_sync
18
+ http = @client.http_sync_client
19
+ http.ssl_config.verify_mode = OpenSSL::SSL::VERIFY_NONE
20
+ begin
21
+ response = http.request(@verb, @uri, @params, @body, @head)
22
+ rescue HTTPClient::BadResponseError, HTTPClient::TimeoutError,
23
+ SocketError, HTTPClient::ReceiveTimeoutError, Errno::ECONNREFUSED => e
24
+ error = Instamsg::HTTPError.new("#{e.message} (#{e.class})")
25
+ error.original_error = e
26
+
27
+ raise error
28
+ end
29
+ body = response.body ? response.body.chomp : nil
30
+ return handle_response(response.code.to_i, body)
31
+ end
32
+
33
+ def send_async
34
+ if defined?(EventMachine) && EventMachine.reactor_running?
35
+ http_client = @client.http_async_client(@uri)
36
+ deferrable = EM::DefaultDeferrable.new
37
+
38
+ http = case @verb
39
+ when :post
40
+ http_client.post({
41
+ :query => @params, :body => @body, :head => @head
42
+ })
43
+ when :get
44
+ http_client.get({
45
+ :query => @params, :head => @head
46
+ })
47
+ when :put
48
+ http_client.put({
49
+ :query => @params, :body => @body, :head => @head
50
+ })
51
+ when :delete
52
+ http_client.delete({
53
+ :query => @params, :head => @head
54
+ })
55
+ else
56
+ raise "Unsupported verb"
57
+ end
58
+
59
+ http.callback {
60
+ begin
61
+ deferrable.succeed(handle_response(http.response_header.status, http.response.chomp))
62
+ rescue => e
63
+ deferrable.fail(e)
64
+ end
65
+ }
66
+
67
+ http.errback { |e|
68
+ message = "Instamsg connection error : (#{http.error})"
69
+ Instamsg.logger.debug(message)
70
+ deferrable.fail(Error.new(message))
71
+ }
72
+
73
+
74
+ return deferrable
75
+ else
76
+ http = @client.sync_http_client
77
+ return http.request_async(@verb, @uri, @params, @body, @head)
78
+ end
79
+ end
80
+
81
+ def download_em_http(urls, concurrency)
82
+ EventMachine.run do
83
+ multi = EventMachine::MultiRequest.new
84
+
85
+ EM::Iterator.new(urls, concurrency).each do |url, iterator|
86
+ req = EventMachine::HttpRequest.new(url).get
87
+ req.callback do
88
+ write_file url, req.response
89
+ iterator.next
90
+ end
91
+ multi.add url, req
92
+ multi.callback { EventMachine.stop } if url == urls.last
93
+ end
94
+ end
95
+ end
96
+
97
+ def upload_sync
98
+ http = @client.http_sync_client
99
+ http.ssl_config.verify_mode = OpenSSL::SSL::VERIFY_NONE
100
+ begin
101
+ File.open(@params["file"]) do |file|
102
+ @body = { :file => file}
103
+ response = http.request(@verb, @uri, @params, @body, @head)
104
+
105
+ body = response.body ? response.body.chomp : nil
106
+ return handle_response(response.code.to_i, body)
107
+ end
108
+ rescue HTTPClient::BadResponseError, HTTPClient::TimeoutError,
109
+ SocketError, HTTPClient::ReceiveTimeoutError, Errno::ECONNREFUSED => e
110
+ error = Instamsg::HTTPError.new("#{e.message} (#{e.class})")
111
+ error.original_error = e
112
+ raise error
113
+ end
114
+ end
115
+
116
+ private
117
+
118
+ def handle_response(status_code, body)
119
+ case status_code
120
+ when 200
121
+ return body
122
+ when 202
123
+ return true
124
+ when 400
125
+ raise Error, "Bad request: #{body}"
126
+ when 401
127
+ raise AuthenticationError, body
128
+ when 403
129
+ raise Error, "#{body}"
130
+ when 404
131
+ raise Error, "404 Not found (#{@uri.path})"
132
+ when 407
133
+ raise Error, "Proxy Authentication Required"
134
+ else
135
+ raise Error, "Unknown error (status code #{status_code}): #{body}"
136
+ end
137
+ end
138
+
139
+ end
140
+ end
@@ -0,0 +1,74 @@
1
+ module Instamsg
2
+ class Resource
3
+ def initialize(client, path)
4
+ @client = client
5
+ @path = path
6
+ end
7
+
8
+ def get(params)
9
+ create_request(:get, params).send_sync
10
+ end
11
+
12
+ def get_async(params)
13
+ create_request(:get, params).send_async
14
+ end
15
+
16
+ def post(params)
17
+ body = MultiJson.encode(params)
18
+ create_request(:post, {}, body).send_sync
19
+ end
20
+
21
+ def post_async(params)
22
+ body = MultiJson.encode(params)
23
+ create_request(:post, {}, body).send_async
24
+ end
25
+
26
+ def put(params)
27
+ body = MultiJson.encode(params)
28
+ create_request(:put, {}, body).send_sync
29
+ end
30
+
31
+ def put_async(params)
32
+ body = MultiJson.encode(params)
33
+ create_request(:put, {}, body).send_async
34
+ end
35
+
36
+ def delete(params)
37
+ create_request(:delete, params).send_sync
38
+ end
39
+
40
+ def delete_async(params)
41
+ create_request(:delete, params).send_async
42
+ end
43
+
44
+ def download(params)
45
+ create_request(:post, params).send_sync
46
+ end
47
+
48
+ def upload(params)
49
+ create_request(:post, params).upload_sync
50
+ end
51
+
52
+ def authenticate(params)
53
+ authenticate_request(:post, params).send_sync
54
+ end
55
+
56
+ private
57
+
58
+ def create_request(verb, params, body = nil)
59
+ Request.new(@client, verb, url, token, params, body)
60
+ end
61
+
62
+ def authenticate_request(verb, params, body = nil)
63
+ Request.new(@client, verb, url, @client.access_token, params, body)
64
+ end
65
+
66
+ def url
67
+ @_url ||= @client.url(@path)
68
+ end
69
+
70
+ def token
71
+ @token ||= @client.bearer_token
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,3 @@
1
+ module Instamsg
2
+ VERSION = "0.0.11"
3
+ end
@@ -0,0 +1,11 @@
1
+ require 'spec_helper'
2
+
3
+ describe Instamsg::Ruby do
4
+ it 'has a version number' do
5
+ expect(Instamsg::Ruby::VERSION).not_to be nil
6
+ end
7
+
8
+ it 'does something useful' do
9
+ expect(false).to eq(true)
10
+ end
11
+ end
@@ -0,0 +1,2 @@
1
+ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
2
+ require 'instamsg/ruby'
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: instamsg-ruby
3
3
  version: !ruby/object:Gem::Version
4
- hash: 29
4
+ hash: 9
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 0
9
- - 1
10
- version: 0.0.1
9
+ - 11
10
+ version: 0.0.11
11
11
  platform: ruby
12
12
  authors:
13
13
  - Instamsg
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2015-04-01 00:00:00 Z
18
+ date: 2015-04-02 00:00:00 Z
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
21
  name: httpclient
@@ -116,8 +116,20 @@ extensions: []
116
116
 
117
117
  extra_rdoc_files: []
118
118
 
119
- files: []
120
-
119
+ files:
120
+ - CODE_OF_CONDUCT.md
121
+ - Gemfile
122
+ - LICENSE
123
+ - README.md
124
+ - Rakefile
125
+ - instamsg-ruby.gemspec
126
+ - lib/instamsg.rb
127
+ - lib/instamsg/client.rb
128
+ - lib/instamsg/request.rb
129
+ - lib/instamsg/resource.rb
130
+ - lib/instamsg/version.rb
131
+ - spec/instamsg/ruby_spec.rb
132
+ - spec/spec_helper.rb
121
133
  homepage: http://github.com/instamsg/instamsg-ruby
122
134
  licenses:
123
135
  - MIT