TokiCLI 0.2.1 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
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