TokiCLI 0.0.1 → 0.0.2
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +12 -0
- data/README.md +74 -3
- data/TokiCLI.gemspec +3 -3
- data/bin/toki +1 -1
- data/lib/TokiCLI/app.rb +28 -19
- data/lib/TokiCLI/module.rb +43 -14
- data/lib/TokiCLI/version.rb +1 -1
- data/lib/TokiCLI/view.rb +18 -9
- metadata +7 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2b09a54e6095cd0db8771b463d7b0b42abcce848
|
4
|
+
data.tar.gz: a38757d420d82bba26f791d5db014034ddd0ca69
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c038040cc9efe49a44e23b70e9c3341ccfbba70619248ebd1a198997f1f8ad1436f9ceae4f7e6e1a7256b605938f4cfa4f8e879cd93c48d8c620c88e79659097
|
7
|
+
data.tar.gz: b2301f6b6608aea4cbc75f616893c18f8e484223fece39d13cb7e4dc05a1e5ab42d229e1a1bde9c0833407cd65f18a81ecf446660ecbf06ff6ed8e88fc4b76b1
|
data/CHANGELOG.md
ADDED
data/README.md
CHANGED
@@ -1,13 +1,84 @@
|
|
1
1
|
# TokiCLI
|
2
2
|
|
3
|
-
|
3
|
+
Toki.app command-line client.
|
4
|
+
|
5
|
+
Access your Toki data from the local database or from the App.net backup channel.
|
4
6
|
|
5
7
|
## Installation
|
6
8
|
|
7
|
-
|
9
|
+
gem install TokiCLI
|
8
10
|
|
9
11
|
## Usage
|
10
12
|
|
11
|
-
|
13
|
+
### Log
|
14
|
+
|
15
|
+
The **log** command shows the entire log (history) for one app.
|
16
|
+
|
17
|
+
You don't have to specify the exact name of the identifier: for example, typing 'iterm' will find 'com.googlecod.iterm2'.
|
18
|
+
|
19
|
+
`toki log iterm`
|
20
|
+
|
21
|
+
The results are sorted by ascending date and time.
|
22
|
+
|
23
|
+
When pulling the data from ADN instead of the local database, the results are sorted by ascending synced message.
|
24
|
+
|
25
|
+
### Total
|
26
|
+
|
27
|
+
The **total** command shows the total usage time for all apps.
|
28
|
+
|
29
|
+
`toki total`
|
30
|
+
|
31
|
+
The results are sorted by ascending usage time.
|
32
|
+
|
33
|
+
### Top
|
34
|
+
|
35
|
+
The **top** command shows your top used apps.
|
36
|
+
|
37
|
+
`toki top`
|
38
|
+
|
39
|
+
TokiCLI shows the top 5 by default, but you can specify a number with the `-n` option:
|
40
|
+
|
41
|
+
`toki top -n 10`
|
42
|
+
|
43
|
+
### Auth
|
44
|
+
|
45
|
+
In order to be able to access your ADN channel (optional), you have to obtain a "token" (secret code) from App.net: go to your App.net account page, click "Your apps" then find "Create a token for yourself."
|
46
|
+
|
47
|
+
The last step is simply to do `toki auth` and paste the token.
|
48
|
+
|
49
|
+
### Global option
|
50
|
+
|
51
|
+
TokiCLI accesses the local Toki database by default.
|
52
|
+
|
53
|
+
If you want to access the App.net backup channel instead, you have to specify the `-a` option:
|
54
|
+
|
55
|
+
`toki total -a`
|
56
|
+
|
57
|
+
`toki log vlc -a`
|
58
|
+
|
59
|
+
`toki top -n 10 -a`
|
60
|
+
|
61
|
+
|
62
|
+
## Toki
|
63
|
+
|
64
|
+
[Toki](https://itunes.apple.com/fr/app/toki/id861749202?mt=12) is a Mac OS X app written by [Keitaroh Kobayashi](http://app.net/keita).
|
65
|
+
|
66
|
+
It's a time tracker for your apps that sits in the menu bar.
|
67
|
+
|
68
|
+
## Important
|
69
|
+
|
70
|
+
**TokiCLI does _not_ track your apps.**
|
71
|
+
|
72
|
+
**Tracking is the job of Toki.app by @keita.**
|
73
|
+
|
74
|
+
TokiCLI interacts only with the Toki.app database or the App.net backup channel.
|
75
|
+
|
76
|
+
## Next
|
77
|
+
|
78
|
+
Teasing: TokiCLI has only read-only commands... for now. ;)
|
79
|
+
|
80
|
+
## Thanks
|
12
81
|
|
82
|
+
Keita was super nice and said "Awesome!" instead of just "Yes" or "GTFO" when I asked him if I could use the 'Toki' name for this companion Gem.
|
13
83
|
|
84
|
+
Many thanks and congrats to Keita! :)
|
data/TokiCLI.gemspec
CHANGED
@@ -8,9 +8,9 @@ Gem::Specification.new do |spec|
|
|
8
8
|
spec.version = TokiCLI::VERSION
|
9
9
|
spec.authors = ["Eric Dejonckheere"]
|
10
10
|
spec.email = ["eric@aya.io"]
|
11
|
-
spec.summary = %q{Toki command-line client}
|
12
|
-
spec.description = %q{Toki command-line client: read your Toki data from the local database or from the App.net backup channel}
|
13
|
-
spec.homepage = ""
|
11
|
+
spec.summary = %q{Toki.app command-line client}
|
12
|
+
spec.description = %q{Toki.app command-line client: read your Toki data from the local database or from the App.net backup channel, delete data from both...}
|
13
|
+
spec.homepage = "https://github.com/ericdke/TokiCLI"
|
14
14
|
spec.license = "MIT"
|
15
15
|
|
16
16
|
spec.files = `git ls-files -z`.split("\x0")
|
data/bin/toki
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
# encoding: utf-8
|
3
3
|
# Toki command-line client
|
4
4
|
# Author: Eric Dejonckheere (http://app.net/ericd)
|
5
|
-
# Toki by:
|
5
|
+
# Toki by: Keitaroh Kobayashi (http://app.net/keita)
|
6
6
|
|
7
7
|
$PROGRAM_NAME = 'toki'
|
8
8
|
require_relative '../lib/TokiCLI'
|
data/lib/TokiCLI/app.rb
CHANGED
@@ -7,38 +7,39 @@ module TokiCLI
|
|
7
7
|
desc "total", "Shows the total usage of all apps"
|
8
8
|
option :adn, aliases: '-a', type: :boolean, desc: 'Select ADN channel as source (toki total -a)'
|
9
9
|
def total
|
10
|
-
|
11
|
-
toki = total_adn
|
12
|
-
else
|
13
|
-
toki = total_db
|
14
|
-
end
|
10
|
+
toki = create_toki(options)
|
15
11
|
get_total(toki, options)
|
16
12
|
end
|
17
13
|
|
14
|
+
desc "top", "Shows your most used apps"
|
15
|
+
option :adn, aliases: '-a', type: :boolean, desc: 'Select ADN channel as source (toki top -a)'
|
16
|
+
option :number, aliases: '-n', type: :numeric, desc: 'Specifi the number of apps (toki top -n 10)'
|
17
|
+
def top
|
18
|
+
toki = create_toki(options)
|
19
|
+
entries = toki.get_content(options)
|
20
|
+
clear
|
21
|
+
hits = toki.top(entries, options[:number] || 5)
|
22
|
+
puts TokiCLI::View.new.hits_table(hits.reverse)
|
23
|
+
puts "\n"
|
24
|
+
end
|
25
|
+
|
18
26
|
desc "auth", "Input your App.net token for authorization"
|
19
27
|
def auth
|
20
28
|
puts Status.paste_token
|
21
29
|
token = STDIN.gets.chomp!
|
22
|
-
|
23
|
-
|
24
|
-
else
|
25
|
-
abort(Status.no_token)
|
26
|
-
end
|
30
|
+
abort(Status.no_token) if token == ''
|
31
|
+
save_token(token)
|
27
32
|
puts Status.done
|
28
33
|
end
|
29
34
|
|
30
35
|
desc "log APP", "Shows the complete log for an app"
|
31
|
-
option :adn, aliases: '-a', type: :boolean, desc: 'Select ADN channel as source (toki
|
36
|
+
option :adn, aliases: '-a', type: :boolean, desc: 'Select ADN channel as source (toki log -a)'
|
32
37
|
def log(*args)
|
33
38
|
abort(Status.specify_name) if args.empty?
|
34
|
-
if options[:adn]
|
35
|
-
toki = total_adn
|
36
|
-
else
|
37
|
-
toki = total_db
|
38
|
-
end
|
39
39
|
asked = args[0]
|
40
|
-
|
41
|
-
|
40
|
+
toki = create_toki(options)
|
41
|
+
entries = toki.get_content(options)
|
42
|
+
app_data = toki.get_app(asked, entries)
|
42
43
|
v = TokiCLI::View.new
|
43
44
|
puts v.app_table(asked, app_data)
|
44
45
|
puts "\n"
|
@@ -46,6 +47,14 @@ module TokiCLI
|
|
46
47
|
|
47
48
|
private
|
48
49
|
|
50
|
+
def create_toki(options)
|
51
|
+
if options[:adn]
|
52
|
+
total_adn
|
53
|
+
else
|
54
|
+
total_db
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
49
58
|
def total_adn
|
50
59
|
clear
|
51
60
|
puts Status.get_all
|
@@ -54,7 +63,7 @@ module TokiCLI
|
|
54
63
|
|
55
64
|
def total_db
|
56
65
|
clear
|
57
|
-
puts "getting data from db\n"
|
66
|
+
#puts "getting data from db\n"
|
58
67
|
init_toki_db
|
59
68
|
end
|
60
69
|
|
data/lib/TokiCLI/module.rb
CHANGED
@@ -35,7 +35,9 @@ module TokiCLI
|
|
35
35
|
app_data[obj.msg[:id]] = {
|
36
36
|
from: Time.at(obj.app[:active_from]).strftime("%Y/%m/%d %Hh:%Mm:%Ss"),
|
37
37
|
to: Time.at(obj.app[:active_to]).strftime("%Y/%m/%d %Hh:%Mm:%Ss"),
|
38
|
-
duration: "#{human[:hours]}h #{human[:minutes]}m #{human[:seconds]}s"
|
38
|
+
duration: "#{human[:hours]}h #{human[:minutes]}m #{human[:seconds]}s",
|
39
|
+
name: obj.app[:name],
|
40
|
+
raw_from: obj.app[:active_from]
|
39
41
|
}
|
40
42
|
end
|
41
43
|
human = epoch_to_human(totals[:app])
|
@@ -43,16 +45,9 @@ module TokiCLI
|
|
43
45
|
app_data
|
44
46
|
end
|
45
47
|
def all_data(synced)
|
46
|
-
totals =
|
47
|
-
synced.each do |obj|
|
48
|
-
unless totals[obj.app[:name]].nil?
|
49
|
-
totals[obj.app[:name]] = totals[obj.app[:name]] + obj.app[:total]
|
50
|
-
else
|
51
|
-
totals[obj.app[:name]] = obj.app[:total]
|
52
|
-
end
|
53
|
-
end
|
48
|
+
totals = get_totals(synced)
|
54
49
|
bundles = {}
|
55
|
-
sorted = totals
|
50
|
+
sorted = sort_totals(totals)
|
56
51
|
sorted.each do |name, total|
|
57
52
|
human = epoch_to_human(total)
|
58
53
|
if human[:hours] < 1
|
@@ -63,9 +58,44 @@ module TokiCLI
|
|
63
58
|
end
|
64
59
|
bundles
|
65
60
|
end
|
61
|
+
def top(synced, number = 5)
|
62
|
+
number = -number
|
63
|
+
totals = get_totals(synced)
|
64
|
+
sorted = sort_totals(totals)
|
65
|
+
humanized = []
|
66
|
+
sorted.each do |n,t|
|
67
|
+
humanized << [n, humanized_date(t)]
|
68
|
+
end
|
69
|
+
humanized[number..-1]
|
70
|
+
end
|
66
71
|
|
67
72
|
private
|
68
73
|
|
74
|
+
def humanized_date(epoch)
|
75
|
+
human = epoch_to_human(epoch)
|
76
|
+
"#{human[:hours]}h #{human[:minutes]}m #{human[:seconds]}s"
|
77
|
+
end
|
78
|
+
|
79
|
+
def sort_totals(totals)
|
80
|
+
totals.sort_by { |k,v| v }
|
81
|
+
end
|
82
|
+
|
83
|
+
def get_totals(synced)
|
84
|
+
totals = {}
|
85
|
+
synced.each do |obj|
|
86
|
+
totals[obj.app[:name]] = app_total(obj, totals)
|
87
|
+
end
|
88
|
+
totals
|
89
|
+
end
|
90
|
+
|
91
|
+
def app_total(obj, totals)
|
92
|
+
unless totals[obj.app[:name]].nil?
|
93
|
+
totals[obj.app[:name]] + obj.app[:total]
|
94
|
+
else
|
95
|
+
obj.app[:total]
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
69
99
|
def epoch_to_human(epoch)
|
70
100
|
hours = epoch / 3600
|
71
101
|
minutes = (epoch / 60 - hours * 60)
|
@@ -81,11 +111,10 @@ module TokiCLI
|
|
81
111
|
def get_db_data
|
82
112
|
db = open_db
|
83
113
|
data = db.execute("SELECT * FROM KKAppActivity")
|
114
|
+
db.close
|
84
115
|
data
|
85
116
|
end
|
86
117
|
|
87
|
-
|
88
|
-
|
89
118
|
def open_db
|
90
119
|
tmp_path = "#{Dir.home}/temp/toki/"
|
91
120
|
db_path = "#{Dir.home}/Library/Containers/us.kkob.Toki/Data/Documents/toki_data.sqlite3"
|
@@ -120,13 +149,13 @@ module TokiCLI
|
|
120
149
|
msg = {}
|
121
150
|
usr = {}
|
122
151
|
app = {}
|
123
|
-
msg[:id] =
|
152
|
+
msg[:id] = obj[0]
|
124
153
|
msg[:thread] = msg[:id]
|
125
154
|
msg[:date] = Time.now
|
126
155
|
usr[:username] = ENV['USERNAME']
|
127
156
|
usr[:name] = usr[:username]
|
128
157
|
usr[:id] = obj[5]
|
129
|
-
app[:id] =
|
158
|
+
app[:id] = msg[:id]
|
130
159
|
app[:uuid] = obj[5]
|
131
160
|
app[:name] = obj[1]
|
132
161
|
app[:active_to] = obj[3]
|
data/lib/TokiCLI/version.rb
CHANGED
data/lib/TokiCLI/view.rb
CHANGED
@@ -9,23 +9,32 @@ module TokiCLI
|
|
9
9
|
end
|
10
10
|
table
|
11
11
|
end
|
12
|
+
def hits_table(list)
|
13
|
+
table = init_table
|
14
|
+
table.title = "Your top apps monitored by Toki"
|
15
|
+
list.each.with_index(1) do |obj,index|
|
16
|
+
table << ["#{index}", "#{obj[0]}", "#{obj[1]}"]
|
17
|
+
end
|
18
|
+
table
|
19
|
+
end
|
12
20
|
def app_table(asked, app_data)
|
13
21
|
table = init_table
|
14
|
-
table.
|
15
|
-
table.
|
22
|
+
table.style = { :width => 100 }
|
23
|
+
table.title = "Toki time tracking for '#{asked}' => #{app_data.first[1][:name]}"
|
24
|
+
table.headings = ['From', 'To', 'Duration', 'Sync id']
|
16
25
|
@index = 0
|
17
26
|
@length = app_data.length - 1
|
18
|
-
app_data.
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
27
|
+
@total = app_data.select {|k,v| k == 'total'}
|
28
|
+
app_data.delete('total')
|
29
|
+
data = app_data.to_a
|
30
|
+
data.sort_by! {|k,v| v[:raw_from] }
|
31
|
+
data.each do |id, log|
|
23
32
|
@index += 1
|
24
|
-
table << ["#{log[:from]}", "#{log[:to]}", "#{log[:duration]}"]
|
33
|
+
table << ["#{log[:from]}", "#{log[:to]}", "#{log[:duration]}", "#{id}"]
|
25
34
|
table << :separator unless @index == @length
|
26
35
|
end
|
27
36
|
table << :separator
|
28
|
-
table << [{ :value => "Total: #{@total}", :colspan =>
|
37
|
+
table << [{ :value => "Total: #{@total['total']}", :colspan => 4, :alignment => :center }]
|
29
38
|
table
|
30
39
|
end
|
31
40
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: TokiCLI
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Eric Dejonckheere
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-04-
|
11
|
+
date: 2014-04-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: thor
|
@@ -94,8 +94,8 @@ dependencies:
|
|
94
94
|
- - ">="
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: '0'
|
97
|
-
description: 'Toki command-line client: read your Toki data from the local database
|
98
|
-
or from the App.net backup channel'
|
97
|
+
description: 'Toki.app command-line client: read your Toki data from the local database
|
98
|
+
or from the App.net backup channel, delete data from both...'
|
99
99
|
email:
|
100
100
|
- eric@aya.io
|
101
101
|
executables:
|
@@ -104,6 +104,7 @@ extensions: []
|
|
104
104
|
extra_rdoc_files: []
|
105
105
|
files:
|
106
106
|
- ".gitignore"
|
107
|
+
- CHANGELOG.md
|
107
108
|
- Gemfile
|
108
109
|
- LICENSE.txt
|
109
110
|
- README.md
|
@@ -119,7 +120,7 @@ files:
|
|
119
120
|
- lib/TokiCLI/status.rb
|
120
121
|
- lib/TokiCLI/version.rb
|
121
122
|
- lib/TokiCLI/view.rb
|
122
|
-
homepage:
|
123
|
+
homepage: https://github.com/ericdke/TokiCLI
|
123
124
|
licenses:
|
124
125
|
- MIT
|
125
126
|
metadata: {}
|
@@ -142,6 +143,6 @@ rubyforge_project:
|
|
142
143
|
rubygems_version: 2.2.2
|
143
144
|
signing_key:
|
144
145
|
specification_version: 4
|
145
|
-
summary: Toki command-line client
|
146
|
+
summary: Toki.app command-line client
|
146
147
|
test_files: []
|
147
148
|
has_rdoc:
|