beeminder 0.2.10 → 0.2.12

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: fe9446419e3fc9249d45e27dfdb7e93eaa2fd293
4
- data.tar.gz: 940d2b2b7a75f34c276aef94a89d76b2f2624adc
3
+ metadata.gz: d48e75546e891468169cba69c260a9b183a02856
4
+ data.tar.gz: a8bec82ae557bdd48009dd6b8ae96e4bc19f977a
5
5
  SHA512:
6
- metadata.gz: 375ad660e200645afa73bbf18df8b3717b7eb7dc945d7c9985a20bf695239d68b0819acab666bb0ff3bbac8e305dde35a47d714b292144ef6f0700283f4c3be9
7
- data.tar.gz: 620545b90de4a56f0fd4cf785763dfc6a6bd2b0baaf18b6ddaa788461b246d725d011001da4e8907b5653a51cba237331a09f169ead72ceeb12dba4e74562668
6
+ metadata.gz: f4dfdd266db0b8ed2b2a0e7aa8583e497719792351c2d7cb7aeb5fbfbccae9e7beb37b20204dea9ff3a4748b83069bd2b015311c3b0d49e18abb67d4944d1206
7
+ data.tar.gz: 80a2fd645e8762ba2d8f241628db3dffc2b42ec72a102e2505a75eaaf6b012dc929dc33402f9524929a217caa2d7968fb9a906e50c8cba8c31fbf5b1b6f6770c
@@ -6,8 +6,8 @@ require 'beeminder/version'
6
6
  Gem::Specification.new do |gem|
7
7
  gem.name = "beeminder"
8
8
  gem.version = Beeminder::VERSION
9
- gem.authors = ["muflax"]
10
- gem.email = ["mail@muflax.com"]
9
+ gem.authors = ["muflax", "bsoule"]
10
+ gem.email = ["support@beeminder.com"]
11
11
  gem.description = "Convenient access to Beeminder's API."
12
12
  gem.summary = "access Beeminder API"
13
13
  gem.homepage = "https://github.com/beeminder/beeminder-gem"
@@ -16,10 +16,10 @@ Gem::Specification.new do |gem|
16
16
  gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
17
  gem.require_paths = ["lib"]
18
18
 
19
- gem.add_dependency 'activesupport', ['>= 3.2', '< 5']
19
+ gem.add_dependency 'activesupport', ['>= 3.2', '< 6']
20
20
  gem.add_dependency 'chronic', '~> 0.7'
21
- gem.add_dependency 'json'
21
+ gem.add_dependency 'json', '~> 1'
22
22
  gem.add_dependency 'highline', '~> 1.6'
23
- gem.add_dependency 'trollop', '~> 2'
24
- gem.add_dependency 'tzinfo'
23
+ gem.add_dependency 'optimist', '~> 3'
24
+ gem.add_dependency 'tzinfo', '~> 1.2'
25
25
  end
@@ -3,7 +3,7 @@
3
3
 
4
4
  require 'chronic'
5
5
  require 'highline/import'
6
- require 'trollop'
6
+ require 'optimist'
7
7
  require 'yaml'
8
8
 
9
9
  # load library
@@ -18,7 +18,7 @@ else
18
18
  end
19
19
 
20
20
  usage = "usage: beemind goal value [comment]"
21
- opts = Trollop::options do
21
+ opts = Optimist::options do
22
22
  banner usage
23
23
 
24
24
  opt :config, "Path to config.", :type => :string, :default => "~/.beeminderrc"
@@ -27,7 +27,7 @@ opts = Trollop::options do
27
27
  opt :date, "Set a manual date. Uses Chronic syntax.", :type => :string, :default => "now"
28
28
  end
29
29
 
30
- Trollop::die usage if not (2..3).include?(ARGV.size) and not opts[:list]
30
+ Optimist::die usage if not (2..3).include?(ARGV.size) and not opts[:list]
31
31
  goal, value, comment = ARGV unless opts[:list]
32
32
 
33
33
  opts[:config] = File.expand_path opts[:config]
@@ -66,7 +66,7 @@ if opts[:list]
66
66
  end
67
67
  else
68
68
  date = Chronic.parse(opts[:date], :context => :past)
69
- Trollop::die "invalid date" if date.nil?
69
+ Optimist::die "invalid date" if date.nil?
70
70
 
71
71
  g = bee.goal goal
72
72
  dp = Beeminder::Datapoint.new :timestamp => date,
@@ -1,5 +1,6 @@
1
1
  # coding: utf-8
2
2
 
3
+ require 'active_support'
3
4
  require 'active_support/core_ext'
4
5
  require 'date'
5
6
  require 'json'
@@ -59,6 +59,9 @@ module Beeminder
59
59
 
60
60
  # @return [Beeminder::User] User that owns this goal.
61
61
  attr_reader :user
62
+
63
+ # @return [Array<Integer, Float, Float>] All road settings over time
64
+ attr_accessor :roadall
62
65
 
63
66
  def initialize user, name_or_info
64
67
  @user = user
@@ -79,7 +82,7 @@ module Beeminder
79
82
  # Reload data from Beeminder.
80
83
  def reload
81
84
  info = @user.get "users/me/goals/#{@slug}.json"
82
- parse_info info
85
+ _parse_info info
83
86
  end
84
87
 
85
88
  # List of datapoints.
@@ -108,8 +111,9 @@ module Beeminder
108
111
  "secret" => @secret || false,
109
112
  "datapublic" => @datapublic || false,
110
113
  }
114
+ data['roadall'] = @roadall if @roadall
111
115
 
112
- @user.put "users/me/goals/#{@slug}.json", data
116
+ @user.put_document "users/me/goals/#{@slug}.json", data
113
117
  end
114
118
 
115
119
  # Send new road setting to Beeminder.
@@ -126,6 +130,20 @@ module Beeminder
126
130
 
127
131
  @user.post "users/me/goals/#{@slug}/dial_road.json", dials
128
132
  end
133
+
134
+ # Schedule a break.
135
+ # Adds two new entries to `roadall` reflecting the break.
136
+ # Use #update to actually update the goal.
137
+ #
138
+ # @param start_time [Time] when to start the break -- must be after the akrasia horizon
139
+ # @param end_time [Time] when to end the break
140
+ # @param rate [Float] the slope of the road during the break
141
+ def schedule_break start_time, end_time, rate = 0.0
142
+ check_break start_time, end_time
143
+
144
+ roadall.insert(-2, [start_time.to_i, nil, roadall.last.last])
145
+ roadall.insert(-2, [end_time.to_i, nil, rate])
146
+ end
129
147
 
130
148
  # Add one or more datapoints to the goal.
131
149
  #
@@ -172,6 +190,14 @@ module Beeminder
172
190
 
173
191
  private
174
192
 
193
+ def check_break start_time, end_time
194
+ akrasia_horizon = user.akrasia_horizon
195
+ fail ArgumentError, "break start can't be before the akrasia horizon (#{akrasia_horizon})" \
196
+ if start_time < akrasia_horizon
197
+ fail ArgumentError, 'break must start before it ends' \
198
+ unless end_time > start_time
199
+ end
200
+
175
201
  def _parse_info info
176
202
  # set variables
177
203
  info.each do |k,v|
@@ -184,6 +210,9 @@ module Beeminder
184
210
  @losedate = DateTime.strptime(@losedate.to_s, '%s').in_time_zone(@user.timezone) unless @losedate.nil?
185
211
  @updated_at = DateTime.strptime(@updated_at.to_s, '%s').in_time_zone(@user.timezone)
186
212
  @curdate = DateTime.strptime(@curdate.to_s, '%s').in_time_zone(@user.timezone) unless @curdate.nil?
213
+
214
+ # reported data is sometimes malformed like this
215
+ roadall.last[0] = nil if !roadall.nil? && roadall.last[0] == 0
187
216
  end
188
217
  end
189
218
 
@@ -19,13 +19,13 @@ module Beeminder
19
19
 
20
20
  # @return [true|false] Enforce user timezone for all passed times? Should be true unless you know what you're doing. (Default: `true`.)
21
21
  attr_accessor :enforce_timezone
22
-
22
+
23
23
  def initialize token, opts={}
24
24
  opts = {
25
25
  :auth_type => :personal,
26
26
  :enforce_timezone => true,
27
27
  }.merge(opts)
28
-
28
+
29
29
  @token = token
30
30
  @auth_type = opts[:auth_type]
31
31
  @enforce_timezone = opts[:enforce_timezone]
@@ -39,7 +39,7 @@ module Beeminder
39
39
  else
40
40
  raise ArgumentError, "Auth type not supported, must be :personal or :oauth."
41
41
  end
42
-
42
+
43
43
  info = get "users/me.json"
44
44
 
45
45
  @name = info["username"]
@@ -47,13 +47,13 @@ module Beeminder
47
47
  @updated_at = DateTime.strptime(info["updated_at"].to_s, '%s').in_time_zone(@timezone)
48
48
  end
49
49
 
50
- # Enforce timezone for all passed times?
50
+ # Enforce timezone for all passed times?
51
51
  #
52
52
  # @return [true|false]
53
53
  def enforce_timezone?
54
54
  !!@enforce_timezone
55
55
  end
56
-
56
+
57
57
  # List of goals.
58
58
  #
59
59
  # @param filter [Symbol] filter goals, can be `:all` (default), `:frontburner` or `:backburner`
@@ -87,7 +87,7 @@ module Beeminder
87
87
  dp = Beeminder::Datapoint.new :value => value, :comment => comment
88
88
  goal.add dp
89
89
  end
90
-
90
+
91
91
  # Create new goal.
92
92
  #
93
93
  # @param opts [Hash] Goal options.
@@ -127,26 +127,43 @@ module Beeminder
127
127
  _connection :put, cmd, data
128
128
  end
129
129
 
130
+ # Send PUT request with a JSON document to API.
131
+ #
132
+ # @param cmd [String] the API command, like `users/#{user.name}.json`
133
+ # @param data [Hash] data to send
134
+ def put_document cmd, data = {}
135
+ _connection :put_json, cmd, data
136
+ end
137
+
130
138
  # Converts time object to one with user's timezone.
131
139
  #
132
140
  # @param time [Date|DateTime|Time] Time to convert.
133
141
  # @return [Time] Converted time.
134
142
  def convert_to_timezone time
135
143
  Time.use_zone(@timezone){
136
-
144
+
137
145
  time = time.to_time unless time.is_a?(Time)
138
146
  Time.local(time.year, time.month, time.day, time.hour, time.min, time.sec)
139
-
147
+
140
148
  }
141
149
  end
142
150
 
143
- private
151
+ # Returns the current akrasia horizon.
152
+ #
153
+ # @return [Time] The first instant changes can be made for.
154
+ def akrasia_horizon
155
+ Time.use_zone(@timezone) do
156
+ -8.days.ago.beginning_of_day
157
+ end
158
+ end
144
159
 
160
+ private
161
+
145
162
  # Establish HTTPS connection to API.
146
163
  def _connection type, cmd, data
147
164
  api = "https://www.beeminder.com/api/v1/#{cmd}"
148
165
  data = {@token_type => @token}.merge(data)
149
-
166
+
150
167
  url = URI.parse(api)
151
168
  http = Net::HTTP.new(url.host, url.port)
152
169
  http.read_timeout = 8640
@@ -159,7 +176,7 @@ module Beeminder
159
176
  raise ArgumentError, "invalid timestamp: #{data["timestamp"]}"
160
177
  end
161
178
  end
162
-
179
+
163
180
  json = ""
164
181
  http.start do |http|
165
182
  case type
@@ -173,6 +190,10 @@ module Beeminder
173
190
  when :put
174
191
  req = Net::HTTP::Put.new(url.path)
175
192
  req.set_form_data(data)
193
+ when :put_json
194
+ req = Net::HTTP::Put.new(url.path)
195
+ req.body = data.to_json
196
+ req.content_type = 'application/json'
176
197
  else
177
198
  raise "invalid connection type"
178
199
  end
@@ -1,3 +1,3 @@
1
1
  module Beeminder
2
- VERSION = "0.2.10"
2
+ VERSION = "0.2.12"
3
3
  end
metadata CHANGED
@@ -1,34 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: beeminder
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.10
4
+ version: 0.2.12
5
5
  platform: ruby
6
6
  authors:
7
7
  - muflax
8
+ - bsoule
8
9
  autorequire:
9
10
  bindir: bin
10
- cert_chain:
11
- - |
12
- -----BEGIN CERTIFICATE-----
13
- MIIDLDCCAhSgAwIBAgIBATANBgkqhkiG9w0BAQUFADA8MQ0wCwYDVQQDDARtYWls
14
- MRYwFAYKCZImiZPyLGQBGRYGbXVmbGF4MRMwEQYKCZImiZPyLGQBGRYDY29tMB4X
15
- DTE0MDMxNzA1NTUwM1oXDTE1MDMxNzA1NTUwM1owPDENMAsGA1UEAwwEbWFpbDEW
16
- MBQGCgmSJomT8ixkARkWBm11ZmxheDETMBEGCgmSJomT8ixkARkWA2NvbTCCASIw
17
- DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMBwn+ZDlWYfoEevtvoQBKK+NBFA
18
- U9iKN5Aa4g51ZjiFUtoasYeTVUvqKmkRDM+tFTjlTNRCMtFKZy+Fbw+Q2+JALBnk
19
- isyJmRCxoWLxUds/XT40I0m+mtwP5etKr7g01lE3gsIM8644iEBGw41pG7F8nm2w
20
- dxcs78uGx/Y89vH4xlP5utdq4lChCo60+jQWUBNdnRlrFoBerUrdEUWlj7HhOQSl
21
- coJqx3UHhPw1e97CxC4r4IEO4vfNwMr3Uxxcv/idcQwDi5thDwtzjG3u4xwzL3xS
22
- HSvktDccLmeF9hsWUGlmee87oQGqZvZTmRmLmpcpzsNxFcVJxGK72VfbsjUCAwEA
23
- AaM5MDcwCQYDVR0TBAIwADALBgNVHQ8EBAMCBLAwHQYDVR0OBBYEFEEiWHZRn5hp
24
- 8ho98JIewpJitn3DMA0GCSqGSIb3DQEBBQUAA4IBAQCFr4wcczJG+SkvzaP+LPaB
25
- PyDf6lhOYB5BbxteVc3qoK1bxOhMKRlzl9k5pzKbd8FCAokhojoPvUFkZuB7E2RB
26
- VC1cDAdYr7s8CCNnUjH1nk3esXRyXGWBBTOlAc96SmbukEV+qVdf2CWnRRHxDtyZ
27
- Ov/8JRksnmBUhPzUgAxsEZaX3eSLv/cJGjnOeEgNKA52FmY6S1/MNkLN743AXFfR
28
- njhyNen7eGs/8Og1krIw4crmFCVawKI0LXuWTff/3zb8d9SZXZePbzPv+q0IG3ek
29
- lmwpPc3Bdi/+i0PzT69bN5W+96Yp2JUDPmQXTG2QGwWDqEQF/BnHtlVQ/1w649V+
30
- -----END CERTIFICATE-----
31
- date: 2014-04-21 00:00:00.000000000 Z
11
+ cert_chain: []
12
+ date: 2018-09-27 00:00:00.000000000 Z
32
13
  dependencies:
33
14
  - !ruby/object:Gem::Dependency
34
15
  name: activesupport
@@ -39,7 +20,7 @@ dependencies:
39
20
  version: '3.2'
40
21
  - - "<"
41
22
  - !ruby/object:Gem::Version
42
- version: '5'
23
+ version: '6'
43
24
  type: :runtime
44
25
  prerelease: false
45
26
  version_requirements: !ruby/object:Gem::Requirement
@@ -49,7 +30,7 @@ dependencies:
49
30
  version: '3.2'
50
31
  - - "<"
51
32
  - !ruby/object:Gem::Version
52
- version: '5'
33
+ version: '6'
53
34
  - !ruby/object:Gem::Dependency
54
35
  name: chronic
55
36
  requirement: !ruby/object:Gem::Requirement
@@ -68,16 +49,16 @@ dependencies:
68
49
  name: json
69
50
  requirement: !ruby/object:Gem::Requirement
70
51
  requirements:
71
- - - ">="
52
+ - - "~>"
72
53
  - !ruby/object:Gem::Version
73
- version: '0'
54
+ version: '1'
74
55
  type: :runtime
75
56
  prerelease: false
76
57
  version_requirements: !ruby/object:Gem::Requirement
77
58
  requirements:
78
- - - ">="
59
+ - - "~>"
79
60
  - !ruby/object:Gem::Version
80
- version: '0'
61
+ version: '1'
81
62
  - !ruby/object:Gem::Dependency
82
63
  name: highline
83
64
  requirement: !ruby/object:Gem::Requirement
@@ -93,36 +74,36 @@ dependencies:
93
74
  - !ruby/object:Gem::Version
94
75
  version: '1.6'
95
76
  - !ruby/object:Gem::Dependency
96
- name: trollop
77
+ name: optimist
97
78
  requirement: !ruby/object:Gem::Requirement
98
79
  requirements:
99
80
  - - "~>"
100
81
  - !ruby/object:Gem::Version
101
- version: '2'
82
+ version: '3'
102
83
  type: :runtime
103
84
  prerelease: false
104
85
  version_requirements: !ruby/object:Gem::Requirement
105
86
  requirements:
106
87
  - - "~>"
107
88
  - !ruby/object:Gem::Version
108
- version: '2'
89
+ version: '3'
109
90
  - !ruby/object:Gem::Dependency
110
91
  name: tzinfo
111
92
  requirement: !ruby/object:Gem::Requirement
112
93
  requirements:
113
- - - ">="
94
+ - - "~>"
114
95
  - !ruby/object:Gem::Version
115
- version: '0'
96
+ version: '1.2'
116
97
  type: :runtime
117
98
  prerelease: false
118
99
  version_requirements: !ruby/object:Gem::Requirement
119
100
  requirements:
120
- - - ">="
101
+ - - "~>"
121
102
  - !ruby/object:Gem::Version
122
- version: '0'
103
+ version: '1.2'
123
104
  description: Convenient access to Beeminder's API.
124
105
  email:
125
- - mail@muflax.com
106
+ - support@beeminder.com
126
107
  executables:
127
108
  - beemind
128
109
  extensions: []
@@ -160,7 +141,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
160
141
  version: '0'
161
142
  requirements: []
162
143
  rubyforge_project:
163
- rubygems_version: 2.2.2
144
+ rubygems_version: 2.6.12
164
145
  signing_key:
165
146
  specification_version: 4
166
147
  summary: access Beeminder API
@@ -1,2 +0,0 @@
1
- �do�K�湷M����$�V�qD/�
2
- �\oQ��4deu��νbJ'��+t�7M;"�`*��[5�
data.tar.gz.sig DELETED
Binary file
metadata.gz.sig DELETED
@@ -1 +0,0 @@
1
- ��mj<���Q]0H�+_��� V��<�N]n�+���S��