robinhood-ruby 0.3.3

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.
Files changed (93) hide show
  1. checksums.yaml +7 -0
  2. data/.DS_Store +0 -0
  3. data/.coveralls.yml +1 -0
  4. data/.github/robinhood-ruby.png +0 -0
  5. data/.gitignore +9 -0
  6. data/.rspec +2 -0
  7. data/.travis.yml +15 -0
  8. data/CODE_OF_CONDUCT.md +74 -0
  9. data/Gemfile +11 -0
  10. data/Guardfile +5 -0
  11. data/LICENSE.txt +21 -0
  12. data/README.md +520 -0
  13. data/Rakefile +8 -0
  14. data/bin/console +14 -0
  15. data/bin/setup +8 -0
  16. data/example/.DS_Store +0 -0
  17. data/example/robinhood-sample/.DS_Store +0 -0
  18. data/example/robinhood-sample/.env.example +2 -0
  19. data/example/robinhood-sample/.gitignore +19 -0
  20. data/example/robinhood-sample/Gemfile +16 -0
  21. data/example/robinhood-sample/Gemfile.lock +164 -0
  22. data/example/robinhood-sample/README.MD +7 -0
  23. data/example/robinhood-sample/Rakefile +6 -0
  24. data/example/robinhood-sample/app/assets/images/.keep +0 -0
  25. data/example/robinhood-sample/app/assets/javascripts/application.js +16 -0
  26. data/example/robinhood-sample/app/assets/stylesheets/application.css +15 -0
  27. data/example/robinhood-sample/app/controllers/application_controller.rb +5 -0
  28. data/example/robinhood-sample/app/controllers/concerns/.keep +0 -0
  29. data/example/robinhood-sample/app/helpers/application_helper.rb +2 -0
  30. data/example/robinhood-sample/app/mailers/.keep +0 -0
  31. data/example/robinhood-sample/app/models/.keep +0 -0
  32. data/example/robinhood-sample/app/models/concerns/.keep +0 -0
  33. data/example/robinhood-sample/app/views/layouts/application.html.erb +14 -0
  34. data/example/robinhood-sample/bin/bundle +3 -0
  35. data/example/robinhood-sample/bin/rails +9 -0
  36. data/example/robinhood-sample/bin/rake +9 -0
  37. data/example/robinhood-sample/bin/setup +29 -0
  38. data/example/robinhood-sample/bin/spring +16 -0
  39. data/example/robinhood-sample/config.ru +4 -0
  40. data/example/robinhood-sample/config/.DS_Store +0 -0
  41. data/example/robinhood-sample/config/application.rb +26 -0
  42. data/example/robinhood-sample/config/boot.rb +3 -0
  43. data/example/robinhood-sample/config/database.yml +25 -0
  44. data/example/robinhood-sample/config/environment.rb +5 -0
  45. data/example/robinhood-sample/config/environments/development.rb +41 -0
  46. data/example/robinhood-sample/config/environments/production.rb +79 -0
  47. data/example/robinhood-sample/config/environments/test.rb +42 -0
  48. data/example/robinhood-sample/config/initializers/.DS_Store +0 -0
  49. data/example/robinhood-sample/config/initializers/assets.rb +11 -0
  50. data/example/robinhood-sample/config/initializers/backtrace_silencers.rb +7 -0
  51. data/example/robinhood-sample/config/initializers/cookies_serializer.rb +3 -0
  52. data/example/robinhood-sample/config/initializers/filter_parameter_logging.rb +4 -0
  53. data/example/robinhood-sample/config/initializers/inflections.rb +16 -0
  54. data/example/robinhood-sample/config/initializers/mime_types.rb +4 -0
  55. data/example/robinhood-sample/config/initializers/robinhood.rb +1 -0
  56. data/example/robinhood-sample/config/initializers/session_store.rb +3 -0
  57. data/example/robinhood-sample/config/initializers/wrap_parameters.rb +14 -0
  58. data/example/robinhood-sample/config/locales/en.yml +23 -0
  59. data/example/robinhood-sample/config/routes.rb +56 -0
  60. data/example/robinhood-sample/config/secrets.yml +22 -0
  61. data/example/robinhood-sample/db/seeds.rb +7 -0
  62. data/example/robinhood-sample/lib/.DS_Store +0 -0
  63. data/example/robinhood-sample/lib/assets/.keep +0 -0
  64. data/example/robinhood-sample/lib/tasks/.keep +0 -0
  65. data/example/robinhood-sample/log/.keep +0 -0
  66. data/example/robinhood-sample/public/404.html +67 -0
  67. data/example/robinhood-sample/public/422.html +67 -0
  68. data/example/robinhood-sample/public/500.html +66 -0
  69. data/example/robinhood-sample/public/favicon.ico +0 -0
  70. data/example/robinhood-sample/public/robots.txt +5 -0
  71. data/example/robinhood-sample/test/controllers/.keep +0 -0
  72. data/example/robinhood-sample/test/fixtures/.keep +0 -0
  73. data/example/robinhood-sample/test/helpers/.keep +0 -0
  74. data/example/robinhood-sample/test/integration/.keep +0 -0
  75. data/example/robinhood-sample/test/mailers/.keep +0 -0
  76. data/example/robinhood-sample/test/models/.keep +0 -0
  77. data/example/robinhood-sample/test/test_helper.rb +10 -0
  78. data/example/robinhood-sample/vendor/assets/javascripts/.keep +0 -0
  79. data/example/robinhood-sample/vendor/assets/stylesheets/.keep +0 -0
  80. data/lib/.DS_Store +0 -0
  81. data/lib/robinhood-ruby.rb +37 -0
  82. data/lib/robinhood-ruby/.DS_Store +0 -0
  83. data/lib/robinhood-ruby/rest/.DS_Store +0 -0
  84. data/lib/robinhood-ruby/rest/api.rb +184 -0
  85. data/lib/robinhood-ruby/rest/client.rb +120 -0
  86. data/lib/robinhood-ruby/util.rb +4 -0
  87. data/lib/robinhood-ruby/util/.DS_Store +0 -0
  88. data/lib/robinhood-ruby/util/configuration.rb +7 -0
  89. data/lib/robinhood-ruby/util/request.rb +51 -0
  90. data/lib/robinhood-ruby/version.rb +3 -0
  91. data/robinhood-ruby-0.3.2.gem +0 -0
  92. data/robinhood-ruby.gemspec +52 -0
  93. metadata +346 -0
@@ -0,0 +1,67 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>The change you wanted was rejected (422)</title>
5
+ <meta name="viewport" content="width=device-width,initial-scale=1">
6
+ <style>
7
+ body {
8
+ background-color: #EFEFEF;
9
+ color: #2E2F30;
10
+ text-align: center;
11
+ font-family: arial, sans-serif;
12
+ margin: 0;
13
+ }
14
+
15
+ div.dialog {
16
+ width: 95%;
17
+ max-width: 33em;
18
+ margin: 4em auto 0;
19
+ }
20
+
21
+ div.dialog > div {
22
+ border: 1px solid #CCC;
23
+ border-right-color: #999;
24
+ border-left-color: #999;
25
+ border-bottom-color: #BBB;
26
+ border-top: #B00100 solid 4px;
27
+ border-top-left-radius: 9px;
28
+ border-top-right-radius: 9px;
29
+ background-color: white;
30
+ padding: 7px 12% 0;
31
+ box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
32
+ }
33
+
34
+ h1 {
35
+ font-size: 100%;
36
+ color: #730E15;
37
+ line-height: 1.5em;
38
+ }
39
+
40
+ div.dialog > p {
41
+ margin: 0 0 1em;
42
+ padding: 1em;
43
+ background-color: #F7F7F7;
44
+ border: 1px solid #CCC;
45
+ border-right-color: #999;
46
+ border-left-color: #999;
47
+ border-bottom-color: #999;
48
+ border-bottom-left-radius: 4px;
49
+ border-bottom-right-radius: 4px;
50
+ border-top-color: #DADADA;
51
+ color: #666;
52
+ box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
53
+ }
54
+ </style>
55
+ </head>
56
+
57
+ <body>
58
+ <!-- This file lives in public/422.html -->
59
+ <div class="dialog">
60
+ <div>
61
+ <h1>The change you wanted was rejected.</h1>
62
+ <p>Maybe you tried to change something you didn't have access to.</p>
63
+ </div>
64
+ <p>If you are the application owner check the logs for more information.</p>
65
+ </div>
66
+ </body>
67
+ </html>
@@ -0,0 +1,66 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>We're sorry, but something went wrong (500)</title>
5
+ <meta name="viewport" content="width=device-width,initial-scale=1">
6
+ <style>
7
+ body {
8
+ background-color: #EFEFEF;
9
+ color: #2E2F30;
10
+ text-align: center;
11
+ font-family: arial, sans-serif;
12
+ margin: 0;
13
+ }
14
+
15
+ div.dialog {
16
+ width: 95%;
17
+ max-width: 33em;
18
+ margin: 4em auto 0;
19
+ }
20
+
21
+ div.dialog > div {
22
+ border: 1px solid #CCC;
23
+ border-right-color: #999;
24
+ border-left-color: #999;
25
+ border-bottom-color: #BBB;
26
+ border-top: #B00100 solid 4px;
27
+ border-top-left-radius: 9px;
28
+ border-top-right-radius: 9px;
29
+ background-color: white;
30
+ padding: 7px 12% 0;
31
+ box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
32
+ }
33
+
34
+ h1 {
35
+ font-size: 100%;
36
+ color: #730E15;
37
+ line-height: 1.5em;
38
+ }
39
+
40
+ div.dialog > p {
41
+ margin: 0 0 1em;
42
+ padding: 1em;
43
+ background-color: #F7F7F7;
44
+ border: 1px solid #CCC;
45
+ border-right-color: #999;
46
+ border-left-color: #999;
47
+ border-bottom-color: #999;
48
+ border-bottom-left-radius: 4px;
49
+ border-bottom-right-radius: 4px;
50
+ border-top-color: #DADADA;
51
+ color: #666;
52
+ box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
53
+ }
54
+ </style>
55
+ </head>
56
+
57
+ <body>
58
+ <!-- This file lives in public/500.html -->
59
+ <div class="dialog">
60
+ <div>
61
+ <h1>We're sorry, but something went wrong.</h1>
62
+ </div>
63
+ <p>If you are the application owner check the logs for more information.</p>
64
+ </div>
65
+ </body>
66
+ </html>
File without changes
@@ -0,0 +1,5 @@
1
+ # See http://www.robotstxt.org/robotstxt.html for documentation on how to use the robots.txt file
2
+ #
3
+ # To ban all spiders from the entire site uncomment the next two lines:
4
+ # User-agent: *
5
+ # Disallow: /
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -0,0 +1,10 @@
1
+ ENV['RAILS_ENV'] ||= 'test'
2
+ require File.expand_path('../../config/environment', __FILE__)
3
+ require 'rails/test_help'
4
+
5
+ class ActiveSupport::TestCase
6
+ # Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical order.
7
+ fixtures :all
8
+
9
+ # Add more helper methods to be used by all tests here...
10
+ end
data/lib/.DS_Store ADDED
Binary file
@@ -0,0 +1,37 @@
1
+ require 'net/http'
2
+ require 'net/https'
3
+ require 'builder'
4
+ require 'multi_json'
5
+ require 'cgi'
6
+ require 'openssl'
7
+ require 'base64'
8
+ require 'forwardable'
9
+ require 'singleton'
10
+
11
+ require 'robinhood-ruby/version' unless defined?(Robinhood::VERSION)
12
+ require 'robinhood-ruby'
13
+ require 'robinhood-ruby/util'
14
+ require 'robinhood-ruby/util/configuration'
15
+ require 'robinhood-ruby/util/request'
16
+ require 'robinhood-ruby/rest/api'
17
+ require 'robinhood-ruby/rest/client'
18
+
19
+ module Robinhood
20
+ extend SingleForwardable
21
+
22
+ def_delegators :configuration, :username, :password
23
+
24
+ ##
25
+ # Pre-configure with account SID and auth token so that you don't need to
26
+ # pass them to various initializers each time.
27
+ def self.configure(&block)
28
+ yield configuration
29
+ end
30
+
31
+ ##
32
+ # Returns an existing or instantiates a new configuration object.
33
+ def self.configuration
34
+ @configuration ||= Util::Configuration.new
35
+ end
36
+ private_class_method :configuration
37
+ end
Binary file
Binary file
@@ -0,0 +1,184 @@
1
+ module Robinhood
2
+ module REST
3
+ class API
4
+ def account
5
+ url = URI(@api_url + @endpoints[:accounts])
6
+ response = http_request(url)
7
+ puts response.read_body
8
+ JSON.parse(response.read_body)
9
+ end
10
+
11
+ def investment_profile
12
+ url = URI(@api_url + @endpoints[:investment_profile])
13
+ response = http_request(url)
14
+ puts response.read_body
15
+ JSON.parse(response.read_body)
16
+ end
17
+
18
+ def fundamentals(ticker)
19
+ url = URI(@api_url + @endpoints[:fundamentals] + "?symbols=" + ticker.to_s)
20
+ response = http_request(url)
21
+ puts response.read_body
22
+ JSON.parse(response.read_body)
23
+ end
24
+
25
+ def instruments(symbol)
26
+ url = URI(@api_url + @endpoints[:instruments] + "?query=" + symbol.to_s)
27
+ response = http_request(url)
28
+ puts response.read_body
29
+ JSON.parse(response.read_body)
30
+ end
31
+
32
+ def quote_data(symbol)
33
+ symbol = symbol.is_a?(Array) ? symbol.join(',') : symbol;
34
+ url = URI(@api_url + @endpoints[:quotes] + "?symbols=" + symbol.to_s)
35
+ response = http_request(url)
36
+ puts response.read_body
37
+ JSON.parse(response.read_body)
38
+ end
39
+
40
+ def user
41
+ url = URI(@api_url + @endpoints[:user])
42
+ response = http_request(url)
43
+ puts response.read_body
44
+ JSON.parse(response.read_body)
45
+ end
46
+
47
+ def dividends
48
+ url = URI(@api_url + @endpoints[:dividends])
49
+ response = http_request(url)
50
+ puts response.read_body
51
+ JSON.parse(response.read_body)
52
+ end
53
+
54
+ def orders
55
+ url = URI(@api_url + @endpoints[:orders])
56
+ response = http_request(url)
57
+ puts response.read_body
58
+ JSON.parse(response.read_body)
59
+ end
60
+
61
+ # def cancel_order(order)
62
+ # if(order.cancel){
63
+ # return _request.post({
64
+ # uri: _apiUrl + order.cancel
65
+ # }, callback);
66
+ # }else{
67
+ # callback({message: order.state=="cancelled" ? "Order already cancelled." : "Order cannot be cancelled.", order: order }, null, null);
68
+ # };
69
+ # }
70
+
71
+ def place_order(options)
72
+ url = URI(@api_url + @endpoints[:orders])
73
+ http = Net::HTTP.new(url.host, url.port)
74
+ http.use_ssl = true
75
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
76
+
77
+ form = {
78
+ account: _private.account,
79
+ instrument: options.instrument.url,
80
+ price: options.bid_price,
81
+ stop_price: options.stop_price,
82
+ quantity: options.quantity,
83
+ side: options.transaction,
84
+ symbol: options.instrument.symbol.toUpperCase(),
85
+ time_in_force: options.time || 'gfd',
86
+ trigger: options.trigger || 'immediate',
87
+ type: options.type || 'market'
88
+ }
89
+
90
+ request = Net::HTTP::Post.new(url)
91
+ request["accept"] = '*/*'
92
+ request["accept-encoding"] = 'gzip, deflate'
93
+ request["accept-language"] = 'en;q=1, fr;q=0.9, de;q=0.8, ja;q=0.7, nl;q=0.6, it;q=0.5'
94
+ request["content-type"] = 'multipart/form-data; boundary=---011000010111000001101001'
95
+ request["x-robinhood-api-version"] = '1.0.0'
96
+ request["connection"] = 'keep-alive'
97
+ request["user-agent"] = 'Robinhood/823 (iPhone; iOS 7.1.2; Scale/2.00)'
98
+ request["authorization"] = 'Token ' + @private[:auth_token]
99
+ request["cache-control"] = 'no-cache'
100
+ request.body = "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"account\"\r\n\r\n"+form[:account]+"\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"instrument\"\r\n\r\n"+form[:instrument]+"\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"price\"\r\n\r\n"+form[:price]+"\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"stop_price\"\r\n\r\n"+form[:stop_price]+"\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"quantity\"\r\n\r\n"+form[:quantity]+"\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"side\"\r\n\r\n"+form[:side]+"\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"symbol\"\r\n\r\n"+form[:symbol]+"\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"time_in_force\"\r\n\r\n"+form[:time_in_force]+"\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"trigger\"\r\n\r\n"+form[:trigger]+"\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"type\"\r\n\r\n"+form[:type]+"\r\n-----011000010111000001101001--"
101
+
102
+ response = http.request(request)
103
+ puts response.read_body
104
+ JSON.parse(response.read_body)
105
+ end
106
+
107
+ def place_buy_order(options)
108
+ options[:transaction] = 'buy'
109
+ place_order(options)
110
+ end
111
+
112
+ def place_sell_order(options)
113
+ options[:transaction] = 'sell'
114
+ place_order(options)
115
+ end
116
+
117
+ def positions
118
+ url = URI(@api_url + @endpoints[:positions])
119
+ response = http_request(url)
120
+ puts response.read_body
121
+ JSON.parse(response.read_body)
122
+ end
123
+
124
+ def news(symbol)
125
+ url = URI(@api_url + @endpoints[:news] + symbol.to_s + "/")
126
+ response = http_request(url)
127
+ puts response.read_body
128
+ JSON.parse(response.read_body)
129
+ end
130
+
131
+ def markets
132
+ url = URI(@api_url + @endpoints[:markets])
133
+ response = http_request(url)
134
+ puts response.read_body
135
+ JSON.parse(response.read_body)
136
+ end
137
+
138
+ def sp500_up
139
+ url = URI(@api_url + @endpoints[:sp500_up])
140
+ response = http_request(url)
141
+ puts response.read_body
142
+ JSON.parse(response.read_body)
143
+ end
144
+
145
+ def sp500_down
146
+ url = URI(@api_url + @endpoints[:sp500_down])
147
+ response = http_request(url)
148
+ puts response.read_body
149
+ JSON.parse(response.read_body)
150
+ end
151
+
152
+ # def create_watch_list(name, callback)
153
+ # return _request.post({
154
+ # uri: @api_url + @endpoints.watchlists,
155
+ # form: {
156
+ # name: name
157
+ # }
158
+ # }, callback);
159
+ # end
160
+
161
+ def watchlists
162
+ url = URI(@api_url + @endpoints[:watchlists])
163
+ response = http_request(url)
164
+ puts response.read_body
165
+ JSON.parse(response.read_body)
166
+ end
167
+
168
+ def splits(instrument)
169
+ url = URI(@api_url + @endpoints[:instruments] + "/splits/" + instrument.to_s)
170
+ response = http_request(url)
171
+ puts response.read_body
172
+ JSON.parse(response.read_body)
173
+ end
174
+
175
+ def historicals(symbol, intv, span)
176
+ url = URI(@api_url + @endpoints[:quotes] + "historicals/" + symbol + "?interval" + intv.to_s + "&span=" + span)
177
+ response = http_request(url)
178
+ puts response.read_body
179
+ JSON.parse(response.read_body)
180
+ end
181
+ end
182
+
183
+ end
184
+ end
@@ -0,0 +1,120 @@
1
+ module Robinhood
2
+ module REST
3
+ class Client < API
4
+ attr_accessor :token, :api_url, :options, :endpoints, :private
5
+
6
+ def initialize(*args)
7
+ @options = args.last.is_a?(Hash) ? args.pop : {}
8
+
9
+ @options[:username] = args[0] || Robinhood.username
10
+ @options[:password] = args[1] || Robinhood.password
11
+ @options[:username] = (args.size > 2 && args[2].is_a?(String) ? args[2] : args[0]) || Robinhood.username
12
+
13
+ if @options[:username].nil? || @options[:password].nil?
14
+ raise ArgumentError, 'Account username and password are required'
15
+ end
16
+
17
+ configuration
18
+ setup
19
+ end
20
+
21
+ def inspect # :nodoc:
22
+ "<Robinhood::REST::Client @username=#{@options[:username]}>"
23
+ end
24
+
25
+ ##
26
+ # Delegate account methods from the client. This saves having to call
27
+ # <tt>client.account</tt> every time for resources on the default
28
+ # account.
29
+ def method_missing(method_name, *args, &block)
30
+ if account.respond_to?(method_name)
31
+ account.send(method_name, *args, &block)
32
+ else
33
+ super
34
+ end
35
+ end
36
+
37
+ def respond_to?(method_name, include_private=false)
38
+ if account.respond_to?(method_name, include_private)
39
+ true
40
+ else
41
+ super
42
+ end
43
+ end
44
+
45
+ def configuration()
46
+ @api_url = 'https://api.robinhood.com/';
47
+
48
+ @endpoints = {
49
+ "login": 'api-token-auth/',
50
+ "investment_profile": 'user/investment_profile/',
51
+ "accounts": 'accounts/',
52
+ "ach_iav_auth": 'ach/iav/auth/',
53
+ "ach_relationships": 'ach/relationships/',
54
+ "ach_transfers": 'ach/transfers/',
55
+ "ach_deposit_schedules": "ach/deposit_schedules/",
56
+ "applications": 'applications/',
57
+ "dividends": 'dividends/',
58
+ "edocuments": 'documents/',
59
+ "instruments": 'instruments/',
60
+ "margin_upgrade": 'margin/upgrades/',
61
+ "markets": 'markets/',
62
+ "notifications": 'notifications/',
63
+ "notifications_devices": "notifications/devices/",
64
+ "orders": 'orders/',
65
+ "cancel_order": 'orders/', #API expects https://api.robinhood.com/orders/{{orderId}}/cancel/
66
+ "password_reset": 'password_reset/request/',
67
+ "quotes": 'quotes/',
68
+ "document_requests": 'upload/document_requests/',
69
+ "user": 'user/',
70
+
71
+ "user_additional_info": "user/additional_info/",
72
+ "user_basic_info": "user/basic_info/",
73
+ "user_employment": "user/employment/",
74
+ "user_investment_profile": "user/investment_profile/",
75
+
76
+ "watchlists": 'watchlists/',
77
+ "positions": 'positions/',
78
+ "fundamentals": 'fundamentals/',
79
+ "sp500_up": 'midlands/movers/sp500/?direction=up',
80
+ "sp500_down": 'midlands/movers/sp500/?direction=down',
81
+ "news": 'midlands/news/'
82
+ }
83
+
84
+ @is_init = false
85
+
86
+ @private = {
87
+ "session": {},
88
+ "account": nil,
89
+ "username": nil,
90
+ "password": nil,
91
+ "headers": nil,
92
+ "auth_token": nil
93
+ }
94
+
95
+ @api = {}
96
+ end
97
+
98
+ def setup
99
+ @private[:username] = @options[:username];
100
+ @private[:password] = @options[:password];
101
+
102
+ if @private[:auth_token].nil?
103
+ login
104
+ end
105
+ end
106
+
107
+ def http_request(url)
108
+ request = Util::Request.new(@private)
109
+ request.http_request(url)
110
+ end
111
+
112
+ def login
113
+ url = URI(@api_url + "api-token-auth/")
114
+ response = http_request(url)
115
+ @private[:auth_token] = JSON.parse(response.read_body)["token"]
116
+ @private[:account] = account["results"][0]["url"]
117
+ end
118
+ end
119
+ end
120
+ end