Class: Reaper::Main

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

Instance Method Summary collapse

Instance Method Details

#accountObject



366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
# File 'lib/reaper.rb', line 366

def 
  abort 'Harvest login info not found' unless File.exist? LOGIN_FILE_PATH
  
   = YAML.load File.read(LOGIN_FILE_PATH)
  if [:harvest_login]
     = [:harvest_login]
    token = [:token]
     = [:account_id]
    user_id = [:user_id]
  
    if token && !token.empty? && 
       && .is_a?(Integer) && 
      user_id && user_id.is_a?(Integer)
      puts """Your current Harvest login info:
- Harvest token: #{token}
- Harvest account ID: #{}
- Harvest user ID: #{user_id}"""
    end
  end
end

#delete(date_str) ⇒ Object



462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
# File 'lib/reaper.rb', line 462

def delete(date_str)
  mon, fri = get_week_range_from_date_str date_str

  entries, _ = show date_str
  
  if !entries.empty?
    puts "Delete #{entries.size} entrires from #{mon} to #{fri}? (Y/n)"
    confirm = $stdin.gets.chomp
    abort 'Deletion cancelled' unless confirm == 'Y'
  end
  
  progressbar = ProgressBar.create(
    :title => 'Deleting', 
    :total => entries.size,
    :format => '%t %c/%C %B'
  )
  
  entries.each do |e|
    rsp = delete_entry e['id']
    if rsp 
      progressbar.increment
    else
      abort "Deleting request failed. Your deleting actions may not be completed. Please run `reaper show #{date_str}` to check."
    end
  end

  puts 'Deletion completed!'
end


865
866
867
868
869
# File 'lib/reaper.rb', line 865

def donate
  puts 'If you think Reaper saves your time, please consider buying the author a milktea ❤️'
  pay_img = File.join Reaper.root, 'assets/alipay.jpg'
  `qlmanage -p #{pay_img} 2>/dev/null`
end

#loginObject



347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
# File 'lib/reaper.rb', line 347

def 
  Reaper.openWebpage "https://id.getharvest.com/oauth2/authorize?client_id=#{HARVEST_CLIENT_ID}&response_type=token"
  
  
  
  if $token
    me = Reaper.request 'users/me'
    $user_id = me['id']
    puts "Harvest user ID: #{$user_id}"
  
     = { :harvest_login => 
      { :token => $token, :account_id => $acc_id, :user_id => $user_id } 
    }
    
    File.write(LOGIN_FILE_PATH, .to_yaml)
  end
end

#meObject



388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
# File 'lib/reaper.rb', line 388

def me
  Reaper.check_auth

  puts "Fetching your Harvest profile..."
  rsp = Reaper.request 'users/me'

  if rsp
    rsp.each { |k, v| rsp[k] = v.scan(/.{1,30}/).join("\n") if (v && v.to_s.size > 30) }

    title = 'Harvest Profile'
    rows = rsp.to_a
    table = Terminal::Table.new :title => title, :rows => rows
    puts table
  end
end

#projectsObject



408
409
410
# File 'lib/reaper.rb', line 408

def projects
  Reaper.list_projects
end

#show(date_str) ⇒ Object



413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
# File 'lib/reaper.rb', line 413

def show(date_str)
  mon, fri = get_week_range_from_date_str date_str
  
  Reaper.check_auth

  # both ruby and Harvest use ISO 8601 by default
  from = mon.to_s
  to = fri.to_s
  
  puts "Fetching your time entries from #{from} to #{to}"
  raw_entries = Reaper.request("time_entries?user_id=#{$user_id}&from=#{from}&to=#{to}")['time_entries']
  
  if raw_entries.empty?
    puts "Cannot find any time entries in the week of #{from}" 
    return []
  end
  
  entries = {}
  raw_entries.each do |e|
    date = Date.parse(e['spent_date'])
    tasks = entries[date] || []
    entries[date] = tasks if tasks.empty?
    tasks << {
      :id => e['id'],
      :created_at => DateTime.parse(e['created_at']),
      :project => e['project']['name'],
      :project_code => e['project']['code'],
      :task => e['task']['name'],
      :client => e['client']['name'],
      :hours => e['hours']
    }
  end
  
  # sort the entries hash to make sure:
  # - keys (spent date) are sorted by date
  # - values (daily entries) are sorted by entry created date
  
  entries = entries.sort.to_h
  
  entries.each do |k, v|
    v.sort_by! { |t| t[:created_at] }
  end
  
  print_time_entries mon, fri, entries

  return raw_entries, entries
end

#submit(date_str) ⇒ Object



493
494
495
# File 'lib/reaper.rb', line 493

def submit(date_str)
  submit_time_entries date_str, options[:excluded]
end

#testObject



335
336
337
338
339
340
341
342
343
344
# File 'lib/reaper.rb', line 335

def test
  a = {"no"=>"0", "po"=>"0", "p0"=>"20769370", "t0"=>"11683694", "pct0"=>"56", "p1"=>"20500923", "t1"=>"11728114", "pct1"=>"22", "p2"=>"20500918", "t2"=>"11728114", "pct2"=>"22"}
  puts a
  
  max_index = a.keys.select { |e| e =~ /p\d+/ }
    .map { |e| e[1..-1] }
    .max
  
  puts max_index
end

#versionObject



872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
# File 'lib/reaper.rb', line 872

def version
sickle = "MMMMMMMMMMMMMMMMMMMMMMMMMMMNdyo//oymMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMmo` `/yNMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMs`   :hMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMN- `: .yMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM: :d: -dMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMN. sMh` oMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMy .MMN- /MM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM  dMMN- oM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM` hMMMm` d
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM  dMMMM+ :
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMy `MMMMMd `
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMN. sMMMMMm  
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMN- /MMMMMMy .
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMh. oMMMMMMM. s
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMNy- -dMMMMMMM+ -M
MMMMMMMMMMMMd/ -/oydmNMMMMMMNmho: `/dMMMMMMMM+ .NM
MMMMMMMMMMd:  syo/-.   ``.`  `./odMMMMMMMMMm: :NMM
MMMMMMMMd: .+` /dMMMMNmmddmmNMMMMMMMMMMMMNo``sMMMM
MMMMMMd: -yMMNy` .odMMMMMMMMMMMMMMMMMMMmo` +NMMMMM
MMMMd:   -----. -o- ./ymMMMMMMMMMMMNdo- .oNMMMMMMM
MMd: -yhhhh+  -hMMMNy+-  .:/+oo+/:. `:odMMMMMMMMMM
m:  `:::::- -hMMMMMMMMMMmhsoo++ooshmMMMMMMMMMMMMMM
` +ssss:  -hMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
. +mNy- -hMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
N+.  `/hMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM"

  slogan = 'Keep your PM away (TM)'
  slogan_len = slogan.length + 4
  puts "#{sickle}\n\n#{'*' * slogan_len}\n* #{slogan} *\n#{'*' * slogan_len}\n\nReaper: A smart Harvest filling helper. \nVersion #{Reaper::VERSION}"
end