module Reaper
Constants
- CONFIG_FILE_PATH
- HARVEST_CLIENT_ID
- LOCAL_SERVER_PORT
- LOGIN_FILE_PATH
- VERSION
Public Instance Methods
check_auth()
click to toggle source
# File lib/reaper.rb, line 71 def check_auth abort('Cannot find cached login info. Please run `reaper login` first.') unless restore_login_info end
list_projects()
click to toggle source
# File lib/reaper.rb, line 129 def list_projects check_auth puts "Fetching your project list..." response = request 'users/me/project_assignments' puts "Cannot fetch your project list, please try agian later." unless response puts '' projects = response['project_assignments'] # puts JSON.pretty_generate projects projects = projects.map do |p| pcode = p['project']['code'] pname = p['project']['name'] desc = "[#{pcode}] #{pname}" tasks = p['task_assignments'] { :project_id => p['project']['id'], :project_name => pname, :project_code => pcode, :desc => desc, :client => p['client']['name'], :tasks => tasks.map do |t| { 'tid' => t['task']['id'], 'name' => t['task']['name'] } end } end max_chars = (projects.max_by { |p| p[:desc].length })[:desc].length clients = projects.group_by { |p| p[:client] }.to_h.sort.to_h clients.each do |k, v| puts k puts '-' * max_chars v.sort_by! { |p| p[:project_code] } v.each do |p| puts p[:desc] end puts '' end puts "Total: #{projects.size}" clients end
load_config()
click to toggle source
# File lib/reaper.rb, line 96 def load_config return false if !File.exist? CONFIG_FILE_PATH $config = YAML.load File.read(CONFIG_FILE_PATH) true end
openWebpage(link)
click to toggle source
# File lib/reaper.rb, line 27 def openWebpage(link) system("open", link) end
request(endpoint)
click to toggle source
# File lib/reaper.rb, line 31 def request(endpoint) uri = URI("https://api.harvestapp.com/v2/#{endpoint}") req = Net::HTTP::Get.new(uri) req['Accept'] = "application/json" req['Authorization'] = "Bearer #{$token}" req['Harvest-Account-ID'] = $acc_id begin res = Net::HTTP.start(uri.hostname, uri.port, :use_ssl => true) { |http| http.request(req) } rescue abort 'Cannot send request. Please check your network connection and try again.' end if res.kind_of? Net::HTTPSuccess JSON.parse res.body else nil end end
request_delete(endpoint)
click to toggle source
# File lib/reaper.rb, line 53 def request_delete(endpoint) uri = URI("https://api.harvestapp.com/v2/#{endpoint}") req = Net::HTTP::Delete.new(uri) req['Accept'] = "application/json" req['Content-Type'] = "application/json" req['Authorization'] = "Bearer #{$token}" req['Harvest-Account-ID'] = $acc_id res = Net::HTTP.start(uri.hostname, uri.port, :use_ssl => true) { |http| http.request(req) } if res.kind_of? Net::HTTPSuccess JSON.parse res.body else nil end end
restore_login_info()
click to toggle source
# File lib/reaper.rb, line 75 def restore_login_info return false if !File.exist? LOGIN_FILE_PATH login_data = YAML.load File.read(LOGIN_FILE_PATH) if login_data[:harvest_login] login = login_data[:harvest_login] token = login[:token] account_id = login[:account_id] user_id = login[:user_id] if token && !token.empty? && account_id && account_id.is_a?(Integer) && user_id && user_id.is_a?(Integer) $token = token $acc_id = account_id $user_id = user_id return true end end false end
root()
click to toggle source
# File lib/reaper.rb, line 249 def root File.expand_path '../', File.dirname(__FILE__) end
show_config(config)
click to toggle source
# File lib/reaper.rb, line 102 def show_config(config) puts "Reaper Configuration (version #{$config[:version]})" puts '' title = 'Global Settings' rows = [] rows << ['Daily working hours negative offset', "#{$config[:daily_negative_offset]} hour(s)"] rows << ['Daily working hours positive offset', "#{$config[:daily_positive_offset]} hour(s)"] table = Terminal::Table.new :title => title, :rows => rows puts table puts '' title = 'Projects & Tasks Settings' headers = ['Project', 'Task', 'Percentage'] rows = [] $config[:tasks].each do |task| desc = "[#{task[:pcode]}] #{task[:pname]} (#{task[:client]})" rows << [desc.scan(/.{1,30}/).join("\n"), task[:tname], "#{(task[:percentage] * 100).round}%"] end table = Terminal::Table.new :title => title, :headings => headers, :rows => rows table.style = { :all_separators => true } puts table end
start_config_server(global_settings, projects, added_tasks)
click to toggle source
# File lib/reaper.rb, line 181 def start_config_server(global_settings, projects, added_tasks) puts 'Launching the configuration page in your browser...' server = TCPServer.new LOCAL_SERVER_PORT while session = server.accept request = session.gets next unless request if match = request.match(/\/reaper-config\s+/i) template_path = File.join root, 'assets/reaper_config_template.html' template = File.read(template_path) .sub('"{{RPR_GLOBAL_SETTINGS}}"', "JSON.parse('#{global_settings.to_json}')") .sub('"{{RPR_PROJECTS}}"', "JSON.parse('#{projects.to_json}')") .sub('"{{RPR_ADDED_TASKS}}"', "JSON.parse('#{added_tasks.to_json}')") session.print "HTTP/1.1 200\r\n" session.print "Content-Type: text/html\r\n" session.print "\r\n" session.print template elsif match = request.match(/\/submitTimeEntries\?([\S]+)\s+HTTP/i) params = match.captures.first raw_config = params.split('&').map { |arg| arg.split '=' }.to_h max_index = raw_config.keys.select { |e| e =~ /p\d+/ } .map { |e| e[1..-1].to_i } .max tasks = [] (max_index + 1).times do |n| tasks << { :pid => raw_config["p#{n}"].to_i, :tid => raw_config["t#{n}"].to_i, :percentage => raw_config["pct#{n}"].to_i / 100.0 } end tasks.each do |t| proj = projects.select { |p| p['pid'] == t[:pid] }.first if proj task = proj['tasks'].select { |it| it['tid'] == t[:tid] }.first t[:pcode] = proj['code'] t[:pname] = proj['name'] t[:client] = proj['client'] t[:tname] = task['name'] end abort 'Something went wrong' unless proj && task end $config = { :version => '0.1.0', :daily_negative_offset => raw_config['no'].to_i, :daily_positive_offset => raw_config['po'].to_i, :tasks => tasks } session.close break end session.close end end