TokiCLI 0.0.9 → 0.1.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +10 -0
- data/README.md +166 -20
- data/TokiCLI.gemspec +2 -2
- data/lib/API/dbapi.rb +451 -0
- data/lib/API/helpers.rb +151 -0
- data/lib/TokiCLI/app.rb +225 -106
- data/lib/TokiCLI/authorize.rb +6 -4
- data/lib/TokiCLI/export.rb +81 -0
- data/lib/TokiCLI/import.rb +122 -0
- data/lib/TokiCLI/scan.rb +19 -0
- data/lib/TokiCLI/version.rb +1 -1
- data/lib/TokiCLI/view.rb +100 -43
- metadata +10 -7
- data/lib/TokiCLI/module.rb +0 -224
data/lib/API/helpers.rb
ADDED
@@ -0,0 +1,151 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module TokiCLI
|
3
|
+
class Helpers
|
4
|
+
|
5
|
+
attr_accessor :table, :bundles, :bundles_file, :home_path, :toki_path, :db_path
|
6
|
+
attr_reader :db
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
@home_path = Dir.home
|
10
|
+
@toki_path = "#{@home_path}/.TokiCLI"
|
11
|
+
FileUtils.mkdir_p(@toki_path) unless Dir.exist?(@toki_path)
|
12
|
+
@db_path = "#{@home_path}/Library/Containers/us.kkob.Toki/Data/Documents/toki_data.sqlite3"
|
13
|
+
if File.exist? @db_path
|
14
|
+
FileUtils.copy @db_path, "#{@toki_path}/toki_data.sqlite3.bak"
|
15
|
+
@db = Amalgalite::Database.new @db_path
|
16
|
+
else
|
17
|
+
raise 'No DB'
|
18
|
+
end
|
19
|
+
@table = 'KKAppActivity'
|
20
|
+
@bundles_file = "#{@toki_path}/apps.json"
|
21
|
+
@bundles = if File.exist? @bundles_file
|
22
|
+
JSON.parse(File.read @bundles_file)
|
23
|
+
else
|
24
|
+
{}
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
|
29
|
+
# Returns the app name if exists
|
30
|
+
def find_app_name bundle_id
|
31
|
+
if @bundles[bundle_id]
|
32
|
+
@bundles[bundle_id]
|
33
|
+
else
|
34
|
+
nil
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def humanized_date epoch
|
39
|
+
human = seconds_to_time epoch
|
40
|
+
"#{human[:hours]}h #{human[:minutes]}m #{human[:seconds]}s"
|
41
|
+
end
|
42
|
+
|
43
|
+
def seconds_to_time epoch
|
44
|
+
begin
|
45
|
+
hours = epoch / 3600
|
46
|
+
minutes = (epoch / 60 - hours * 60)
|
47
|
+
seconds = (epoch - (minutes * 60 + hours * 3600))
|
48
|
+
{hours: hours, minutes: minutes, seconds: seconds}
|
49
|
+
rescue Exception => e
|
50
|
+
oops e
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def oops error
|
55
|
+
puts "\nOOPS! A gremlin crashed the app.\n\n"
|
56
|
+
puts "STACK: #{caller}\n\n"
|
57
|
+
abort "GREMLIN: #{error}\n\n"
|
58
|
+
end
|
59
|
+
|
60
|
+
def epoch_to_date epoch
|
61
|
+
Time.at(epoch).to_time
|
62
|
+
end
|
63
|
+
|
64
|
+
def sec_to_time sec
|
65
|
+
seconds_to_time sec
|
66
|
+
end
|
67
|
+
|
68
|
+
# Scans for names from bundle ids, saves the file and returns its content
|
69
|
+
def scan params = {}
|
70
|
+
bundle_ids = get_bundle_ids params
|
71
|
+
f = File.new "#{@toki_path}/apps.json", "w"
|
72
|
+
f.write bundle_ids.to_json
|
73
|
+
f.close
|
74
|
+
bundle_ids
|
75
|
+
end
|
76
|
+
|
77
|
+
# Scan for names from bundle ids
|
78
|
+
def get_bundle_ids params = {}
|
79
|
+
@infos = {}
|
80
|
+
get_bundles(get_plists("/Applications/*/Contents/*"), params)
|
81
|
+
get_bundles(get_plists("/Applications/Utilities/*/Contents/*"), params)
|
82
|
+
get_bundles(get_plists("#{@home_path}/Applications/*/Contents/*"), params)
|
83
|
+
@infos
|
84
|
+
end
|
85
|
+
|
86
|
+
def get_bundle_from_name name
|
87
|
+
(@bundles).each do |k,v|
|
88
|
+
if v.downcase =~ /#{name.downcase}/
|
89
|
+
return [v, k]
|
90
|
+
end
|
91
|
+
end
|
92
|
+
[]
|
93
|
+
end
|
94
|
+
|
95
|
+
def meta_nodata
|
96
|
+
{
|
97
|
+
code: 404,
|
98
|
+
error: { message: 'No data returned from the database' }
|
99
|
+
}
|
100
|
+
end
|
101
|
+
|
102
|
+
def json_nodata
|
103
|
+
{
|
104
|
+
meta: meta_nodata,
|
105
|
+
data: {}
|
106
|
+
}.to_json
|
107
|
+
end
|
108
|
+
|
109
|
+
def tracked_bundles apps
|
110
|
+
tracked = JSON.parse(apps)
|
111
|
+
list = []
|
112
|
+
tracked['data']['apps'].each {|v| list << v['bundle']}
|
113
|
+
list
|
114
|
+
end
|
115
|
+
|
116
|
+
private
|
117
|
+
|
118
|
+
def get_plists path
|
119
|
+
Dir.glob(path).select {|f| (File.split f).last == 'Info.plist'}
|
120
|
+
end
|
121
|
+
|
122
|
+
def get_bundles plists, params
|
123
|
+
plists.each do |obj|
|
124
|
+
puts "Analyzing #{obj} ...\n" if params[:verbose] == true
|
125
|
+
begin
|
126
|
+
pl = CFPropertyList::List.new(:file => obj)
|
127
|
+
rescue CFFormatError
|
128
|
+
bundles_error if params[:verbose] == true
|
129
|
+
next
|
130
|
+
rescue NoMethodError
|
131
|
+
bundles_error if params[:verbose] == true
|
132
|
+
next
|
133
|
+
end
|
134
|
+
data = CFPropertyList.native_types(pl.value)
|
135
|
+
name = data['CFBundleName']
|
136
|
+
bundle_id = data['CFBundleIdentifier']
|
137
|
+
if name.nil?
|
138
|
+
name = data['CFBundleExecutable']
|
139
|
+
end
|
140
|
+
next if name.nil?
|
141
|
+
next if bundle_id.nil? || bundle_id.empty?
|
142
|
+
@infos[bundle_id] = name
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
def bundles_error
|
147
|
+
puts "Unable to read the file, skipping...\n"
|
148
|
+
end
|
149
|
+
|
150
|
+
end
|
151
|
+
end
|
data/lib/TokiCLI/app.rb
CHANGED
@@ -2,161 +2,288 @@
|
|
2
2
|
module TokiCLI
|
3
3
|
class App < Thor
|
4
4
|
package_name "TokiCLI"
|
5
|
-
%w{get_messages search_messages get_channels
|
5
|
+
%w{get_messages search_messages get_channels status view authorize export import scan ../API/dbapi}.each {|r| require_relative "#{r}"}
|
6
|
+
|
7
|
+
desc "auth", "App.net login"
|
8
|
+
def auth
|
9
|
+
begin
|
10
|
+
toki = DBAPI.new
|
11
|
+
adn = Authorize.new(toki.helpers.toki_path)
|
12
|
+
adn.authorize
|
13
|
+
rescue Interrupt
|
14
|
+
puts Status.canceled
|
15
|
+
exit
|
16
|
+
end
|
17
|
+
end
|
6
18
|
|
7
19
|
desc "scan", "Scan /Applications to resolve app names"
|
8
20
|
def scan
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
f.write bundle_ids.to_json
|
15
|
-
f.close
|
16
|
-
puts "\nDone.\n\n"
|
17
|
-
end
|
18
|
-
|
19
|
-
desc "total", "Shows the total usage of all apps"
|
20
|
-
option :adn, aliases: '-a', type: :boolean, desc: 'Select ADN channel as source (toki total -a)'
|
21
|
+
scanner = Scan.new DBAPI.new
|
22
|
+
scanner.scan({verbose: true})
|
23
|
+
end
|
24
|
+
|
25
|
+
desc "total", "Total usage of all apps"
|
21
26
|
option :json, aliases: '-j', type: :boolean, desc: 'Export the results as a JSON file'
|
22
27
|
option :csv, aliases: '-c', type: :boolean, desc: 'Export the results as a CSV file'
|
23
28
|
def total
|
24
|
-
toki =
|
25
|
-
apps =
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
+
toki, view = DBAPI.new, View.new
|
30
|
+
apps = JSON.parse toki.apps_total
|
31
|
+
view.total_table apps
|
32
|
+
if (options[:json] || options[:csv])
|
33
|
+
export = Export.new toki, view
|
34
|
+
export.apps_total options, apps, 'total'
|
35
|
+
end
|
29
36
|
end
|
30
37
|
|
31
|
-
desc "top", "
|
32
|
-
option :
|
33
|
-
option :number, aliases: '-n', type: :numeric, desc: 'Specify the number of apps (toki top -n 10)'
|
38
|
+
desc "top", "Most used apps"
|
39
|
+
option :number, aliases: '-n', type: :numeric, desc: 'Specify the number of apps'
|
34
40
|
option :json, aliases: '-j', type: :boolean, desc: 'Export the results as a JSON file'
|
35
41
|
option :csv, aliases: '-c', type: :boolean, desc: 'Export the results as a CSV file'
|
36
42
|
def top
|
37
|
-
toki,
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
43
|
+
toki, view = DBAPI.new, View.new
|
44
|
+
apps = JSON.parse toki.apps_top(options[:number] || 5)
|
45
|
+
view.total_table apps
|
46
|
+
if (options[:json] || options[:csv])
|
47
|
+
export = Export.new toki, view
|
48
|
+
export.apps_total options, apps, 'top'
|
49
|
+
end
|
42
50
|
end
|
43
51
|
|
44
|
-
desc "
|
45
|
-
|
52
|
+
desc "day DATE", "All apps used on a specific day"
|
53
|
+
option :json, aliases: '-j', type: :boolean, desc: 'Export the results as a JSON file'
|
54
|
+
option :csv, aliases: '-c', type: :boolean, desc: 'Export the results as a CSV file'
|
55
|
+
def day(*args)
|
56
|
+
abort(Status.specify_day) if args.empty?
|
46
57
|
begin
|
47
|
-
|
48
|
-
rescue
|
49
|
-
|
50
|
-
|
58
|
+
DateTime.strptime(args[0], '%Y-%m-%d')
|
59
|
+
rescue ArgumentError
|
60
|
+
abort(Status.specify_day)
|
61
|
+
end
|
62
|
+
toki, view = DBAPI.new, View.new
|
63
|
+
apps = JSON.parse toki.apps_day args[0]
|
64
|
+
view.total_table apps
|
65
|
+
if (options[:json] || options[:csv])
|
66
|
+
export = Export.new toki, view
|
67
|
+
export.apps_total options, apps, "day-#{args[0]}"
|
51
68
|
end
|
52
69
|
end
|
53
70
|
|
54
|
-
desc "
|
55
|
-
option :adn, aliases: '-a', type: :boolean, desc: 'Select ADN channel as source (toki log -a)'
|
71
|
+
desc "since DATE", "All apps used since a specific day"
|
56
72
|
option :json, aliases: '-j', type: :boolean, desc: 'Export the results as a JSON file'
|
57
73
|
option :csv, aliases: '-c', type: :boolean, desc: 'Export the results as a CSV file'
|
58
|
-
def
|
59
|
-
abort(Status.
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
74
|
+
def since *args
|
75
|
+
abort(Status.specify_day) if args.empty?
|
76
|
+
begin
|
77
|
+
DateTime.strptime args[0], '%Y-%m-%d'
|
78
|
+
rescue ArgumentError
|
79
|
+
abort Status.specify_day
|
80
|
+
end
|
81
|
+
toki, view = DBAPI.new, View.new
|
82
|
+
apps = JSON.parse toki.apps_since args[0]
|
83
|
+
view.total_table apps
|
84
|
+
if (options[:json] || options[:csv])
|
85
|
+
export = Export.new toki, view
|
86
|
+
export.apps_total options, apps, "since-#{args[0]}"
|
87
|
+
end
|
65
88
|
end
|
66
89
|
|
67
|
-
desc "
|
68
|
-
option :adn, aliases: '-a', type: :boolean, desc: 'Select ADN channel as source (toki day 2014-04-19 -a)'
|
90
|
+
desc "before DATE", "All apps used before a specific day"
|
69
91
|
option :json, aliases: '-j', type: :boolean, desc: 'Export the results as a JSON file'
|
70
92
|
option :csv, aliases: '-c', type: :boolean, desc: 'Export the results as a CSV file'
|
71
|
-
def
|
93
|
+
def before *args
|
72
94
|
abort(Status.specify_day) if args.empty?
|
73
95
|
begin
|
74
|
-
|
96
|
+
DateTime.strptime args[0], '%Y-%m-%d'
|
75
97
|
rescue ArgumentError
|
76
|
-
abort
|
98
|
+
abort Status.specify_day
|
99
|
+
end
|
100
|
+
toki, view = DBAPI.new, View.new
|
101
|
+
apps = JSON.parse toki.apps_before args[0]
|
102
|
+
view.total_table apps
|
103
|
+
if (options[:json] || options[:csv])
|
104
|
+
export = Export.new toki, view
|
105
|
+
export.apps_total options, apps, "before-#{args[0]}"
|
77
106
|
end
|
78
|
-
toki, entries = init(options)
|
79
|
-
day_data = toki.get_day(date, entries, options)
|
80
|
-
clear
|
81
|
-
View.new.day_table(args[0], day_data)
|
82
|
-
export(options, day_data, "toki-day-#{args[0]}") if (options[:json] || options[:csv])
|
83
107
|
end
|
84
108
|
|
85
|
-
desc "range
|
86
|
-
option :adn, aliases: '-a', type: :boolean, desc: 'Select ADN channel as source (toki range 2014-04-16 2014-04-18 -a)'
|
109
|
+
desc "range DATE1 DATE2", "All apps used between two specific days"
|
87
110
|
option :json, aliases: '-j', type: :boolean, desc: 'Export the results as a JSON file'
|
88
111
|
option :csv, aliases: '-c', type: :boolean, desc: 'Export the results as a CSV file'
|
89
112
|
def range(*args)
|
90
113
|
abort(Status.specify_range) if args.empty? || args.length != 2
|
91
114
|
begin
|
92
|
-
|
93
|
-
|
115
|
+
DateTime.strptime(args[0], '%Y-%m-%d')
|
116
|
+
DateTime.strptime(args[1], '%Y-%m-%d')
|
94
117
|
rescue ArgumentError
|
95
118
|
abort(Status.specify_range)
|
96
119
|
end
|
97
|
-
toki,
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
120
|
+
toki, view = DBAPI.new, View.new
|
121
|
+
apps = JSON.parse toki.apps_range args[0], args[1]
|
122
|
+
view.total_table apps
|
123
|
+
if (options[:json] || options[:csv])
|
124
|
+
export = Export.new toki, view
|
125
|
+
export.apps_total options, apps, "range-#{args[0]}_#{args[1]}"
|
126
|
+
end
|
102
127
|
end
|
103
128
|
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
end
|
129
|
+
desc "log APP", "Complete log for an app"
|
130
|
+
option :json, aliases: '-j', type: :boolean, desc: 'Export the results as a JSON file'
|
131
|
+
option :csv, aliases: '-c', type: :boolean, desc: 'Export the results as a CSV file'
|
132
|
+
option :bundle, aliases: '-b', type: :boolean, desc: "Specify the complete bundle identifier (in case the app name resolve doesn't work)"
|
133
|
+
def log(*args)
|
134
|
+
abort(Status.specify_name) if args.empty?
|
135
|
+
asked = args[0]
|
136
|
+
toki = DBAPI.new
|
137
|
+
view = View.new
|
138
|
+
log = if options[:bundle]
|
139
|
+
JSON.parse toki.bundle_log asked
|
116
140
|
else
|
117
|
-
|
141
|
+
JSON.parse toki.name_log asked
|
142
|
+
end
|
143
|
+
view.app_table asked, log
|
144
|
+
if (options[:json] || options[:csv])
|
145
|
+
export = Export.new toki, view
|
146
|
+
export.log options, log, "log-#{log['data']['bundle'].gsub('.', '_')}"
|
118
147
|
end
|
119
|
-
puts "File converted and exported to #{name}\n\n"
|
120
148
|
end
|
121
149
|
|
122
|
-
|
123
|
-
|
124
|
-
|
150
|
+
desc "app APP", "Total tracked time for an app"
|
151
|
+
option :json, aliases: '-j', type: :boolean, desc: 'Export the results as a JSON file'
|
152
|
+
option :csv, aliases: '-c', type: :boolean, desc: 'Export the results as a CSV file'
|
153
|
+
option :bundle, aliases: '-b', type: :boolean, desc: "Specify the complete bundle identifier (in case the app name resolve doesn't work)"
|
154
|
+
def app *args
|
155
|
+
abort(Status.specify_name) if args.empty?
|
156
|
+
asked = args[0]
|
157
|
+
toki = DBAPI.new
|
158
|
+
view = View.new
|
159
|
+
app = if options[:bundle]
|
160
|
+
JSON.parse toki.bundle_total asked
|
161
|
+
else
|
162
|
+
JSON.parse toki.name_total asked
|
163
|
+
end
|
164
|
+
view.total_table app
|
165
|
+
if (options[:json] || options[:csv])
|
166
|
+
export = Export.new toki, view
|
167
|
+
export.app_total options, app, "app-#{app['data']['bundle'].gsub('.', '_')}"
|
168
|
+
end
|
125
169
|
end
|
126
170
|
|
127
|
-
|
128
|
-
|
171
|
+
desc "app_before APP DATE", "Total tracked time for an app before a specific day"
|
172
|
+
option :json, aliases: '-j', type: :boolean, desc: 'Export the results as a JSON file'
|
173
|
+
option :csv, aliases: '-c', type: :boolean, desc: 'Export the results as a CSV file'
|
174
|
+
option :bundle, aliases: '-b', type: :boolean, desc: "Specify the complete bundle identifier (in case the app name resolve doesn't work)"
|
175
|
+
def app_before *args
|
176
|
+
abort('Error') if args.empty? #TODO: better and more complete
|
177
|
+
asked = args[0]
|
178
|
+
date = args[1]
|
179
|
+
begin
|
180
|
+
DateTime.strptime args[1], '%Y-%m-%d'
|
181
|
+
rescue ArgumentError
|
182
|
+
abort Status.specify_day
|
183
|
+
end
|
184
|
+
toki = DBAPI.new
|
185
|
+
view = View.new
|
186
|
+
app = if options[:bundle]
|
187
|
+
JSON.parse toki.bundle_total_before asked, date
|
188
|
+
else
|
189
|
+
JSON.parse toki.name_total_before asked, date
|
190
|
+
end
|
191
|
+
view.total_table app
|
192
|
+
if (options[:json] || options[:csv])
|
193
|
+
export = Export.new toki, view
|
194
|
+
export.app_total options, app, "app_before-#{app['data']['bundle'].gsub('.', '_')}_#{args[1]}"
|
195
|
+
end
|
129
196
|
end
|
130
197
|
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
198
|
+
desc "app_since APP DATE", "Total tracked time for an app since a specific day"
|
199
|
+
option :json, aliases: '-j', type: :boolean, desc: 'Export the results as a JSON file'
|
200
|
+
option :csv, aliases: '-c', type: :boolean, desc: 'Export the results as a CSV file'
|
201
|
+
option :bundle, aliases: '-b', type: :boolean, desc: "Specify the complete bundle identifier (in case the app name resolve doesn't work)"
|
202
|
+
def app_since *args
|
203
|
+
abort('Error') if args.empty? #TODO: better and more complete
|
204
|
+
asked = args[0]
|
205
|
+
date = args[1]
|
206
|
+
begin
|
207
|
+
DateTime.strptime args[1], '%Y-%m-%d'
|
208
|
+
rescue ArgumentError
|
209
|
+
abort Status.specify_day
|
210
|
+
end
|
211
|
+
toki = DBAPI.new
|
212
|
+
view = View.new
|
213
|
+
app = if options[:bundle]
|
214
|
+
JSON.parse toki.bundle_total_since asked, date
|
215
|
+
else
|
216
|
+
JSON.parse toki.name_total_since asked, date
|
217
|
+
end
|
218
|
+
view.total_table app
|
219
|
+
if (options[:json] || options[:csv])
|
220
|
+
export = Export.new toki, view
|
221
|
+
export.app_total options, app, "app_since-#{app['data']['bundle'].gsub('.', '_')}_#{date}"
|
222
|
+
end
|
135
223
|
end
|
136
224
|
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
225
|
+
desc "app_day APP DATE", "Total tracked time for an app on a specific day"
|
226
|
+
option :json, aliases: '-j', type: :boolean, desc: 'Export the results as a JSON file'
|
227
|
+
option :csv, aliases: '-c', type: :boolean, desc: 'Export the results as a CSV file'
|
228
|
+
option :bundle, aliases: '-b', type: :boolean, desc: "Specify the complete bundle identifier (in case the app name resolve doesn't work)"
|
229
|
+
def app_day *args
|
230
|
+
abort('Error') if args.empty? #TODO: better and more complete
|
231
|
+
asked = args[0]
|
232
|
+
date = args[1]
|
233
|
+
begin
|
234
|
+
DateTime.strptime args[1], '%Y-%m-%d'
|
235
|
+
rescue ArgumentError
|
236
|
+
abort Status.specify_day
|
237
|
+
end
|
238
|
+
toki = DBAPI.new
|
239
|
+
view = View.new
|
240
|
+
app = if options[:bundle]
|
241
|
+
JSON.parse toki.bundle_total_day asked, date
|
242
|
+
else
|
243
|
+
JSON.parse toki.name_total_day asked, date
|
244
|
+
end
|
245
|
+
view.total_table app
|
246
|
+
if (options[:json] || options[:csv])
|
247
|
+
export = Export.new toki, view
|
248
|
+
export.app_total options, app, "app_day-#{app['data']['bundle'].gsub('.', '_')}_#{date}"
|
249
|
+
end
|
141
250
|
end
|
142
251
|
|
143
|
-
|
252
|
+
desc "app_range APP DATE1 DATE2", "total tracked time for an app between two specific days"
|
253
|
+
option :json, aliases: '-j', type: :boolean, desc: 'Export the results as a JSON file'
|
254
|
+
option :csv, aliases: '-c', type: :boolean, desc: 'Export the results as a CSV file'
|
255
|
+
option :bundle, aliases: '-b', type: :boolean, desc: "Specify the complete bundle identifier (in case the app name resolve doesn't work)"
|
256
|
+
def app_range *args
|
257
|
+
abort('Error') if args.empty? || args.length != 3
|
144
258
|
begin
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
259
|
+
DateTime.strptime(args[1], '%Y-%m-%d')
|
260
|
+
DateTime.strptime(args[2], '%Y-%m-%d')
|
261
|
+
rescue ArgumentError
|
262
|
+
abort(Status.specify_range)
|
263
|
+
end
|
264
|
+
toki = DBAPI.new
|
265
|
+
view = View.new
|
266
|
+
app = if options[:bundle]
|
267
|
+
JSON.parse toki.bundle_total_range args[0], args[1], args[2]
|
268
|
+
else
|
269
|
+
JSON.parse toki.name_total_range args[0], args[1], args[2]
|
270
|
+
end
|
271
|
+
view.total_table app
|
272
|
+
if (options[:json] || options[:csv])
|
273
|
+
export = Export.new toki, view
|
274
|
+
export.app_total options, app, "app_range-#{app['data']['bundle'].gsub('.', '_')}_#{args[1]}_#{args[2]}"
|
150
275
|
end
|
151
276
|
end
|
152
277
|
|
153
|
-
|
154
|
-
|
278
|
+
desc "restore", "Restore data from App.net and rebuild the Toki.app database"
|
279
|
+
def restore
|
280
|
+
toki_api = DBAPI.new
|
281
|
+
view = View.new
|
282
|
+
import = Import.new toki_api, view
|
283
|
+
import.restore get_token, get_channel_id
|
155
284
|
end
|
156
285
|
|
157
|
-
|
158
|
-
TokiCLI::Toki.new("#{get_token}", channel_id)
|
159
|
-
end
|
286
|
+
private
|
160
287
|
|
161
288
|
def get_token
|
162
289
|
filepath = Dir.home + '/.TokiCLI/config.json'
|
@@ -182,13 +309,5 @@ module TokiCLI
|
|
182
309
|
abort Status.no_channel
|
183
310
|
end
|
184
311
|
|
185
|
-
def clear
|
186
|
-
puts "\e[H\e[2J"
|
187
|
-
end
|
188
|
-
|
189
|
-
def get_all(t, options)
|
190
|
-
content = t.get_content(options)
|
191
|
-
t.all_data(content)
|
192
|
-
end
|
193
312
|
end
|
194
313
|
end
|