# encoding: utf-8 module TokiCLI class App < Thor package_name "TokiCLI" %w{get_messages search_messages get_channels status view authorize export import scan ../API/dbapi}.each {|r| require_relative "#{r}"} desc "version", "Toki version" map "-v" => :version def version puts "\n-- TokiCLI --\n\nVersion:\t#{VERSION}\nUrl:\t\thttp://github.com/ericdke/TokiCLI\n\n" end desc "serve", "Start a local Toki API server" map "server" => :serve def serve require_relative '../TokiServer/tokiserver' #View.new.clear puts "\nStarting the Toki API server...\n\nPress [CTRL-C] to stop.\n\nThe index page URL is: http://localhost:4567\n\n" TokiServer.run! puts "\nToki API server has been shut down.\n\n" end desc "auth", "App.net login" def auth begin toki = DBAPI.new adn = Authorize.new(toki.helpers.toki_path) adn.authorize rescue Interrupt puts Status.canceled exit end end desc "scan", "Scan /Applications to resolve app names" def scan scanner = Scan.new DBAPI.new scanner.scan({verbose: true}) end desc "total", "Total usage of all apps" option :json, aliases: '-j', type: :boolean, desc: 'Export the results as a JSON file' option :csv, aliases: '-c', type: :boolean, desc: 'Export the results as a CSV file' def total toki, view = DBAPI.new, View.new apps = JSON.parse toki.apps_total if apps['meta']['code'] == 200 view.total_table apps else puts "\nError:\n\n#{apps}\n\n" exit end if (options[:json] || options[:csv]) export = Export.new toki, view export.apps_total options, apps, 'total' end end desc "top", "Most used apps" option :number, aliases: '-n', type: :numeric, desc: 'Specify the number of apps' option :json, aliases: '-j', type: :boolean, desc: 'Export the results as a JSON file' option :csv, aliases: '-c', type: :boolean, desc: 'Export the results as a CSV file' def top toki, view = DBAPI.new, View.new apps = JSON.parse toki.apps_top(options[:number] || 5) if apps['meta']['code'] == 200 view.total_table apps else puts "\nError:\n\n#{apps}\n\n" exit end if (options[:json] || options[:csv]) export = Export.new toki, view export.apps_total options, apps, 'top' end end desc "day DATE", "All apps used on a specific day" option :json, aliases: '-j', type: :boolean, desc: 'Export the results as a JSON file' option :csv, aliases: '-c', type: :boolean, desc: 'Export the results as a CSV file' def day(*args) abort(Status.specify_day) if args.empty? begin DateTime.strptime(args[0], '%Y-%m-%d') rescue ArgumentError abort(Status.specify_day) end toki, view = DBAPI.new, View.new apps = JSON.parse toki.apps_day args[0] if apps['meta']['code'] == 200 view.total_table apps else puts "\nError:\n\n#{apps}\n\n" exit end if (options[:json] || options[:csv]) export = Export.new toki, view export.apps_total options, apps, "day-#{args[0]}" end end desc "since DATE", "All apps used since a specific day" option :json, aliases: '-j', type: :boolean, desc: 'Export the results as a JSON file' option :csv, aliases: '-c', type: :boolean, desc: 'Export the results as a CSV file' def since *args abort(Status.specify_day) if args.empty? begin DateTime.strptime args[0], '%Y-%m-%d' rescue ArgumentError abort Status.specify_day end toki, view = DBAPI.new, View.new apps = JSON.parse toki.apps_since args[0] if apps['meta']['code'] == 200 view.total_table apps else puts "\nError:\n\n#{apps}\n\n" exit end if (options[:json] || options[:csv]) export = Export.new toki, view export.apps_total options, apps, "since-#{args[0]}" end end desc "before DATE", "All apps used before a specific day" option :json, aliases: '-j', type: :boolean, desc: 'Export the results as a JSON file' option :csv, aliases: '-c', type: :boolean, desc: 'Export the results as a CSV file' def before *args abort(Status.specify_day) if args.empty? begin DateTime.strptime args[0], '%Y-%m-%d' rescue ArgumentError abort Status.specify_day end toki, view = DBAPI.new, View.new apps = JSON.parse toki.apps_before args[0] if apps['meta']['code'] == 200 view.total_table apps else puts "\nError:\n\n#{apps}\n\n" exit end if (options[:json] || options[:csv]) export = Export.new toki, view export.apps_total options, apps, "before-#{args[0]}" end end desc "range DATE1 DATE2", "All apps used between two specific days" option :json, aliases: '-j', type: :boolean, desc: 'Export the results as a JSON file' option :csv, aliases: '-c', type: :boolean, desc: 'Export the results as a CSV file' def range(*args) abort(Status.specify_range) if args.empty? || args.length != 2 begin DateTime.strptime(args[0], '%Y-%m-%d') DateTime.strptime(args[1], '%Y-%m-%d') rescue ArgumentError abort(Status.specify_range) end toki, view = DBAPI.new, View.new apps = JSON.parse toki.apps_range args[0], args[1] if apps['meta']['code'] == 200 view.total_table apps else puts "\nError:\n\n#{apps}\n\n" exit end if (options[:json] || options[:csv]) export = Export.new toki, view export.apps_total options, apps, "range-#{args[0]}_#{args[1]}" end end desc "log APP", "Complete log for an app" option :json, aliases: '-j', type: :boolean, desc: 'Export the results as a JSON file' option :csv, aliases: '-c', type: :boolean, desc: 'Export the results as a CSV file' option :bundle, aliases: '-b', type: :boolean, desc: "Specify the complete bundle identifier (in case the app name resolve doesn't work)" def log(*args) abort(Status.specify_name) if args.empty? asked = args[0] toki = DBAPI.new view = View.new log = if options[:bundle] JSON.parse toki.bundle_log asked else JSON.parse toki.name_log asked end if log['meta']['code'] == 200 view.app_table asked, log else puts "\nError:\n\n#{log}\n\n" exit end if (options[:json] || options[:csv]) export = Export.new toki, view export.log options, log, "log-#{log['data']['bundle'].gsub('.', '_')}" end end desc "app APP", "Total tracked time for an app" option :json, aliases: '-j', type: :boolean, desc: 'Export the results as a JSON file' option :csv, aliases: '-c', type: :boolean, desc: 'Export the results as a CSV file' option :bundle, aliases: '-b', type: :boolean, desc: "Specify the complete bundle identifier (in case the app name resolve doesn't work)" def app *args abort(Status.specify_name) if args.empty? asked = args[0] toki = DBAPI.new view = View.new app = if options[:bundle] JSON.parse toki.bundle_total asked else JSON.parse toki.name_total asked end if app['meta']['code'] == 200 view.total_table app else puts "\nError:\n\n#{app}\n\n" exit end if (options[:json] || options[:csv]) export = Export.new toki, view export.app_total options, app, "app-#{app['data']['bundle'].gsub('.', '_')}" end end desc "app_before APP DATE", "Total tracked time for an app before a specific day" option :json, aliases: '-j', type: :boolean, desc: 'Export the results as a JSON file' option :csv, aliases: '-c', type: :boolean, desc: 'Export the results as a CSV file' option :bundle, aliases: '-b', type: :boolean, desc: "Specify the complete bundle identifier (in case the app name resolve doesn't work)" def app_before *args abort('Error') if args.empty? #TODO: better and more complete asked = args[0] date = args[1] begin DateTime.strptime args[1], '%Y-%m-%d' rescue ArgumentError abort Status.specify_day end toki = DBAPI.new view = View.new app = if options[:bundle] JSON.parse toki.bundle_total_before asked, date else JSON.parse toki.name_total_before asked, date end if app['meta']['code'] == 200 view.total_table app else puts "\nError:\n\n#{app}\n\n" exit end if (options[:json] || options[:csv]) export = Export.new toki, view export.app_total options, app, "app_before-#{app['data']['bundle'].gsub('.', '_')}_#{args[1]}" end end desc "app_since APP DATE", "Total tracked time for an app since a specific day" option :json, aliases: '-j', type: :boolean, desc: 'Export the results as a JSON file' option :csv, aliases: '-c', type: :boolean, desc: 'Export the results as a CSV file' option :bundle, aliases: '-b', type: :boolean, desc: "Specify the complete bundle identifier (in case the app name resolve doesn't work)" def app_since *args abort('Error') if args.empty? #TODO: better and more complete asked = args[0] date = args[1] begin DateTime.strptime args[1], '%Y-%m-%d' rescue ArgumentError abort Status.specify_day end toki = DBAPI.new view = View.new app = if options[:bundle] JSON.parse toki.bundle_total_since asked, date else JSON.parse toki.name_total_since asked, date end if app['meta']['code'] == 200 view.total_table app else puts "\nError:\n\n#{app}\n\n" exit end if (options[:json] || options[:csv]) export = Export.new toki, view export.app_total options, app, "app_since-#{app['data']['bundle'].gsub('.', '_')}_#{date}" end end desc "app_day APP DATE", "Total tracked time for an app on a specific day" option :json, aliases: '-j', type: :boolean, desc: 'Export the results as a JSON file' option :csv, aliases: '-c', type: :boolean, desc: 'Export the results as a CSV file' option :bundle, aliases: '-b', type: :boolean, desc: "Specify the complete bundle identifier (in case the app name resolve doesn't work)" def app_day *args abort('Error') if args.empty? #TODO: better and more complete asked = args[0] date = args[1] begin DateTime.strptime args[1], '%Y-%m-%d' rescue ArgumentError abort Status.specify_day end toki = DBAPI.new view = View.new app = if options[:bundle] JSON.parse toki.bundle_total_day asked, date else JSON.parse toki.name_total_day asked, date end if app['meta']['code'] == 200 view.total_table app else puts "\nError:\n\n#{app}\n\n" exit end if (options[:json] || options[:csv]) export = Export.new toki, view export.app_total options, app, "app_day-#{app['data']['bundle'].gsub('.', '_')}_#{date}" end end desc "app_range APP DATE1 DATE2", "total tracked time for an app between two specific days" option :json, aliases: '-j', type: :boolean, desc: 'Export the results as a JSON file' option :csv, aliases: '-c', type: :boolean, desc: 'Export the results as a CSV file' option :bundle, aliases: '-b', type: :boolean, desc: "Specify the complete bundle identifier (in case the app name resolve doesn't work)" def app_range *args abort('Error') if args.empty? || args.length != 3 begin DateTime.strptime(args[1], '%Y-%m-%d') DateTime.strptime(args[2], '%Y-%m-%d') rescue ArgumentError abort(Status.specify_range) end toki = DBAPI.new view = View.new app = if options[:bundle] JSON.parse toki.bundle_total_range args[0], args[1], args[2] else JSON.parse toki.name_total_range args[0], args[1], args[2] end if app['meta']['code'] == 200 view.total_table app else puts "\nError:\n\n#{app}\n\n" exit end if (options[:json] || options[:csv]) export = Export.new toki, view export.app_total options, app, "app_range-#{app['data']['bundle'].gsub('.', '_')}_#{args[1]}_#{args[2]}" end end desc "restore", "Restore data from App.net and rebuild the Toki.app database" def restore toki_api = DBAPI.new view = View.new import = Import.new toki_api, view import.restore get_token, get_channel_id end private def get_token filepath = Dir.home + '/.TokiCLI/config.json' if File.exist?(filepath) content = JSON.parse(File.read(filepath)) content['token'] else clear abort Status.run_auth end end def get_channel_id #TODO return ch['counts']['messages'] too channels = ADNChannels::GetChannels.new(get_token).get_channels channel_id = '' channels.each do |ch| if ch['type'] == 'us.kkob.toki.sync-b' channel_id = ch['id'] break end end return channel_id.to_i unless channel_id == '' abort Status.no_channel end end end