Class: Caltime

Inherits:
Object
  • Object
show all
Defined in:
lib/caltime.rb

Constant Summary collapse

TIMESTAMP_URL =
"https://caltimeprod.berkeley.edu/wfc/applications/wtk/html/ess/timestamp-record.jsp"
BASE_URL =
"https://caltimeprod.berkeley.edu/"
SSO_URL =
"https://caltimeprod.berkeley.edu/wfc/logonESS_SSO"

Instance Method Summary collapse

Constructor Details

#initializeCaltime

Returns a new instance of Caltime.



13
14
15
16
17
# File 'lib/caltime.rb', line 13

def initialize
  @agent = Mechanize.new
  @agent.follow_meta_refresh = true
  @authed = false
end

Instance Method Details

#authenticateObject



19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# File 'lib/caltime.rb', line 19

def authenticate
  page = @agent.get(BASE_URL)
  loop do
    count = 0
    page = page.form_with(:id => "loginForm") do |form|
      form.field_with(:id => 'username').value = ask("CalNet Username: ") 
      form.field_with(:id => 'password').value = ask("CalNet Password: ") { |q| q.echo = false }
    end.submit
    # Did we get redirected back to the login page?
    if page.uri.to_s =~ /auth\.berkeley\.edu/
      # Bail after 3 failures
      count += 1
      raise SecurityError("Too many failed authentication attempts") unless count < 3
      puts "\nLogin incorrect, please try again."
    else
      break
    end
  end
  # Strange extra SSO submission step
  page.form_with(:action => SSO_URL).submit
  # Let other methods know we are now authenticated
  @authed = true
end

#punchObject



43
44
45
46
47
48
49
# File 'lib/caltime.rb', line 43

def punch
  authenticate unless @authed
  page = @agent.post(TIMESTAMP_URL)
  if page.code != 200
    # TODO: Raise some sort of custom error here
  end
end

#punched_in?Boolean

Returns:

  • (Boolean)


77
78
79
80
81
82
83
84
85
86
87
88
89
90
# File 'lib/caltime.rb', line 77

def punched_in?
  today = Time.now.strftime("%a %-m/%d")
  latest_today_row = fetch_timecard_rows.select { |row| row.text =~ /#{today}/ }[-1]
  punched_in = latest_today_row.css('td[class="InPunch"]').text =~ /[0-9]:[0-9][0-9]/
  punched_out = latest_today_row.css('td[class="OutPunch"]').text =~ /[0-9]:[0-9][0-9]/
  if (punched_in and punched_out) or (!punched_in and !punched_out)
    return false
  elsif punched_in
    return true
  else
    # TODO: Raise some kind of custom error instead
    return false
  end
end

#punched_out?Boolean

Returns:

  • (Boolean)


92
93
94
# File 'lib/caltime.rb', line 92

def punched_out?
  return !punched_in?
end

#timecard(options = {}) ⇒ Object

Returns a Terminal::Table object that can be pretty-printed and contains timecard data TODO: Have this method return something less print-oriented and more data-oriented.

Maybe something that can easily be converted to a terminal-table, idk
For now, if called like CalTime.timecard raw: true, will return 2D array


55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/caltime.rb', line 55

def timecard(options={})
  authenticate unless @authed
  rows = fetch_timecard_rows  
  table_data = []
  total = 0
  rows.each do |row|
    date, inpunch, outpunch, amount = timecard_row_to_array(row)
    begin
      total += amount.to_f
    rescue
      total += 0
    end
    table_data << [date, inpunch, outpunch, amount]
  end
  return table_data if options[:raw]
  pretty_table = Terminal::Table.new :rows => table_data, :headings => ['Date', 'Punch In', 'Punch Out', 'Hours']
  pretty_table.add_separator
  pretty_table.add_row ["","","Total", total]
  pretty_table.style = {:width => 50}
  pretty_table
end