TokiCLI 0.2.1 → 0.3.0

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.
Files changed (129) hide show
  1. checksums.yaml +4 -4
  2. data/.coveralls.yml +1 -0
  3. data/.gitignore +9 -17
  4. data/.rspec +3 -0
  5. data/.travis.yml +3 -0
  6. data/CHANGELOG.md +4 -0
  7. data/README.md +99 -163
  8. data/Rakefile +5 -0
  9. data/TokiCLI.gemspec +5 -4
  10. data/bin/toki +2 -2
  11. data/lib/API/helpers.rb +27 -170
  12. data/lib/API/toki_api.rb +227 -0
  13. data/lib/API/toki_db.rb +67 -0
  14. data/lib/TokiCLI.rb +270 -5
  15. data/lib/TokiCLI/adnimport.rb +202 -0
  16. data/lib/TokiCLI/fileops.rb +187 -0
  17. data/lib/TokiCLI/status.rb +49 -37
  18. data/lib/TokiCLI/version.rb +1 -1
  19. data/lib/TokiCLI/view.rb +133 -86
  20. data/lib/TokiServer/.bowerrc +3 -0
  21. data/lib/TokiServer/.gitignore +2 -0
  22. data/lib/TokiServer/Gemfile +1 -0
  23. data/lib/TokiServer/bower.json +0 -0
  24. data/lib/TokiServer/bower_components/fastclick/.bower.json +4 -4
  25. data/lib/TokiServer/bower_components/fastclick/bower.json +1 -1
  26. data/lib/TokiServer/bower_components/fastclick/lib/fastclick.js +33 -2
  27. data/lib/TokiServer/bower_components/foundation/.bower.json +5 -4
  28. data/lib/TokiServer/bower_components/foundation/bower.json +2 -1
  29. data/lib/TokiServer/bower_components/foundation/css/foundation.css +2173 -922
  30. data/lib/TokiServer/bower_components/foundation/css/foundation.css.map +7 -0
  31. data/lib/TokiServer/bower_components/foundation/css/normalize.css +53 -16
  32. data/lib/TokiServer/bower_components/foundation/css/normalize.css.map +7 -0
  33. data/lib/TokiServer/bower_components/foundation/js/foundation.js +782 -542
  34. data/lib/TokiServer/bower_components/foundation/js/foundation.min.js +4 -3
  35. data/lib/TokiServer/bower_components/foundation/js/foundation/foundation.abide.js +45 -31
  36. data/lib/TokiServer/bower_components/foundation/js/foundation/foundation.accordion.js +12 -6
  37. data/lib/TokiServer/bower_components/foundation/js/foundation/foundation.alert.js +5 -5
  38. data/lib/TokiServer/bower_components/foundation/js/foundation/foundation.clearing.js +34 -10
  39. data/lib/TokiServer/bower_components/foundation/js/foundation/foundation.dropdown.js +83 -29
  40. data/lib/TokiServer/bower_components/foundation/js/foundation/foundation.equalizer.js +3 -3
  41. data/lib/TokiServer/bower_components/foundation/js/foundation/foundation.interchange.js +25 -12
  42. data/lib/TokiServer/bower_components/foundation/js/foundation/foundation.joyride.js +112 -40
  43. data/lib/TokiServer/bower_components/foundation/js/foundation/foundation.js +19 -5
  44. data/lib/TokiServer/bower_components/foundation/js/foundation/foundation.magellan.js +22 -11
  45. data/lib/TokiServer/bower_components/foundation/js/foundation/foundation.offcanvas.js +52 -8
  46. data/lib/TokiServer/bower_components/foundation/js/foundation/foundation.orbit.js +133 -271
  47. data/lib/TokiServer/bower_components/foundation/js/foundation/foundation.reveal.js +27 -20
  48. data/lib/TokiServer/bower_components/foundation/js/foundation/foundation.slider.js +73 -33
  49. data/lib/TokiServer/bower_components/foundation/js/foundation/foundation.tab.js +88 -31
  50. data/lib/TokiServer/bower_components/foundation/js/foundation/foundation.tooltip.js +7 -5
  51. data/lib/TokiServer/bower_components/foundation/js/foundation/foundation.topbar.js +44 -24
  52. data/lib/TokiServer/bower_components/foundation/js/vendor/fastclick.js +2 -2
  53. data/lib/TokiServer/bower_components/foundation/js/vendor/modernizr.js +2 -2
  54. data/lib/TokiServer/bower_components/foundation/scss/foundation.scss +38 -38
  55. data/lib/TokiServer/bower_components/foundation/scss/foundation/_functions.scss +3 -3
  56. data/lib/TokiServer/bower_components/foundation/scss/foundation/_settings.scss +417 -271
  57. data/lib/TokiServer/bower_components/foundation/scss/foundation/components/_accordion.scss +110 -6
  58. data/lib/TokiServer/bower_components/foundation/scss/foundation/components/_alert-boxes.scss +2 -2
  59. data/lib/TokiServer/bower_components/foundation/scss/foundation/components/_block-grid.scss +2 -2
  60. data/lib/TokiServer/bower_components/foundation/scss/foundation/components/_breadcrumbs.scss +8 -3
  61. data/lib/TokiServer/bower_components/foundation/scss/foundation/components/_button-groups.scss +99 -9
  62. data/lib/TokiServer/bower_components/foundation/scss/foundation/components/_buttons.scss +66 -28
  63. data/lib/TokiServer/bower_components/foundation/scss/foundation/components/_clearing.scss +5 -5
  64. data/lib/TokiServer/bower_components/foundation/scss/foundation/components/_dropdown-buttons.scss +4 -4
  65. data/lib/TokiServer/bower_components/foundation/scss/foundation/components/_dropdown.scss +48 -35
  66. data/lib/TokiServer/bower_components/foundation/scss/foundation/components/_forms.scss +104 -32
  67. data/lib/TokiServer/bower_components/foundation/scss/foundation/components/_global.scss +48 -30
  68. data/lib/TokiServer/bower_components/foundation/scss/foundation/components/_grid.scss +19 -4
  69. data/lib/TokiServer/bower_components/foundation/scss/foundation/components/_icon-bar.scss +293 -0
  70. data/lib/TokiServer/bower_components/foundation/scss/foundation/components/_joyride.scss +11 -9
  71. data/lib/TokiServer/bower_components/foundation/scss/foundation/components/_keystrokes.scss +4 -4
  72. data/lib/TokiServer/bower_components/foundation/scss/foundation/components/_labels.scss +4 -2
  73. data/lib/TokiServer/bower_components/foundation/scss/foundation/components/_magellan.scss +1 -1
  74. data/lib/TokiServer/bower_components/foundation/scss/foundation/components/_offcanvas.scss +193 -35
  75. data/lib/TokiServer/bower_components/foundation/scss/foundation/components/_orbit.scss +92 -147
  76. data/lib/TokiServer/bower_components/foundation/scss/foundation/components/_pagination.scss +22 -10
  77. data/lib/TokiServer/bower_components/foundation/scss/foundation/components/_panels.scss +10 -7
  78. data/lib/TokiServer/bower_components/foundation/scss/foundation/components/_pricing-tables.scss +11 -11
  79. data/lib/TokiServer/bower_components/foundation/scss/foundation/components/_progress-bars.scss +2 -2
  80. data/lib/TokiServer/bower_components/foundation/scss/foundation/components/_range-slider.scss +29 -9
  81. data/lib/TokiServer/bower_components/foundation/scss/foundation/components/_reveal.scss +60 -56
  82. data/lib/TokiServer/bower_components/foundation/scss/foundation/components/_side-nav.scss +3 -2
  83. data/lib/TokiServer/bower_components/foundation/scss/foundation/components/_split-buttons.scss +2 -2
  84. data/lib/TokiServer/bower_components/foundation/scss/foundation/components/_sub-nav.scss +2 -2
  85. data/lib/TokiServer/bower_components/foundation/scss/foundation/components/_switches.scss +226 -0
  86. data/lib/TokiServer/bower_components/foundation/scss/foundation/components/_tables.scss +13 -7
  87. data/lib/TokiServer/bower_components/foundation/scss/foundation/components/_tabs.scss +22 -8
  88. data/lib/TokiServer/bower_components/foundation/scss/foundation/components/_thumbs.scss +2 -4
  89. data/lib/TokiServer/bower_components/foundation/scss/foundation/components/_toolbar.scss +70 -0
  90. data/lib/TokiServer/bower_components/foundation/scss/foundation/components/_tooltips.scss +9 -7
  91. data/lib/TokiServer/bower_components/foundation/scss/foundation/components/_top-bar.scss +77 -44
  92. data/lib/TokiServer/bower_components/foundation/scss/foundation/components/_type.scss +21 -9
  93. data/lib/TokiServer/bower_components/modernizr/.bower.json +4 -4
  94. data/lib/TokiServer/bower_components/modernizr/feature-detects/workers-blobworkers.js +2 -2
  95. data/lib/TokiServer/bower_components/modernizr/grunt.js +1 -1
  96. data/lib/TokiServer/bower_components/modernizr/modernizr.js +2 -2
  97. data/lib/TokiServer/config.rb +0 -0
  98. data/lib/TokiServer/humans.txt +0 -0
  99. data/lib/TokiServer/{itunesicon.rb → itunesicons.rb} +25 -23
  100. data/lib/TokiServer/js/app.js +0 -0
  101. data/lib/TokiServer/public/stylesheets/app.css +2636 -1610
  102. data/lib/TokiServer/robots.txt +0 -0
  103. data/lib/TokiServer/scss/_settings.scss +0 -0
  104. data/lib/TokiServer/scss/app.scss +7 -1
  105. data/lib/TokiServer/tokiserver.rb +239 -244
  106. data/lib/TokiServer/views/activity.erb +42 -0
  107. data/lib/TokiServer/views/apps_total.erb +8 -2
  108. data/lib/TokiServer/views/error.erb +13 -4
  109. data/lib/TokiServer/views/index.erb +36 -27
  110. data/lib/TokiServer/views/logs_total.erb +34 -0
  111. data/spec/TokiCLI_spec.rb +354 -0
  112. data/spec/mock/mock.sqlite3 +0 -0
  113. data/spec/spec_helper.rb +26 -0
  114. metadata +78 -23
  115. data/lib/API/dbapi.rb +0 -488
  116. data/lib/TokiCLI/app.rb +0 -389
  117. data/lib/TokiCLI/authorize.rb +0 -77
  118. data/lib/TokiCLI/export.rb +0 -81
  119. data/lib/TokiCLI/get_channels.rb +0 -22
  120. data/lib/TokiCLI/get_messages.rb +0 -32
  121. data/lib/TokiCLI/import.rb +0 -122
  122. data/lib/TokiCLI/scan.rb +0 -19
  123. data/lib/TokiCLI/search_messages.rb +0 -23
  124. data/lib/TokiServer/README.md +0 -37
  125. data/lib/TokiServer/bower_components/foundation/scss/foundation/components/_reveal-new.scss +0 -0
  126. data/lib/TokiServer/bower_components/foundation/scss/foundation/components/_switch.scss +0 -294
  127. data/lib/TokiServer/views/name_log.erb +0 -50
  128. data/lib/TokiServer/views/name_split.erb +0 -37
  129. data/lib/TokiServer/views/name_total.erb +0 -34
@@ -18,8 +18,6 @@ Gem::Specification.new do |spec|
18
18
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
19
  spec.require_paths = ["lib"]
20
20
 
21
- spec.required_ruby_version = '>= 2.0.0'
22
-
23
21
  spec.add_dependency "thor", "~> 0.18"
24
22
  spec.add_dependency "rest-client", "~> 1.6"
25
23
  spec.add_dependency "amalgalite", "~> 1.3"
@@ -28,7 +26,10 @@ Gem::Specification.new do |spec|
28
26
  spec.add_dependency 'sinatra', '~> 1.4', '>= 1.4.5'
29
27
  spec.add_dependency "thin", "~> 1.6"
30
28
  spec.add_dependency 'sinatra-assetpack', "~> 0.3", '>= 0.3.2'
29
+ spec.add_dependency "sinatra-contrib", '~> 1.4', '>= 1.4.2'
31
30
 
32
- spec.add_development_dependency "bundler", "~> 1.6"
33
- spec.add_development_dependency "rake"
31
+ spec.add_development_dependency "bundler", "~> 1.7"
32
+ spec.add_development_dependency "rake", "~> 10.0"
33
+ spec.add_development_dependency "rspec", "~> 3.0"
34
+ spec.add_development_dependency "coveralls"
34
35
  end
data/bin/toki CHANGED
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env ruby
2
2
  # encoding: utf-8
3
3
  # Toki command-line client
4
- # Author: Eric Dejonckheere (http://app.net/ericd)
5
- # Toki by: Keitaroh Kobayashi (http://app.net/keita)
4
+ # TokiCLI by: Eric Dejonckheere (http://app.net/ericd)
5
+ # Toki.app by: Keitaroh Kobayashi (http://app.net/keita)
6
6
 
7
7
  $PROGRAM_NAME = 'toki'
8
8
  require_relative '../lib/TokiCLI'
@@ -1,195 +1,52 @@
1
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
2
 
38
- def humanized_date epoch
39
- human = seconds_to_time epoch
40
- "#{'%.2d' % human[:hours]}h #{'%.2d' % human[:minutes]}m #{'%.2d' % human[:seconds]}s"
41
- end
3
+ module TokiCLI
42
4
 
43
- def humanized_minutes_seconds epoch
44
- human = seconds_to_time epoch
45
- "#{'%.2d' % human[:minutes]}m #{'%.2d' % human[:seconds]}s"
46
- end
5
+ class Helpers
47
6
 
48
- def seconds_to_time epoch
7
+ def sec_to_time(secs)
49
8
  begin
50
- hours = epoch / 3600
51
- minutes = (epoch / 60 - hours * 60)
52
- seconds = (epoch - (minutes * 60 + hours * 3600))
53
- {hours: hours, minutes: minutes, seconds: seconds}
9
+ hours = secs / 3600
10
+ minutes = (secs / 60 - hours * 60)
11
+ seconds = (secs - (minutes * 60 + hours * 3600))
12
+ {'hours' => hours, 'minutes' => minutes, 'seconds' => seconds}
54
13
  rescue Exception => e
55
- oops e
14
+ raise e, Status.wtf
56
15
  end
57
16
  end
58
17
 
59
- def oops error
60
- puts "\nOOPS! A gremlin crashed the app.\n\n"
61
- puts "STACK: #{caller}\n\n"
62
- puts "GREMLIN: #{error}\n\n"
63
- end
64
-
65
- def epoch_to_date epoch
18
+ def epoch_to_date(epoch)
66
19
  Time.at(epoch).to_time
67
20
  end
68
21
 
69
- def sec_to_time sec
70
- seconds_to_time sec
71
- end
72
-
73
- # Scans for names from bundle ids, saves the file and returns its content
74
- def scan params = {}
75
- bundle_ids = get_bundle_ids params
76
- f = File.new "#{@toki_path}/apps.json", "w"
77
- f.write bundle_ids.to_json
78
- f.close
79
- bundle_ids
80
- end
81
-
82
- def scan_app_icons
83
- @bundles.each do |k,v|
84
- gs = v.gsub(' ', '\ ')
85
- where = "/Applications/#{gs}.app/Contents/Resources/*.icns"
86
- files = Dir.glob(where)
87
- candidates = files.select {|f| File.basename(f) == "Icon.icns" || File.basename(f, ".icns").downcase =~ /#{v.downcase}/}
88
- puts "#{v} => #{candidates}"
89
- end
90
- end
91
-
92
- # Scan for names from bundle ids
93
- def get_bundle_ids params = {}
94
- @infos = {}
95
- get_bundles(get_plists("/Applications/*/Contents/*"), params)
96
- get_bundles(get_plists("/Applications/Utilities/*/Contents/*"), params)
97
- get_bundles(get_plists("#{@home_path}/Applications/*/Contents/*"), params)
98
- specials = {
99
- 'com.evernote.EvernoteHelper' => 'Evernote Helper',
100
- 'com.apple.finder' => 'Finder',
101
- 'com.apple.ReportPanic' => 'Kernel Panic',
102
- 'com.apple.coreservices.uiagent' => 'CoreServices UIAgent',
103
- 'com.apple.installer' => 'Apple Installer',
104
- 'com.apple.frameworks.diskimages.diuiagent' => 'Apple Disk Images Agent',
105
- 'com.mediaatelier.CheatSheet' => 'Cheat Sheet',
106
- 'com.vyprvpn.authorization' => 'VyprVPN',
107
- 'com.apple.WebKit.WebContent' => 'Safari module',
108
- 'com.apple.ProblemReporter' => 'Apple Problem Reporter',
109
- 'org.andymatuschak.sparkle.finish-installation' => 'Sparkle Install',
110
- 'com.noodlesoft.HazelHelper' => 'Hazel Helper',
111
- 'de.appsolute.MAMP' => 'MAMP',
112
- 'com.apple.KeyboardSetupAssistant' => 'Apple Keyboard Setup Assistant',
113
- 'com.apple.NetAuthAgent' => 'Apple Net Auth Agent',
114
- 'com.adobe.acc.AdobeCreativeCloud' => 'Adobe Creative Cloud',
115
- 'com.apple.iphonesimulator' => 'Apple iPhone Simulator',
116
- 'com.macromates.TextMate.preview' => 'TextMate',
117
- 'com.alfredapp.Alfred' => 'Alfred',
118
- 'com.runningwithcrayons.Alfred-Preferences' => 'Alfred Preferences',
119
- 'com.apple.WebKit.PluginProcess' => 'Safari Plugin',
120
- 'com.apple.ScreenSharing' => 'Apple Screen Sharing',
121
- 'org.virtualbox.app.VirtualBoxVM' => 'VirtualBox',
122
- '2BUA8C4S2C.com.agilebits.onepassword-osx-helper' => '1Password Helper'
123
- }
124
- specials.each do |k, v|
125
- @infos[k] = v
126
- end
127
- @infos
128
- end
129
-
130
- def get_bundle_from_name name
131
- (@bundles).each do |k,v|
132
- if v.downcase =~ /#{name.downcase}/
133
- return [v, k]
134
- end
22
+ def check_date_validity(day)
23
+ begin
24
+ DateTime.strptime(day, '%Y-%m-%d')
25
+ rescue ArgumentError, TypeError => e
26
+ false
135
27
  end
136
- []
137
- end
138
-
139
- def meta_nodata
140
- {
141
- code: 404,
142
- message: 'No data returned from the database'
143
- }
144
- end
145
-
146
- def json_nodata
147
- {
148
- meta: meta_nodata,
149
- data: {}
150
- }.to_json
151
28
  end
152
29
 
153
- def tracked_bundles apps
154
- tracked = JSON.parse(apps)
155
- list = []
156
- tracked['data']['apps'].each {|v| list << v['bundle']}
157
- list
30
+ def readable_time(obj)
31
+ "#{obj['hours']}h #{'%.2d' % obj['minutes']}m #{'%.2d' % obj['seconds']}s"
158
32
  end
159
33
 
160
- private
161
-
162
- def get_plists path
163
- Dir.glob(path).select {|f| (File.split f).last == 'Info.plist'}
34
+ def readable_time_log(obj)
35
+ "#{'%.2d' % obj['minutes']}m #{'%.2d' % obj['seconds']}s"
164
36
  end
165
37
 
166
- def get_bundles plists, params
167
- plists.each do |obj|
168
- puts "Analyzing #{obj} ...\n" if params[:verbose] == true
169
- begin
170
- pl = CFPropertyList::List.new(:file => obj)
171
- rescue CFFormatError
172
- bundles_error if params[:verbose] == true
173
- next
174
- rescue NoMethodError
175
- bundles_error if params[:verbose] == true
176
- next
177
- end
178
- data = CFPropertyList.native_types(pl.value)
179
- name = data['CFBundleName']
180
- bundle_id = data['CFBundleIdentifier']
181
- if name.nil?
182
- name = data['CFBundleExecutable']
183
- end
184
- next if name.nil?
185
- next if bundle_id.nil? || bundle_id.empty?
186
- @infos[bundle_id] = name
187
- end
38
+ def calc_apps_total(data)
39
+ total = 0
40
+ data.each { |obj| total += obj['total']['seconds'] }
41
+ return total
188
42
  end
189
43
 
190
- def bundles_error
191
- puts "Unable to read the file, skipping...\n"
44
+ def calc_logs_total(data)
45
+ total = 0
46
+ data.each { |k, v| total += v['duration']['seconds'] }
47
+ return total
192
48
  end
193
49
 
194
50
  end
51
+
195
52
  end
@@ -0,0 +1,227 @@
1
+ # encoding: utf-8
2
+
3
+ module TokiCLI
4
+
5
+ class TokiAPI
6
+
7
+ require 'json'
8
+ require 'amalgalite'
9
+
10
+ require_relative 'helpers'
11
+ require_relative 'toki_db'
12
+
13
+ attr_reader :bundles, :response, :helpers
14
+
15
+ def initialize(db_path, bundles = nil)
16
+ @db = TokiCLI::TokiDB.new(db_path)
17
+ @helpers = TokiCLI::Helpers.new
18
+ @bundles = bundles
19
+ end
20
+
21
+ def apps_total
22
+ request = {command: 'apps_total', type: 'apps', args: [], processed_at: Time.now}
23
+ resp = @db.apps_total
24
+ return response_wrapper(request, resp) { make_apps_list(resp) }
25
+ end
26
+
27
+ def apps_top(number = 5)
28
+ request = {command: 'apps_top', type: 'apps', args: [number], processed_at: Time.now}
29
+ resp = @db.apps_total
30
+ return invalid_response(request) if resp.empty?
31
+ index = -number
32
+ list = make_apps_list(resp)[index..-1]
33
+ @response = make_basic_response(request, list)
34
+ end
35
+
36
+ def apps_day(day)
37
+ request = {command: 'apps_day', type: 'apps', args: [day], processed_at: Time.now}
38
+ date = @helpers.check_date_validity(day)
39
+ return invalid_response(request) if date == false
40
+ resp = @db.apps_range(date.to_time.to_i, date.next_day.to_time.to_i)
41
+ return response_wrapper(request, resp) { make_apps_list(resp) }
42
+ end
43
+
44
+ def apps_range(day1, day2)
45
+ request = {command: 'apps_range', type: 'apps', args: [day1, day2], processed_at: Time.now}
46
+ starting, ending = @helpers.check_date_validity(day1), @helpers.check_date_validity(day2)
47
+ return invalid_response(request) if starting == false || ending == false || starting > ending
48
+ resp = @db.apps_range(starting.to_time.to_i, ending.to_time.to_i)
49
+ return response_wrapper(request, resp) { make_apps_list(resp) }
50
+ end
51
+
52
+ def apps_since(day)
53
+ request = {command: 'apps_since', type: 'apps', args: [day], processed_at: Time.now}
54
+ starting = @helpers.check_date_validity(day)
55
+ return invalid_response(request) if starting == false
56
+ resp = @db.apps_since(starting.to_time.to_i)
57
+ return response_wrapper(request, resp) { make_apps_list(resp) }
58
+ end
59
+
60
+ def apps_before(day)
61
+ request = {command: 'apps_before', type: 'apps', args: [day], processed_at: Time.now}
62
+ ending = @helpers.check_date_validity(day)
63
+ return invalid_response(request) if ending == false
64
+ resp = @db.apps_before(ending.to_time.to_i)
65
+ return response_wrapper(request, resp) { make_apps_list(resp) }
66
+ end
67
+
68
+ def bundle_log(bundle)
69
+ request = {command: 'bundle_log', type: 'log', args: [bundle], processed_at: Time.now}
70
+ resp = @db.bundle_log(bundle)
71
+ return response_wrapper(request, resp) { make_log_objects(resp) }
72
+ end
73
+
74
+ def bundle_log_since(bundle, date)
75
+ request = {command: 'bundle_log_since', type: 'log', args: [bundle, date], processed_at: Time.now}
76
+ starting = @helpers.check_date_validity(date)
77
+ return invalid_response(request) if starting == false
78
+ resp = @db.bundle_log_since(bundle, starting.to_time.to_i)
79
+ return response_wrapper(request, resp) { make_log_objects(resp) }
80
+ end
81
+
82
+ def bundle_log_before(bundle, date)
83
+ request = {command: 'bundle_log_before', type: 'log', args: [bundle, date], processed_at: Time.now}
84
+ ending = @helpers.check_date_validity(date)
85
+ return invalid_response(request) if ending == false
86
+ resp = @db.bundle_log_before(bundle, ending.to_time.to_i)
87
+ return response_wrapper(request, resp) { make_log_objects(resp) }
88
+ end
89
+
90
+ def bundle_log_range(bundle, day1, day2)
91
+ request = {command: 'bundle_log_range', type: 'log', args: [bundle, day1, day2], processed_at: Time.now}
92
+ starting, ending = @helpers.check_date_validity(day1), @helpers.check_date_validity(day2)
93
+ return invalid_response(request) if starting == false || ending == false || starting > ending
94
+ resp = @db.bundle_log_range(bundle, starting.to_time.to_i, ending.to_time.to_i)
95
+ return response_wrapper(request, resp) { make_log_objects(resp) }
96
+ end
97
+ def bundle_log_day(bundle, day)
98
+ starting = @helpers.check_date_validity(day)
99
+ return invalid_response(request) if starting == false
100
+ next_day = starting.next_day.strftime('%Y-%m-%d')
101
+ bundle_log_range(bundle, day, next_day)
102
+ end
103
+
104
+ def log_since(day = nil)
105
+ request = {command: 'log_since', type: 'log', args: [day], processed_at: Time.now}
106
+ starting = if day.nil?
107
+ @helpers.check_date_validity(Time.now.to_s[0..9])
108
+ else
109
+ @helpers.check_date_validity(day)
110
+ end
111
+ resp = @db.log_since(starting.to_time.to_i)
112
+ return response_wrapper(request, resp) { make_log_objects(resp) }
113
+ end
114
+
115
+ def log_day(day)
116
+ request = {command: 'log_range', type: 'log', args: [day], processed_at: Time.now}
117
+ starting = @helpers.check_date_validity(day)
118
+ return invalid_response(request) if starting == false
119
+ ending = @helpers.check_date_validity(starting.next_day.strftime('%Y-%m-%d'))
120
+ resp = @db.log_range(starting.to_time.to_i, ending.to_time.to_i)
121
+ return response_wrapper(request, resp) { make_log_objects(resp) }
122
+ end
123
+
124
+ # ---
125
+
126
+ def delete_bundle(bundle_id)
127
+ request = {command: 'delete_bundle', type: 'action', args: [bundle_id], processed_at: Time.now}
128
+ resp = @db.delete_bundle(bundle_id)
129
+ if resp.empty? # success
130
+ resp = [{'deleted' => bundle_id}]
131
+ @response = make_basic_response(request, resp)
132
+ else
133
+ @response = bad_request(request)
134
+ end
135
+ return @response
136
+ end
137
+
138
+ # ---
139
+
140
+ def invalid_response(request)
141
+ @response = bad_request(request)
142
+ end
143
+
144
+ private
145
+
146
+ def response_wrapper(request, resp)
147
+ return invalid_response(request) if resp.empty?
148
+ list = yield
149
+ @response = make_basic_response(request, list)
150
+ end
151
+
152
+ def make_apps_list(resp)
153
+ result = make_apps_objects(resp)
154
+ result.sort_by {|obj| obj[:total][:seconds]}
155
+ end
156
+
157
+ def make_basic_response(request, list)
158
+ {
159
+ meta: {
160
+ code: 200,
161
+ request: request
162
+ },
163
+ data: list
164
+ }.to_json
165
+ end
166
+
167
+ def make_apps_objects(db_resp)
168
+ if @bundles.nil?
169
+ db_resp.map do |id, sec|
170
+ {
171
+ bundle: id,
172
+ total: {
173
+ seconds: sec,
174
+ time: @helpers.sec_to_time(sec)
175
+ }
176
+ }
177
+ end
178
+ else
179
+ db_resp.map do |id, sec|
180
+ {
181
+ bundle: id,
182
+ name: @bundles[id],
183
+ total: {
184
+ seconds: sec,
185
+ time: @helpers.sec_to_time(sec)
186
+ }
187
+ }
188
+ end
189
+ end
190
+ end
191
+
192
+ def make_log_objects(db_resp)
193
+ result = {}
194
+ sorted = db_resp.sort_by { |arr| arr[2] }
195
+ sorted.each do |arr|
196
+ name = if @bundles.nil?
197
+ arr[1]
198
+ else
199
+ @bundles[arr[1]]
200
+ end
201
+ result[arr[0]] = {
202
+ bundle: arr[1],
203
+ name: name,
204
+ start: @helpers.epoch_to_date(arr[2]),
205
+ duration: {
206
+ seconds: arr[4],
207
+ time: @helpers.sec_to_time(arr[4])
208
+ }
209
+ }
210
+ end
211
+ return result
212
+ end
213
+
214
+ def bad_request(request)
215
+ {
216
+ meta: {
217
+ code: 403,
218
+ request: request,
219
+ message: 'Bad request.'
220
+ },
221
+ data: []
222
+ }.to_json
223
+ end
224
+
225
+ end
226
+
227
+ end