slimtimer4r 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/History.txt ADDED
@@ -0,0 +1,9 @@
1
+ == 0.2.0 / 2008-01-09
2
+
3
+ * 1 major enhancement
4
+ * Not-so-ugly code thanks to borrowing from the 37 Signals / Basecamp sample Ruby wrappers
5
+
6
+ == 0.1.0 / Sometime back in 2006...
7
+
8
+ * Lots of UGLY code
9
+
data/Manifest.txt ADDED
@@ -0,0 +1,7 @@
1
+ History.txt
2
+ Manifest.txt
3
+ README.txt
4
+ Rakefile
5
+ bin/slimtimer4r
6
+ lib/slimtimer4r.rb
7
+ test/test_slimtimer4r.rb
data/README.txt ADDED
@@ -0,0 +1,51 @@
1
+ == SlimTimer4R
2
+
3
+ == Overview
4
+
5
+ A basic wrapper against the SlimTimer (www.slimtimer.com) API.
6
+
7
+ == Installation
8
+
9
+ RubyGems FTW!
10
+
11
+ sudo gem install slimtimer4r
12
+
13
+ == Usage
14
+
15
+ require 'slimtimer4r'
16
+
17
+ slimtimer = SlimTimer.new("EMAIL", "PASSWORD", "API_KEY")
18
+ tasks = slimtimer.list_tasks
19
+ => [#<Record(Task) "name"=>"Ta...">, #<Record(Task) "name"=>"Br...">...]
20
+
21
+ == Thanks
22
+ - 37 Signals for their sample Backpack/Basecamp Ruby wrappers
23
+
24
+ == Author
25
+ - Dylan Markow (dylan@dylanmarkow.com)
26
+
27
+
28
+ == License
29
+
30
+ (The MIT License)
31
+
32
+ Copyright (c) 2008
33
+
34
+ Permission is hereby granted, free of charge, to any person obtaining
35
+ a copy of this software and associated documentation files (the
36
+ 'Software'), to deal in the Software without restriction, including
37
+ without limitation the rights to use, copy, modify, merge, publish,
38
+ distribute, sublicense, and/or sell copies of the Software, and to
39
+ permit persons to whom the Software is furnished to do so, subject to
40
+ the following conditions:
41
+
42
+ The above copyright notice and this permission notice shall be
43
+ included in all copies or substantial portions of the Software.
44
+
45
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
46
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
47
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
48
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
49
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
50
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
51
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,18 @@
1
+ # -*- ruby -*-
2
+
3
+ require 'rubygems'
4
+ require 'hoe'
5
+ require './lib/slimtimer4r.rb'
6
+
7
+ Hoe.new('slimtimer4r', SlimTimer::VERSION) do |p|
8
+ p.rubyforge_name = 'slimtimer4r'
9
+ p.author = 'Dylan Markow'
10
+ p.email = 'dylan@dylanmarkow.com'
11
+ p.remote_rdoc_dir = ''
12
+ # p.summary = 'FIX'
13
+ # p.description = p.paragraphs_of('README.txt', 2..5).join("\n\n")
14
+ # p.url = p.paragraphs_of('README.txt', 0).first.split(/\n/)[1..-1]
15
+ p.changes = p.paragraphs_of('History.txt', 0..1).join("\n\n")
16
+ end
17
+
18
+ # vim: syntax=Ruby
data/bin/slimtimer4r ADDED
File without changes
@@ -0,0 +1,207 @@
1
+ require 'yaml'
2
+ require 'net/http'
3
+
4
+ class SlimTimer
5
+ VERSION = '0.2.0'
6
+
7
+ #
8
+ # The Record class is used to encapsulate the data returned from the SlimTimer API
9
+ class Record
10
+ attr_reader :type, :hash
11
+
12
+ def initialize(type, hash)
13
+ @type = type
14
+ @hash = hash
15
+ end
16
+
17
+ # Checks to see if one of the values of the hash is another hash, and if so, changes it to a Record object. This allows you to use time_entry.task.name instead of time_entry.task["name"]
18
+ def [](name)
19
+ case @hash[name]
20
+ when Hash then
21
+ @hash[name] = (@hash[name].keys.length == 1 && Array === @hash[name].values.first) ? @hash[name].values.first.map { |v| Record.new(@hash[name].keys.first, v) } : Record.new(name, @hash[name])
22
+ else
23
+ @hash[name]
24
+ end
25
+ end
26
+
27
+ def id
28
+ @hash["id"]
29
+ end
30
+
31
+ def attributes
32
+ @hash.keys
33
+ end
34
+
35
+ def respond_to?(sym)
36
+ super || @hash.has_key?(sym)
37
+ end
38
+
39
+ # Used to convert an unknown method into a hash key. For example, item.user_id would become item["user_id"]
40
+ def method_missing(sym, *args)
41
+ if args.empty? && !block_given? && respond_to?(sym.to_s)
42
+ self[sym.to_s]
43
+ else
44
+ super
45
+ end
46
+ end
47
+
48
+ def to_s
49
+ "\#<Record(#{@type}) #{@hash.inspect[1..-2]}>"
50
+ end
51
+
52
+ def inspect
53
+ to_s
54
+ end
55
+
56
+ private
57
+
58
+ def dashify(name)
59
+ name.to_s.tr("_","-")
60
+ end
61
+ end
62
+
63
+ attr_accessor :email, :password, :api_key, :user_id, :access_token, :request
64
+
65
+ # Creates a new SlimTimer object and obtains the +access_token+ and +user_id+ from the SlimTimer API by sending your +email+, +password+, and +api_key+. Raises a _RuntimeError_ if it can't authenticate.
66
+ #
67
+ # slim_timer = SlimTimer.new("person@example.com", "password", "12345")
68
+ # => #<SlimTimer:0x68bca8 @password="password"...>
69
+ #
70
+ # slim_timer = SlimTimer.new("bademail@example.com", "badpassword", "12345")
71
+ # => RuntimeError: Error occurred (500)
72
+ def initialize(email, password, api_key)
73
+ @email, @password, @api_key = email, password, api_key
74
+ connect
75
+ get_token
76
+ end
77
+
78
+ # Returns a list of tasks.
79
+ #
80
+ # Options:
81
+ # <tt>show_completed</tt>:: Include completed tasks. Specify +only+ to only include the completed tasks. Valid options are +yes+, +no+, and +only+. Default is +yes+.
82
+ # <tt>role</tt>:: Include tasks where the user's role is one of the roles given (comma delimited). Valid options include +owner+, +coworker+, and +reporter+. Default is +owner,coworker+.
83
+ def list_tasks(show_completed="yes", role="owner,coworker")
84
+ request("get", "#{@user_id}/tasks?api_key=#{@api_key}&access_token=#{@access_token}&show_completed=#{show_completed}&role=#{role}", "Tasks")
85
+ end
86
+
87
+ # Returns a specific task. Returns _nil_ if the record is not found.
88
+ #
89
+ # Options:
90
+ # <tt>task_id</tt>:: The id of the task you would like to retrieve.
91
+ def show_task(task_id)
92
+ request("get", "#{@user_id}/tasks/#{task_id}?api_key=#{@api_key}&access_token=#{@access_token}", "Task")
93
+ end
94
+
95
+ def delete_task(task_id)
96
+ request("delete", "#{@user_id}/tasks/#{task_id}?api_key=#{@api_key}&access_token=#{@access_token}", "Task")
97
+ end
98
+
99
+ def create_task(name, tags=nil, coworker_emails=nil, reporter_emails=nil, completed_on=nil)
100
+ request("post", "#{@user_id}/tasks", {"access_token" => @access_token, "api_key" => @api_key, "task" => {"name" => name, "tags" => tags, "coworker_emails" => coworker_emails, "reporter_emails" => reporter_emails, "completed_on" => completed_on}}, "Task")
101
+ end
102
+
103
+ def update_task(task_id, name, tags=nil, coworker_emails=nil, reporter_emails=nil, completed_on=nil)
104
+ request("put", "#{@user_id}/tasks/#{task_id}", {"access_token" => @access_token, "api_key" => @api_key, "task" => {"name" => name, "tags" => tags, "coworker_emails" => coworker_emails, "reporter_emails" => reporter_emails, "completed_on" => completed_on}}, "Task")
105
+ end
106
+
107
+ def list_timeentries(range_start=nil, range_end=nil)
108
+ range_start = range_start.strftime("%Y-%m-%dT%H:%M:%SZ") unless range_start.nil?
109
+ range_end = range_end.strftime("%Y-%m-%dT%H:%M:%SZ") unless range_end.nil?
110
+ request("get", "#{@user_id}/time_entries?api_key=#{@api_key}&access_token=#{@access_token}&range_start=#{range_start}&range_end=#{range_end}", "TimeEntries")
111
+ end
112
+
113
+ def update_timeentry(timeentry_id, start_time, duration_in_seconds, task_id, end_time, tags=nil, comments=nil, in_progress=nil)
114
+ start_time = start_time.strftime("%Y-%m-%dT%H:%M:%SZ")
115
+ end_time = end_time.strftime("%Y-%m-%dT%H:%M:%SZ") unless end_time.nil?
116
+
117
+ # add the default params
118
+ params = {
119
+ "start_time" => start_time,
120
+ "duration_in_seconds" => duration_in_seconds,
121
+ "task_id" => task_id,
122
+ "end_time" => end_time,
123
+ }
124
+
125
+ # only add the applicable params
126
+ params.merge!({"tags" => tags}) unless tags.nil?
127
+ params.merge!({"comments" => comments}) unless comments.nil?
128
+ params.merge!({"in_progress" => in_progress}) unless in_progress.nil?
129
+
130
+
131
+ request("put", "#{@user_id}/time_entries/#{timeentry_id}", {"access_token" => @access_token, "api_key" => @api_key, "time_entry" => params}, "TimeEntry")
132
+ end
133
+
134
+ def create_timeentry(start_time, duration_in_seconds, task_id, end_time, tags=nil, comments=nil, in_progress=nil)
135
+ start_time = start_time.strftime("%Y-%m-%dT%H:%M:%SZ")
136
+ end_time = end_time.strftime("%Y-%m-%dT%H:%M:%SZ") unless end_time.nil?
137
+
138
+ # add the default params
139
+ params = {
140
+ "start_time" => start_time,
141
+ "duration_in_seconds" => duration_in_seconds,
142
+ "task_id" => task_id,
143
+ "end_time" => end_time,
144
+ }
145
+
146
+ # only add the applicable params
147
+ params.merge!({"tags" => tags}) unless tags.nil?
148
+ params.merge!({"comments" => comments}) unless comments.nil?
149
+ params.merge!({"in_progress" => in_progress}) unless in_progress.nil?
150
+
151
+
152
+ request("post", "#{@user_id}/time_entries", {"access_token" => @access_token, "api_key" => @api_key, "time_entry" => params}, "TimeEntry")
153
+ end
154
+
155
+ def show_timeentry(timeentry_id)
156
+ request("get", "#{@user_id}/time_entries/#{timeentry_id}?api_key=#{@api_key}&access_token=#{@access_token}", "TimeEntry")
157
+ end
158
+
159
+ def delete_timeentry(timeentry_id)
160
+ request("delete", "#{@user_id}/time_entries/#{timeentry_id}?api_key=#{@api_key}&access_token=#{@access_token}", "TimeEntry")
161
+ end
162
+
163
+
164
+ private
165
+ def get_token
166
+ values = request("post", "token", {"user" => {"email" => @email, "password" => @password}, "api_key" => @api_key})
167
+ @access_token = values.access_token
168
+ @user_id = values.user_id
169
+ end
170
+
171
+ def connect
172
+ @connection = Net::HTTP.new("www.slimtimer.com", 80)
173
+ end
174
+
175
+ def request(method, path, parameters = {}, type="Result")
176
+ method.downcase!
177
+ if !['post','get','delete','put'].include?(method)
178
+ raise "Error: bad method parameter"
179
+ end
180
+ if %w(get delete).include?(method)
181
+ response = @connection.send(method, "/users/#{path}", {"Accept" => "application/x-yaml"})
182
+ else
183
+ response = @connection.send(method, "/users/#{path}", parameters.to_yaml, {"Content-Type" => "application/x-yaml", "Accept" => "application/x-yaml"})
184
+ end
185
+
186
+ if response.code == "200"
187
+
188
+ # If this was a delete request, return true
189
+ if method == 'delete'
190
+ true
191
+ else
192
+ result = YAML::load(response.body)
193
+ if result.is_a?(Array)
194
+ result.map { |row| Record.new(type, row) }
195
+ else
196
+ Record.new(type, result)
197
+ end
198
+ end
199
+ elsif response.code == "404"
200
+ method == 'get' ? nil : false
201
+ else
202
+ raise "Error occurred (#{response.code}): #{response.body}"
203
+ end
204
+ end
205
+
206
+ end
207
+
File without changes
metadata ADDED
@@ -0,0 +1,70 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: slimtimer4r
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.0
5
+ platform: ruby
6
+ authors:
7
+ - Dylan Markow
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2008-01-09 00:00:00 -08:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: hoe
17
+ version_requirement:
18
+ version_requirements: !ruby/object:Gem::Requirement
19
+ requirements:
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 1.4.0
23
+ version:
24
+ description: The author was too lazy to write a description
25
+ email: dylan@dylanmarkow.com
26
+ executables:
27
+ - slimtimer4r
28
+ extensions: []
29
+
30
+ extra_rdoc_files:
31
+ - History.txt
32
+ - Manifest.txt
33
+ - README.txt
34
+ files:
35
+ - History.txt
36
+ - Manifest.txt
37
+ - README.txt
38
+ - Rakefile
39
+ - bin/slimtimer4r
40
+ - lib/slimtimer4r.rb
41
+ - test/test_slimtimer4r.rb
42
+ has_rdoc: true
43
+ homepage: http://www.zenspider.com/ZSS/Products/slimtimer4r/
44
+ post_install_message:
45
+ rdoc_options:
46
+ - --main
47
+ - README.txt
48
+ require_paths:
49
+ - lib
50
+ required_ruby_version: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: "0"
55
+ version:
56
+ required_rubygems_version: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: "0"
61
+ version:
62
+ requirements: []
63
+
64
+ rubyforge_project: slimtimer4r
65
+ rubygems_version: 1.0.1
66
+ signing_key:
67
+ specification_version: 2
68
+ summary: The author was too lazy to write a summary
69
+ test_files:
70
+ - test/test_slimtimer4r.rb