ruby_desk 0.7.0 → 0.8.0

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.
data/README.rdoc CHANGED
@@ -6,6 +6,8 @@ A gem built by BadrIT (www.badrit.com) that works as an interface for oDesk APIs
6
6
  If you want to use oDesk APIs with Rails applications you may better use ror_desk.
7
7
  ror_desk is a plugin built on Ruby Desk and makes it much easier to use with Rails.
8
8
 
9
+ For more information read the documentation at http://aseldawy.github.com/ruby_desk/
10
+
9
11
  == Example
10
12
  Initialize with your api key
11
13
  rd = RubyDesk::Connector.new(api_key, api_secret)
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.7.0
1
+ 0.8.0
@@ -6,6 +6,8 @@ require 'rexml/document'
6
6
  require 'json'
7
7
 
8
8
  module RubyDesk
9
+ # Basic methods used for connecting with oDesk like signing request parameters and parsing response.
10
+ # This class is also responsible for authorizing user
9
11
  class Connector
10
12
  ODESK_URL = "www.odesk.com/"
11
13
  ODESK_API_URL = "#{ODESK_URL}api/"
@@ -15,6 +17,7 @@ module RubyDesk
15
17
  :base_url=>ODESK_API_URL, :auth=>true}
16
18
 
17
19
  attr_writer :frob
20
+ attr_accessor :auth_user
18
21
 
19
22
  def initialize(api_key=nil, api_secret=nil, api_token=nil)
20
23
  @api_key = api_key
@@ -76,7 +79,8 @@ module RubyDesk
76
79
  http = Net::HTTP.new(url.host, url.port)
77
80
  http.use_ssl = true
78
81
 
79
- data = api_call[:params].to_a.map{|pair| pair.join '='}.join('&')
82
+ # Concatenate parameters to form data
83
+ data = api_call[:params].to_a.map{|pair| pair.map{|x| URI.escape(x.to_s)}.join '='}.join('&')
80
84
  headers = {
81
85
  'Content-Type' => 'application/x-www-form-urlencoded'
82
86
  }
@@ -99,9 +103,11 @@ module RubyDesk
99
103
 
100
104
  case resp.code
101
105
  when "200" then return data
102
- when "401" then raise RubyDesk::UnauthorizedError, data
106
+ when "400" then raise RubyDesk::BadRequest, data
107
+ when "401", "403" then raise RubyDesk::UnauthorizedError, data
103
108
  when "404" then raise RubyDesk::PageNotFound, data
104
109
  when "500" then raise RubyDesk::ServerError, data
110
+ else raise RubyDesk::Error, data
105
111
  end
106
112
 
107
113
  end
@@ -131,7 +137,7 @@ module RubyDesk
131
137
  # return the URL that logs user out of odesk applications
132
138
  def logout_url
133
139
  logout_call = prepare_api_call("", :base_url=>ODESK_AUTH_URL,
134
- :secure=>false, :auth=>false)
140
+ :secure=>false, :auth=>false, :format=>nil)
135
141
  return logout_call[:url]
136
142
  end
137
143
 
@@ -147,6 +153,7 @@ module RubyDesk
147
153
  json = prepare_and_invoke_api_call 'auth/v1/keys/tokens',
148
154
  :params=>{:frob=>@frob, :api_key=>@api_key}, :method=>:post,
149
155
  :auth=>false
156
+ @auth_user = User.new(json['auth_user'])
150
157
  @api_token = json['token']
151
158
  end
152
159
 
@@ -0,0 +1,215 @@
1
+ # A job opening with the following attributes
2
+ # * adj_score
3
+ # * amount
4
+ # * ciphertext
5
+ # * country
6
+ # * create_date
7
+ # * engagement_weeks
8
+ # * hours_per_week
9
+ # * job_category_level_one
10
+ # * job_category_level_two
11
+ # * job_type
12
+ # * op_adjusted_score
13
+ # * op_amount
14
+ # * op_buyer_ace
15
+ # * op_city
16
+ # * op_company_name
17
+ # * op_contract_date
18
+ # * op_country
19
+ # * op_date_created
20
+ # * op_description
21
+ # * op_eng_duration
22
+ # * op_hrs_per_week
23
+ # * op_job
24
+ # * op_job_category_
25
+ # * op_job_type
26
+ # * op_num_of_pending_invites
27
+ # * op_pref_english_skill
28
+ # * op_pref_fb_score
29
+ # * op_pref_hourly_rate
30
+ # * op_pref_odesk_hours
31
+ # * op_pref_test
32
+ # * op_pref_test_name
33
+ # * op_recno
34
+ # * op_required_skills
35
+ # * op_status_for_search
36
+ # * op_title
37
+ # * op_tot_asgs
38
+ # * op_tot_cand
39
+ # * op_tot_cand_client
40
+ # * op_tot_cand_prof
41
+ # * op_tot_feedback
42
+ # * op_tot_fp_asgs
43
+ # * op_tot_fp_charge
44
+ # * op_tot_hours
45
+ # * op_tot_hr_asgs
46
+ # * op_tot_hr_charge
47
+ # * op_tot_intv
48
+ # * op_tot_jobs_filled
49
+ # * op_tot_jobs_posted
50
+ # * record_id
51
+ # * search_status
52
+ # * timezone
53
+ # * total_billed_assignments
54
+ # * total_charge
55
+ # * total_hours
56
+ class RubyDesk::Job < RubyDesk::OdeskEntity
57
+ attributes :op_tot_hours, :job_category_level_two, :op_company_name,
58
+ :op_tot_cand_client, :record_id, :op_amount, :total_hours,
59
+ :op_date_created, :op_city, :country, :op_tot_intv, :op_tot_feedback,
60
+ :search_status, :op_job, :op_hrs_per_week, :op_job_category_, :op_country,
61
+ :amount, :op_tot_cand_prof, :op_tot_asgs, :total_charge,
62
+ :op_status_for_search, :op_tot_cand, :op_buyer_ace,
63
+ :job_category_level_one, :timezone, :op_pref_test, :adj_score,
64
+ :op_num_of_pending_invites, :op_tot_fp_asgs, :op_required_skills,
65
+ :ciphertext, :op_title, :op_pref_fb_score, :op_tot_hr_asgs, :create_date,
66
+ :op_tot_jobs_filled, :op_pref_hourly_rate, :op_tot_jobs_posted,
67
+ :job_type, :hours_per_week, :op_job_type, :op_pref_test_name,
68
+ :op_pref_english_skill, :op_pref_odesk_hours, :op_tot_fp_charge,
69
+ :op_contract_date, :op_tot_hr_charge, :engagement_weeks,
70
+ :op_adjusted_score, :op_recno, :total_billed_assignments,
71
+ :op_description, :op_eng_duration
72
+
73
+ # <h2>Details on Search Parameters</h2>
74
+ # <p>&nbsp;</p>
75
+ # <ul>
76
+ # <li><b>q -</b> OpeningData<b>&nbsp;</b>(Opening Data)
77
+ #
78
+ # <ul>
79
+ # <li>Search the text of the job description</li>
80
+ # </ul>
81
+ # </li>
82
+ # <li><b>c1 -</b> JobCategory<b>&nbsp;(</b>Level One Job Category)
83
+ # <ul>
84
+ # <li>Limit your search to a specific <a href="/all-categories">category</a></li>
85
+ # </ul>
86
+ # </li>
87
+ # <li><b>c2 -</b> second_category<b>&nbsp;</b>(Second Level Job Category)
88
+ #
89
+ # <ul>
90
+ # <li>Limit your search to a specific <a href="/all-categories">sub-category</a>
91
+ # <ul>
92
+ # <li>You must use a level one category in order to use a second level category.</li>
93
+ # </ul>
94
+ # </li>
95
+ # </ul>
96
+ # </li>
97
+ # <li><b>fb -</b> adjusted_score<b>&nbsp;</b>(Adjusted Score)
98
+ # <ul>
99
+ # <li>Limit your search to buyers with at least a score of the number passed in this parameter.
100
+ #
101
+ # <ul>
102
+ # <li>This number must be <strong>5</strong> or less</li>
103
+ # </ul>
104
+ # </li>
105
+ # </ul>
106
+ # </li>
107
+ # <li><b>min -</b> min_budget<b>&nbsp;</b>(Min Budget)
108
+ # <ul>
109
+ # <li>Limit your search to jobs with a budget greater than this number.</li>
110
+ #
111
+ # </ul>
112
+ # </li>
113
+ # <li><b>max -</b> max_budget<b>&nbsp;</b>(Max Budget)
114
+ # <ul>
115
+ # <li>Limit your search to jobs with a budget less than this number.</li>
116
+ # </ul>
117
+ # </li>
118
+ # <li><b>t -</b> JobType<b>&nbsp;</b>(Job Type)
119
+ # <ul>
120
+ # <li>oDesk has both hourly jobs and fixed prices jobs. This parameter allows you to limit your search to one or the other.
121
+ #
122
+ # <ul>
123
+ # <li>Hourly Jobs = '<strong>Hourly</strong>'</li>
124
+ # <li>Fixed Priced Jobs = '<strong>Fixed</strong>'</li>
125
+ # </ul>
126
+ # </li>
127
+ # <li><strong>wl -</strong> hours_per_week(Hours per Week)
128
+ # <ul>
129
+ # <li>This parameter can only be used when searching Hourly jobs. These numbers are a little arbitrary, so follow the following parameters in order to successfully use this parameter:
130
+ # <ul>
131
+ #
132
+ # <li>
133
+ # <p>As Needed &lt; 10 Hours/Week = '<strong>0</strong>'</p>
134
+ # </li>
135
+ # <li>
136
+ # <p>Part Time: 10-30 hrs/week = '<strong>20</strong>'</p>
137
+ # </li>
138
+ # <li>Full Time: 30+ hrs/week = '<strong>40</strong>'</li>
139
+ #
140
+ # </ul>
141
+ # </li>
142
+ # </ul>
143
+ # </li>
144
+ # <li><b>dur -</b> engagement_duration<b>&nbsp;</b>(Engagement Duration)
145
+ # <ul>
146
+ # <li>This parameter can only be used when searching Hourly jobs. These numbers are a little arbitrary, so follow the following parameters in order to successfully use this parameter:
147
+ # <ul>
148
+ # <li>Ongoing / More than 6 months = '<strong>1</strong>'</li>
149
+ # <li>3 to 6 months = '<strong>2</strong>'</li>
150
+ #
151
+ # <li>1 to 3 months = '<strong>3</strong>'</li>
152
+ # <li>Less than 1 month = '<strong>4</strong>'</li>
153
+ # <li>Less than 1 week = '<strong>5</strong>'</li>
154
+ # </ul>
155
+ # </li>
156
+ # </ul>
157
+ # </li>
158
+ # </ul>
159
+ #
160
+ # </li>
161
+ # <li><b>dp -</b> Date_Posted<b>&nbsp;</b><strong>(</strong>Date Posted)
162
+ # <ul>
163
+ # <li>Search jobs posted after this date.
164
+ # <ul>
165
+ # <li>Format for date: <em>07-22-2009</em></li>
166
+ # </ul>
167
+ # </li>
168
+ # </ul>
169
+ # </li>
170
+ # <li><b>st -</b> status_for_search<b>&nbsp;</b>(Status for Search)
171
+ #
172
+ # <ul>
173
+ # <li>Search Canceled jobs, In Progress Jobs and Completed Jobs: By default this default to Open Jobs
174
+ # <ul>
175
+ # <li>Open Jobs = '<strong>Open</strong>'</li>
176
+ # <li>Jobs in Progress = '<strong>In Progress</strong>'</li>
177
+ # <li>Completed Jobs = '<strong>Completed</strong>'</li>
178
+ # <li>Canceled Jobs = '<strong>Cancelled</strong>'</li>
179
+ #
180
+ # </ul>
181
+ # </li>
182
+ # </ul>
183
+ # </li>
184
+ # <li><strong>tba</strong> - total_billed_assignments<b>&nbsp;</b>(Total Billed Assignments)
185
+ # <ul>
186
+ # <li>Limit your search to buyers who completed at least this number of paid assignments
187
+ # <ul>
188
+ # <li>For example tb=5 searches buyers who have at least 5 billed assignments</li>
189
+ # </ul>
190
+ # </li>
191
+ # </ul>
192
+ # </li>
193
+ #
194
+ # <li><strong>gr</strong> -&nbsp;PrefGroup(Preferred Group)providers
195
+ # <ul>
196
+ # <li>Limits your search to buyers in a particular group</li>
197
+ # </ul>
198
+ # </li>
199
+ # <li><strong>to</strong> - titles_only<b>&nbsp;</b>(titles only)
200
+ # <ul>
201
+ # <li>Limits your search to job titles only. (you should be able to combine this search)</li>
202
+ def self.search(connector, query_options={})
203
+ if query_options.respond_to? :to_str
204
+ return search(connector, :q=>query_options.to_str)
205
+ end
206
+ json = connector.prepare_and_invoke_api_call(
207
+ 'profiles/v1/search/jobs', :method=>:get,
208
+ :auth=>false, :sign=>false, :params=>query_options)
209
+ jobs = []
210
+ [json['jobs']['job']].flatten.each do |job|
211
+ jobs << self.new(job)
212
+ end
213
+ return jobs
214
+ end
215
+ end
@@ -2,6 +2,46 @@ class RubyDesk::OdeskEntity
2
2
  @@complex_attributes = {}
3
3
 
4
4
  class << self
5
+ # Defines a new attribute or multiple attributes to this class.
6
+ # Allowed options:
7
+ # * class: The class used to initialize this attribute
8
+ # * sub_element: Indicates this is an array. Name of the key used to initialize this attribute.
9
+ #
10
+ # Here are some examples of how to use this method
11
+ # class Project
12
+ # # Defines a new attribute called 'name'.
13
+ # # This is generally used for defining simple attributes such as String or integer
14
+ # attribute :name
15
+ #
16
+ # # Defines two attributes called 'description' and 'priority'.
17
+ # attributes :description, :priority
18
+ # # The same effect can be accomplished by calling
19
+ # attribute :description
20
+ # attribute :priority
21
+ #
22
+ # # Defines an attribute called 'manager' of class User
23
+ # # This class is used to initialize this attribute as we will see later
24
+ # attribute :manager, :class=>User
25
+ #
26
+ # # Defines an attribute called 'tasks' which is an array of type Task
27
+ # attribute :tasks, :class=>Task, :sub_element=>"tasks"
28
+ # end
29
+ #
30
+ # Initialization
31
+ # ==============
32
+ # The above class Project can be initialized like this
33
+ # # An instance of class Project all attributes set to nil
34
+ # Project.new
35
+ #
36
+ # # Initialize simple attributes with the given values
37
+ # Project.new :name=>"GitHub project", :description=>"Sample project on git hub"
38
+ #
39
+ # # Initialize complex attribute
40
+ # # This will initialize manager with: User.new(:name=>"Ahmed", :birthday=>Date.parse("3/3/1983"))
41
+ # Project.new :manager=>{:name=>"Ahmed", :birthday=>Date.parse("3/3/1983")}
42
+ #
43
+ # # Initializes 'tasks' attribute with [Task.new(:name=>"task1", Task.new(:name=>"task2", :priority=>3}]
44
+ # Project.new :tasks=>[{:name=>"task1"}, {:name=>"task2", :priority=>3}]
5
45
  def attribute(*att_names)
6
46
  options = nil
7
47
  if att_names.last.is_a?Hash
@@ -16,7 +56,18 @@ class RubyDesk::OdeskEntity
16
56
  alias attributes attribute
17
57
  end
18
58
 
19
-
59
+
60
+ # Creates a new object of this class
61
+ # Initial values of attributes is passed as a paramter
62
+ # * params: A hash used to initialize this object.
63
+ # The key is the name of the attribute to initialize.
64
+ # The value is used as the initial value for this attribute.
65
+ # If the attribute is defined a class in creation,
66
+ # the value is used as an initialization parameter with this class.
67
+ # If the attribute is marked as "sub_element" in creation,
68
+ # the value is assumed to be an array.
69
+ # Each entry in the array is used as an initialization parameter to create a new element.
70
+ # If the value is not an array, it is used to create an array of single element.
20
71
  def initialize(params={})
21
72
  params.each do |k, v|
22
73
  attribute_options = @@complex_attributes[k.to_s] || {}
@@ -34,7 +85,7 @@ class RubyDesk::OdeskEntity
34
85
  end
35
86
  end
36
87
  else
37
- # This attribute is a single comple attribute
88
+ # This attribute is a single complex attribute
38
89
  self.instance_variable_set("@#{k}", attribute_options[:class].new(v))
39
90
  end
40
91
  else
@@ -1,3 +1,126 @@
1
+ # A provider in oDesk.
2
+ # <p>There is a TON&nbsp;of info returned here and the best way to see what this actually means is to try pulling data from a few providers and match up the fields, most of the response fields are human readable. Here is some aditional info that should help decipher this response:</p>
3
+ #
4
+ # <p>&nbsp;</p>
5
+ # <ul>
6
+ # <li>&lt;dev_userid&gt;scoopwilson&lt;/dev_userid&gt; The odesk users id of the provider</li>
7
+ # <li>&lt;dev_rank_percentile&gt;82&lt;/dev_rank_percentile&gt; The providers rank overall on oDesk</li>
8
+ # <li>&lt;dev_usr_score&gt;4.9681818181818&lt;/dev_usr_score&gt; The providers feedback score</li>
9
+ #
10
+ # <li>&lt;dev_profile_access&gt;public&lt;/dev_profile_access&gt; The status of the providers profile (public or private)</li>
11
+ # <li>&lt;skill&gt; The Skill tag describes a skill that the provider has listed in their profile</li>
12
+ # <li>&lt;tsexam&gt; tsexam describes a test that the provider has taken and made public.</li>
13
+ # <li>&lt;dev_score&gt; dev_score describes feedback that the provider has received after a job has been completed (or just closed)</li>
14
+ #
15
+ # <li>&lt;dev_recent_rank_percentile&gt;80&lt;/dev_recent_rank_percentile&gt; The providers rank on oDesk using data from the last 90 days.</li>
16
+ # <li>&lt;dev_active_interviews&gt;0&lt;/dev_active_interviews&gt; How many active interviews the provider is engaged in now.</li>
17
+ # <li>&lt;dev_total_hours&gt;2526.1666666667&lt;/dev_total_hours&gt; The providers total hours worked on oDesk.</li>
18
+ #
19
+ # <li>&lt;experience&gt; Describes the providers experience as listed in their profile under the Experience section</li>
20
+ # <li>&lt;assignment&gt; Describes past assignements that are publicly viewable.</li>
21
+ #
22
+ # Here's a full list of all attributes available:
23
+ # * affiliated
24
+ # * ag_active_assignments
25
+ # * ag_adj_score
26
+ # * ag_adj_score_recent
27
+ # * ag_billed_assignments
28
+ # * ag_city
29
+ # * ag_cny_recno
30
+ # * ag_country
31
+ # * ag_country_tz
32
+ # * ag_description
33
+ # * ag_hours_lastdays
34
+ # * ag_last_date_worked
35
+ # * ag_logo
36
+ # * ag_manager_blurb
37
+ # * ag_manager_name
38
+ # * ag_member_since
39
+ # * ag_name
40
+ # * ag_portrait
41
+ # * ag_rank_percentile
42
+ # * ag_recent_hours
43
+ # * ag_summary
44
+ # * ag_teamid
45
+ # * ag_teamid_rollup
46
+ # * ag_tot_feedback
47
+ # * ag_total_developers
48
+ # * ag_total_hours
49
+ # * agency_ciphertext
50
+ # * assignments
51
+ # * assignments_count
52
+ # * candidacies
53
+ # * certification
54
+ # * ciphertext
55
+ # * competencies
56
+ # * dev_ac_agencies
57
+ # * dev_active_interviews
58
+ # * dev_adj_score
59
+ # * dev_adj_score_recent
60
+ # * dev_agency_ciphertext
61
+ # * dev_agency_ref
62
+ # * dev_availability
63
+ # * dev_bill_rate
64
+ # * dev_billed_assignments
65
+ # * dev_billed_assignments_recent
66
+ # * dev_blurb
67
+ # * dev_blurb_short
68
+ # * dev_category
69
+ # * dev_city
70
+ # * dev_country
71
+ # * dev_cur_assignments
72
+ # * dev_eng_skill
73
+ # * dev_est_availability
74
+ # * dev_expose_full_name
75
+ # * dev_full_name
76
+ # * dev_groups
77
+ # * dev_ic
78
+ # * dev_is_affiliated
79
+ # * dev_is_ready
80
+ # * dev_last_activity
81
+ # * dev_last_worked
82
+ # * dev_location
83
+ # * dev_member_since
84
+ # * dev_pay_agency_rate
85
+ # * dev_pay_rate
86
+ # * dev_portfolio_items_count
87
+ # * dev_portrait
88
+ # * dev_profile_title
89
+ # * dev_rank_percentile
90
+ # * dev_recent_hours
91
+ # * dev_recent_rank_percentile
92
+ # * dev_recno
93
+ # * dev_region
94
+ # * dev_scores
95
+ # * dev_short_name
96
+ # * dev_test_passed_count
97
+ # * dev_timezone
98
+ # * dev_tot_feedback
99
+ # * dev_tot_feedback_recent
100
+ # * dev_total_assignments
101
+ # * dev_total_hours
102
+ # * dev_total_hours_rounded
103
+ # * dev_ui_profile_access
104
+ # * dev_usr_score
105
+ # * dev_year_exp
106
+ # * education
107
+ # * experiences
108
+ # * favorited
109
+ # * iinitialize
110
+ # * is_odesk_ready
111
+ # * job_categories
112
+ # * oth_experiences
113
+ # * permalink
114
+ # * portfolio_items
115
+ # * profile_title_full
116
+ # * provider_profile_api
117
+ # * response_time
118
+ # * search_affiliate_providers_url
119
+ # * skills
120
+ # * trends
121
+ # * tsexams
122
+ # * tsexams_count
123
+ # * version
1
124
  class RubyDesk::Provider < RubyDesk::OdeskEntity
2
125
 
3
126
  attributes :affiliated, :ag_name, :ag_description, :dev_adj_score_recent,
@@ -42,6 +165,11 @@ class RubyDesk::Provider < RubyDesk::OdeskEntity
42
165
  attribute :portfolio_items, :class=>RubyDesk::PortfolioItem, :sub_element=>'portfolio_item'
43
166
 
44
167
  class << self
168
+ # Returns all categories defined in oDesk.
169
+ # These categories are retrieved from a static text file and not updated from the web.
170
+ # Return value is a hash.
171
+ # Each key is a name of a root category.
172
+ # Value is an array of subcategories.
45
173
  def all_categories
46
174
  text = File.read(File.join(File.dirname(__FILE__), "..", "categories"))
47
175
  lines = text.split(/[\r\n]+/).map{|line| line.strip}
@@ -57,7 +185,9 @@ class RubyDesk::Provider < RubyDesk::OdeskEntity
57
185
  return categories
58
186
  end
59
187
 
60
- # Implements search with the given criteria
188
+ # Implements search with the given criteria.
189
+ # For basic search, pass a string as the second parameter
190
+ # For advanced search, pass a string according to the following parameters
61
191
  #* q - ProfileData (ProfileData)
62
192
  # * Profile data is any text that appears in a provider's profile. For example if q = 'odesk' the search would return any user's with the word odesk in their profile.
63
193
  #* c1 - JobCategory (First Level Job Category)
@@ -118,15 +248,22 @@ class RubyDesk::Provider < RubyDesk::OdeskEntity
118
248
  end
119
249
  json = connector.prepare_and_invoke_api_call(
120
250
  'profiles/v1/search/providers', :method=>:get,
121
- :auth=>false, :sign=>false)
251
+ :auth=>false, :sign=>false, :params=>options)
122
252
 
123
253
  providers = []
124
- [json['providers']['provider']].flatten.each do |provider|
125
- providers << self.new(provider)
254
+ if json['providers']['provider']
255
+ [json['providers']['provider']].flatten.each do |provider|
256
+ providers << self.new(provider)
257
+ end
126
258
  end
127
259
  return providers
128
260
  end
129
261
 
262
+ # Retrieves the profile with the given user
263
+ # * connector: The RubyDesk::Connector that is connected to oDesk
264
+ # * id: The id of the user to retrieve his profile
265
+ # * options: A hash of options
266
+ # * brief: set this to true to retrieve only a brief profile of the given user
130
267
  def get_profile(connector, id, options={})
131
268
  brief = options.delete :brief || false
132
269
  json = connector.prepare_and_invoke_api_call(
@@ -1,3 +1,126 @@
1
+ # <h2>Response Details</h2>
2
+ # <ul>
3
+ # <li>&lt;snapshot&gt;
4
+ # <ul>
5
+ # <li>Snapshot detail container</li>
6
+ # </ul>
7
+ # </li>
8
+ # <li>&lt;status&gt;PRIVATE&lt;/status&gt;
9
+ #
10
+ # <ul>
11
+ # <li>Status of the snapshot
12
+ # <ul>
13
+ # <li>LOGIN</li>
14
+ # <li>NORMAL</li>
15
+ # <li>PRIVATE</li>
16
+ # <li>EXIT</li>
17
+ # </ul>
18
+ # </li>
19
+ # </ul>
20
+ # </li>
21
+ # <li>&lt;time&gt;1229521500&lt;/time&gt;
22
+ #
23
+ # <ul>
24
+ # <li>The GMT&nbsp;that the snapshot was taken</li>
25
+ # </ul>
26
+ # </li>
27
+ # <li>&lt;billing_status&gt;non-billed.disconnected&lt;/billing_status&gt;
28
+ # <ul>
29
+ # <li>A snapshot's billing status
30
+ # <ul>
31
+ # <li>non-billed.disconnected</li>
32
+ # <li>billed.disconnected</li>
33
+ #
34
+ # <li>billed.connected</li>
35
+ # </ul>
36
+ # </li>
37
+ # </ul>
38
+ # </li>
39
+ # <li>&lt;activity&gt;0&lt;/activity&gt;</li>
40
+ # <li>&lt;online_presence&gt;&lt;/online_presence&gt;</li>
41
+ # <li>&lt;user&gt;
42
+ # <ul>
43
+ # <li>The general user details associated with the current use</li>
44
+ #
45
+ # </ul>
46
+ # </li>
47
+ # <li>&lt;mouse_events_count/&gt;
48
+ # <ul>
49
+ # <li>The number of mouse events associated with this snapshot</li>
50
+ # </ul>
51
+ # </li>
52
+ # <li>&lt;company_id&gt;agencyone&lt;/company_id&gt;
53
+ # <ul>
54
+ # <li>Company ID&nbsp;associated with this snapshot</li>
55
+ #
56
+ # </ul>
57
+ # </li>
58
+ # <li>&lt;timezone&gt;America/Los_Angeles&lt;/timezone&gt;
59
+ # <ul>
60
+ # <li>User's time zone</li>
61
+ # </ul>
62
+ # </li>
63
+ # <li>&lt;uid/&gt;
64
+ # <ul>
65
+ # <li>The user id</li>
66
+ # </ul>
67
+ #
68
+ # </li>
69
+ # <li>&lt;keyboard_events_count/&gt;
70
+ # <ul>
71
+ # <li>Number of keyboard events counted for this snapshot</li>
72
+ # </ul>
73
+ # </li>
74
+ # <li>&lt;last_worked&gt;
75
+ # <ul>
76
+ # <li>The timestamp last worked
77
+ # <ul>
78
+ # <li>Format:&nbsp;[<em>1240637782</em>]</li>
79
+ #
80
+ # </ul>
81
+ # </li>
82
+ # </ul>
83
+ # </li>
84
+ # <li>&lt;memo/&gt;
85
+ # <ul>
86
+ # <li>Memo associated with the current time stamp</li>
87
+ # </ul>
88
+ # </li>
89
+ # <li>&lt;active_window_title/&gt;
90
+ # <ul>
91
+ # <li>The title of the active window when the snapshot was taken</li>
92
+ # </ul>
93
+ #
94
+ # </li>
95
+ # <li>&lt;report24_img&gt;
96
+ # <ul>
97
+ # <li>URL to a graph that describes a users activitly over a 24hr period</li>
98
+ # </ul>
99
+ # </li>
100
+ # <li>&lt;computer_name/&gt;
101
+ # <ul>
102
+ # <li>The name of the computer where the snapshot was taken</li>
103
+ # </ul>
104
+ # </li>
105
+ # <li>&lt;online_presence_img&gt;
106
+ #
107
+ # <ul>
108
+ # <li>URL&nbsp;for the default online user activity</li>
109
+ # </ul>
110
+ # </li>
111
+ # <li>&lt;user_id&gt;
112
+ # <ul>
113
+ # <li>User id associated with the current snapshot</li>
114
+ # </ul>
115
+ # </li>
116
+ # <li>&lt;client_version/&gt;
117
+ # <ul>
118
+ # <li>The oDesk Time Tracker version used to take the snapshot</li>
119
+ #
120
+ # </ul>
121
+ # </li>
122
+ # <li>&lt;teamroom_api&gt;/api/team/v1/teamrooms/agencyone.xml&lt;/teamroom_api&gt;&nbsp;</li>
123
+ # <li>&lt;workdiary_api&gt;/api/team/v1/workdiaries/agencyone/scoopwilson/20081217.xml&lt;/workdiary_api&gt;</li>
1
124
  class RubyDesk::Snapshot < RubyDesk::OdeskEntity
2
125
  attribute :status, :time, :billing_status, :report_url, :screenshot_img, :activity,
3
126
  :online_presence, :screenshot_url, :mouse_events_count, :company_id,
@@ -8,6 +131,10 @@ class RubyDesk::Snapshot < RubyDesk::OdeskEntity
8
131
 
9
132
  attribute :user, :class=>RubyDesk::User
10
133
 
134
+ # Retrieves work diary as an array of snapshots.
135
+ # The Work Diary method retrieves all snapshots from a single user account within a single day.
136
+ # Keep in mind that a day is dependent on server time and not the day in which the query is made.
137
+ # Make sure to test with various locations before you're done.
11
138
  def self.work_diary(connector, company_id, user_id, date = nil, timezone = "mine")
12
139
  json = connector.prepare_and_invoke_api_call(
13
140
  "team/v1/workdiaries/#{company_id}/#{user_id}" + (date ? "/"+date : ""),
@@ -19,6 +146,7 @@ class RubyDesk::Snapshot < RubyDesk::OdeskEntity
19
146
  end
20
147
  end
21
148
 
149
+ # Retrieves details of one snapshot
22
150
  def self.snapshot_details(connector, company_id, user_id, timestamp = nil)
23
151
  timestamp_param = case timestamp
24
152
  when String then timestamp