togman 0.1
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/bin/togman +58 -0
- data/lib/mantis.rb +44 -0
- data/lib/toggl.rb +63 -0
- metadata +135 -0
data/bin/togman
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
require "rubygems"
|
|
3
|
+
require "patron"
|
|
4
|
+
require "pp"
|
|
5
|
+
require "json"
|
|
6
|
+
require 'savon'
|
|
7
|
+
require 'highline/import'
|
|
8
|
+
require 'trollop'
|
|
9
|
+
require 'yaml'
|
|
10
|
+
|
|
11
|
+
require 'toggl.rb'
|
|
12
|
+
require 'mantis.rb'
|
|
13
|
+
|
|
14
|
+
configfile = ENV['HOME'] + '/.togmanrc'
|
|
15
|
+
if !File.file? configfile
|
|
16
|
+
puts 'Cannot open ' + configfile
|
|
17
|
+
exit
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
config = YAML::load_file configfile
|
|
21
|
+
pp config
|
|
22
|
+
|
|
23
|
+
Savon.configure do |setting|
|
|
24
|
+
setting.log = false # disable logging
|
|
25
|
+
# config.log_level = :info # changing the log level
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
opts = Trollop::options do
|
|
29
|
+
opt :dryrun, "Preview time to be logged without saving to Mantis", :short => 'd'
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
if !opts.dryrun
|
|
33
|
+
pass = ask('Password:') {|q| q.echo = '*'}
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
t = Toggl.new config['toggl_api_key'], config['nonbill']
|
|
37
|
+
m = Mantis.new config['user'], pass, config['mantis_url']
|
|
38
|
+
|
|
39
|
+
if !opts.dryrun
|
|
40
|
+
t.today.each do |ims, data|
|
|
41
|
+
if !m.issue_exists ims
|
|
42
|
+
raise "Issue not found #{ims}"
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
total = 0
|
|
48
|
+
free = []
|
|
49
|
+
t.today.each do |ims, data|
|
|
50
|
+
data.each do |item|
|
|
51
|
+
if !opts.dryrun
|
|
52
|
+
m.add_note ims, item[:desc], item[:duration]
|
|
53
|
+
end
|
|
54
|
+
p ims.to_s + " " + item[:desc] + " " + item[:duration].to_s + " " + item[:orig].to_s
|
|
55
|
+
total += item[:duration]
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
p "TOTAL: " + total.to_s
|
data/lib/mantis.rb
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
class Mantis
|
|
2
|
+
def initialize (user, password, url)
|
|
3
|
+
@client = Savon::Client.new do |wdsl|
|
|
4
|
+
wdsl.document = url
|
|
5
|
+
end
|
|
6
|
+
@client.wsdl.endpoint = url
|
|
7
|
+
@user = user
|
|
8
|
+
@password = password
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def issue_exists (issue_id)
|
|
12
|
+
user = @user
|
|
13
|
+
password = @password
|
|
14
|
+
issue = @client.request "mc_issue_exists" do
|
|
15
|
+
soap.body = <<XML
|
|
16
|
+
<username>#{user}</username>
|
|
17
|
+
<password>#{password}</password>
|
|
18
|
+
<issue_id>#{issue_id}</issue_id>
|
|
19
|
+
XML
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
issue.to_hash[:mc_issue_exists_response][:return]
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def add_note (issue_id, text, time_tracking)
|
|
26
|
+
user = @user
|
|
27
|
+
password = @password
|
|
28
|
+
res = @client.request "mc_issue_note_add" do
|
|
29
|
+
soap.body = <<XML
|
|
30
|
+
<username>#{user}</username>
|
|
31
|
+
<password>#{password}</password>
|
|
32
|
+
<issue_id>#{issue_id}</issue_id>
|
|
33
|
+
<note>
|
|
34
|
+
<text>#{text}</text>
|
|
35
|
+
<view_state>
|
|
36
|
+
<name>private</name>
|
|
37
|
+
<id>50</id>
|
|
38
|
+
</view_state>
|
|
39
|
+
<time_tracking>#{time_tracking}</time_tracking>
|
|
40
|
+
</note>
|
|
41
|
+
XML
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
data/lib/toggl.rb
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
class Toggl
|
|
2
|
+
def initialize (api_key, nonbill)
|
|
3
|
+
@api_key = api_key
|
|
4
|
+
@nonbill = nonbill
|
|
5
|
+
|
|
6
|
+
@sess = Patron::Session.new
|
|
7
|
+
@sess.base_url = "https://www.toggl.com"
|
|
8
|
+
@sess.username = api_key
|
|
9
|
+
@sess.password = "api_token"
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def today
|
|
13
|
+
from = Time.utc(Time.now.year, Time.now.month, Time.now.day).iso8601
|
|
14
|
+
to = Time.utc(Time.now.year, Time.now.month, Time.now.day, 23, 59, 59).iso8601
|
|
15
|
+
return self.entries(from, to)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def entries (from, to)
|
|
19
|
+
log = {}
|
|
20
|
+
res = @sess.get('/api/v5/time_entries.json?start_date=' + from + '&end_date=' + to).body
|
|
21
|
+
JSON.parse(res)["data"].each do |item|
|
|
22
|
+
raw = item["description"]
|
|
23
|
+
|
|
24
|
+
# Check all entries start with a issue number
|
|
25
|
+
if !res = raw.match(/^([0-9]+) (.+)$/)
|
|
26
|
+
raise 'Item does not have an issue number: ' + raw
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
ims = res[1]
|
|
30
|
+
desc = res[2]
|
|
31
|
+
duration = (item["duration"] / 60)
|
|
32
|
+
|
|
33
|
+
if log[ims] == nil
|
|
34
|
+
log[ims] = []
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Squash times with the same descriptions together
|
|
38
|
+
exists = false
|
|
39
|
+
log[ims].each do |exist|
|
|
40
|
+
if exist[:desc] == desc
|
|
41
|
+
exist[:duration] += duration
|
|
42
|
+
exists = true
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# TOOD: Rounding should be on the total time for an issue.
|
|
47
|
+
# not per note... either need to bunch them together or
|
|
48
|
+
# round the final note???
|
|
49
|
+
|
|
50
|
+
free = false
|
|
51
|
+
if !@nonbill.member? ims.to_i
|
|
52
|
+
orig = duration
|
|
53
|
+
duration = ((duration.to_f/10).ceil*10).round
|
|
54
|
+
free = true
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
if !exists
|
|
58
|
+
log[ims].push({:desc => desc, :duration => duration, :orig => orig})
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
return log
|
|
62
|
+
end
|
|
63
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: togman
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
prerelease: false
|
|
5
|
+
segments:
|
|
6
|
+
- 0
|
|
7
|
+
- 1
|
|
8
|
+
version: "0.1"
|
|
9
|
+
platform: ruby
|
|
10
|
+
authors:
|
|
11
|
+
- Benjamin Johnson
|
|
12
|
+
autorequire:
|
|
13
|
+
bindir: bin
|
|
14
|
+
cert_chain: []
|
|
15
|
+
|
|
16
|
+
date: 2011-10-03 00:00:00 +01:00
|
|
17
|
+
default_executable: bin/togman
|
|
18
|
+
dependencies:
|
|
19
|
+
- !ruby/object:Gem::Dependency
|
|
20
|
+
name: patron
|
|
21
|
+
prerelease: false
|
|
22
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - ">="
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
segments:
|
|
27
|
+
- 0
|
|
28
|
+
- 4
|
|
29
|
+
- 16
|
|
30
|
+
version: 0.4.16
|
|
31
|
+
type: :runtime
|
|
32
|
+
version_requirements: *id001
|
|
33
|
+
- !ruby/object:Gem::Dependency
|
|
34
|
+
name: json
|
|
35
|
+
prerelease: false
|
|
36
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - ">="
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
segments:
|
|
41
|
+
- 1
|
|
42
|
+
- 6
|
|
43
|
+
- 1
|
|
44
|
+
version: 1.6.1
|
|
45
|
+
type: :runtime
|
|
46
|
+
version_requirements: *id002
|
|
47
|
+
- !ruby/object:Gem::Dependency
|
|
48
|
+
name: savon
|
|
49
|
+
prerelease: false
|
|
50
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
|
51
|
+
requirements:
|
|
52
|
+
- - ">="
|
|
53
|
+
- !ruby/object:Gem::Version
|
|
54
|
+
segments:
|
|
55
|
+
- 0
|
|
56
|
+
- 9
|
|
57
|
+
- 7
|
|
58
|
+
version: 0.9.7
|
|
59
|
+
type: :runtime
|
|
60
|
+
version_requirements: *id003
|
|
61
|
+
- !ruby/object:Gem::Dependency
|
|
62
|
+
name: highline
|
|
63
|
+
prerelease: false
|
|
64
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
|
65
|
+
requirements:
|
|
66
|
+
- - ">="
|
|
67
|
+
- !ruby/object:Gem::Version
|
|
68
|
+
segments:
|
|
69
|
+
- 1
|
|
70
|
+
- 6
|
|
71
|
+
- 2
|
|
72
|
+
version: 1.6.2
|
|
73
|
+
type: :runtime
|
|
74
|
+
version_requirements: *id004
|
|
75
|
+
- !ruby/object:Gem::Dependency
|
|
76
|
+
name: trollop
|
|
77
|
+
prerelease: false
|
|
78
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
|
79
|
+
requirements:
|
|
80
|
+
- - ">="
|
|
81
|
+
- !ruby/object:Gem::Version
|
|
82
|
+
segments:
|
|
83
|
+
- 1
|
|
84
|
+
- 16
|
|
85
|
+
- 2
|
|
86
|
+
version: 1.16.2
|
|
87
|
+
type: :runtime
|
|
88
|
+
version_requirements: *id005
|
|
89
|
+
description: ""
|
|
90
|
+
email:
|
|
91
|
+
- ben@benpjohnson.com
|
|
92
|
+
executables:
|
|
93
|
+
- togman
|
|
94
|
+
extensions: []
|
|
95
|
+
|
|
96
|
+
extra_rdoc_files: []
|
|
97
|
+
|
|
98
|
+
files:
|
|
99
|
+
- bin/togman
|
|
100
|
+
- lib/mantis.rb
|
|
101
|
+
- lib/toggl.rb
|
|
102
|
+
has_rdoc: true
|
|
103
|
+
homepage: http://benpjohnson.com
|
|
104
|
+
licenses: []
|
|
105
|
+
|
|
106
|
+
post_install_message:
|
|
107
|
+
rdoc_options: []
|
|
108
|
+
|
|
109
|
+
require_paths:
|
|
110
|
+
- lib
|
|
111
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
112
|
+
requirements:
|
|
113
|
+
- - ">="
|
|
114
|
+
- !ruby/object:Gem::Version
|
|
115
|
+
segments:
|
|
116
|
+
- 0
|
|
117
|
+
version: "0"
|
|
118
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
119
|
+
requirements:
|
|
120
|
+
- - ">="
|
|
121
|
+
- !ruby/object:Gem::Version
|
|
122
|
+
segments:
|
|
123
|
+
- 1
|
|
124
|
+
- 3
|
|
125
|
+
- 6
|
|
126
|
+
version: 1.3.6
|
|
127
|
+
requirements: []
|
|
128
|
+
|
|
129
|
+
rubyforge_project:
|
|
130
|
+
rubygems_version: 1.3.6
|
|
131
|
+
signing_key:
|
|
132
|
+
specification_version: 3
|
|
133
|
+
summary: Transfer time from Toggl to Mantis
|
|
134
|
+
test_files: []
|
|
135
|
+
|