fitbit_alarms_cli 0.1.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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: d57a33a593111e65cceae5cd7670984e5dc59e5b
4
+ data.tar.gz: ad04ddaeb8c523ce2c67e7c384ec4d6ac11fedf2
5
+ SHA512:
6
+ metadata.gz: cd90a5ced0d0c465a57b638381144a4b8e66dcbc6ce8c12e5db0c6ffe0f736bd18c0860871f827c7524e4c3c30f5944a8ae868d2fdc464add71a18c1f62cad0f
7
+ data.tar.gz: a1b0cca80a312f6fe5f3c2ff12f3c926788c37bc848ed3159fa74eb21eca3d0320c7396b228e8552d4764afc8dd0da5fb0e9378c39ae94178e3be18547b5b3ff
@@ -0,0 +1,22 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ *.bundle
19
+ *.so
20
+ *.o
21
+ *.a
22
+ mkmf.log
@@ -0,0 +1 @@
1
+ 2.1.2
@@ -0,0 +1,5 @@
1
+ language: ruby
2
+ cache: bundler
3
+ script: "bundle exec rake test"
4
+ rvm:
5
+ - 2.1.2
data/Gemfile ADDED
@@ -0,0 +1,18 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'bundler', '~> 1.6'
4
+ gem 'fitgem'
5
+ gem 'rake'
6
+ gem 'thor'
7
+
8
+ group :test do
9
+ #gem 'backports'
10
+ #gem 'coveralls', :require => false
11
+ #gem 'json', :platforms => [:ruby_19]
12
+ #gem 'rubocop', '>= 0.23', :platforms => [:ruby_19, :ruby_20, :ruby_21]
13
+ gem 'minitest', '~> 5.3.5'
14
+ gem 'simplecov', :require => false
15
+ #gem 'yardstick'
16
+ end
17
+
18
+ gemspec
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Ben Colon
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,31 @@
1
+ # FitbitAlarmsCli
2
+
3
+ A CLI gem to setup Fitbit alarms
4
+
5
+ ## Installation
6
+
7
+ Install the gem on your system:
8
+
9
+ $ gem install fitbit_alarms_cli
10
+
11
+ ## Usage
12
+
13
+ Enjoy `fac` executable
14
+
15
+ ```bash
16
+ Commands:
17
+ fac add # Add a new alarm
18
+ fac help [COMMAND] # Describe available commands or one specific command
19
+ fac list # List all alarms
20
+ fac remove # Remove an alarm
21
+ fac setup # Start the setup of Fitbit Alarms CLI
22
+ fac version # Fitbit Alarms CLI version
23
+ ```
24
+
25
+ ## Contributing
26
+
27
+ 1. Fork it ( https://github.com/[my-github-username]/fitbit_alarms_cli/fork )
28
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
29
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
30
+ 4. Push to the branch (`git push origin my-new-feature`)
31
+ 5. Create a new Pull Request
@@ -0,0 +1,7 @@
1
+ require "bundler/gem_tasks"
2
+ require "rake/testtask"
3
+
4
+ Rake::TestTask.new do |t|
5
+ t.libs << 'test'
6
+ t.pattern = "test/*_test.rb"
7
+ end
data/bin/fac ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/ruby
2
+ require "fitbit_alarms_cli"
3
+ FitbitAlarmsCli::Commands.start(ARGV)
@@ -0,0 +1,20 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path("../lib", __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require "fitbit_alarms_cli/version"
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "fitbit_alarms_cli"
8
+ spec.version = FitbitAlarmsCli::VERSION
9
+ spec.authors = ["Ben Colon"]
10
+ spec.email = ["ben@colon.com.fr"]
11
+ spec.summary = "A CLI gem to setup Fitbit alarms"
12
+ spec.description = "A CLI gem to setup Fitbit alarms"
13
+ spec.homepage = "https://github.com/bencolon/fitbit_alarms_cli"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = ["fac"]
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+ end
@@ -0,0 +1,74 @@
1
+ require "thor"
2
+ require "fitbit_alarms_cli/version"
3
+ require "fitbit_alarms_cli/setup"
4
+ require "fitbit_alarms_cli/client"
5
+
6
+ module FitbitAlarmsCli
7
+ class Commands < Thor
8
+ desc "version", "Fitbit Alarms CLI version"
9
+ def version
10
+ puts "Fitbit Alarms CLI - v#{VERSION}"
11
+ end
12
+
13
+ desc "setup", "Run the setup of Fitbit Alarms CLI"
14
+ long_desc <<-LONGDESC
15
+ Guide you to setup Fitbit Alarms CLI across authentication process.
16
+ LONGDESC
17
+ def setup
18
+ Setup.start
19
+ end
20
+
21
+ desc "list", "List all alarms"
22
+ long_desc <<-LONGDESC
23
+ List all Fitbit alarms. By default, list all alarms from ALL you devices.
24
+
25
+ With -D option, you can specify a device ID to get only device's alarms.
26
+ LONGDESC
27
+ option :device, :aliases => :"-D", :type => :numeric
28
+ def list
29
+ client = Client.new
30
+ client.list_alarms(options)
31
+ end
32
+
33
+ desc "add TIME", "Add a new alarm"
34
+ long_desc <<-LONGDESC
35
+ Add a new alarm with <time>. <time> should be HH:MM+TZ:00 formatted.
36
+ \x5 By default, the new alarm is assigned to the first device with these settings: today, enabled and no recurring.
37
+
38
+ With -e option, you can enabled/disabled the alarm (true or false).
39
+
40
+ With -d option, you can set the day(s) the alarm will be active for recurring alarm only.
41
+ \x5 You have to pass coma separated values (MONDAY,FRIDAY,...).
42
+
43
+ With -r option, you can set if it's a one time alarm or a recurring alarm (true or false).
44
+
45
+ With -l option, you can add a label to the alarm.
46
+ \x5 Unfortunately, this label will not be displayed on you're Fitbit :(
47
+ \x5 I really hope this feature will be added asap to the Fitbit firmware.
48
+
49
+ With -D option, you can specify a device ID to specify on which device the alarm has to be added.
50
+ LONGDESC
51
+ option :enabled, :aliases => :"-e", :type => :boolean
52
+ option :week_days, :aliases => :"-d", :type => :array
53
+ option :recurring, :aliases => :"-r", :type => :boolean
54
+ option :label, :aliases => :"-l", :type => :string
55
+ option :device_id, :aliases => :"-D", :type => :numeric
56
+ def add(time)
57
+ client = Client.new
58
+ client.add_alarm(time, options)
59
+ end
60
+
61
+ desc "remove ALARM_ID", "Remove an alarm"
62
+ long_desc <<-LONGDESC
63
+ Remove the alarm with the corresponding <alarm_id>.
64
+ \x5 By default, try to remove the alarm from the first device.
65
+
66
+ With -D option, you can specify the device ID from where the alarm has to be removed.
67
+ LONGDESC
68
+ option :device, :aliases => :"-D", :type => :numeric
69
+ def remove(alarm_id)
70
+ client = Client.new
71
+ client.remove_alarm(alarm_id, options)
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,116 @@
1
+ require 'yaml'
2
+ require 'fitgem'
3
+
4
+ module FitbitAlarmsCli
5
+ class Client
6
+ MAX_ALARMS_COUNT = 8
7
+
8
+ def initialize
9
+ unless File.exists?(Setup::AUTH_FILE_PATH)
10
+ puts "You haven't setup FitbitAlarmsCli."
11
+ puts "Please run `fac setup` before."
12
+ exit
13
+ end
14
+
15
+ auth = YAML.load_file(Setup::AUTH_FILE_PATH)
16
+ unless auth[:consumer_key] && auth[:consumer_secret] && auth[:token] && auth[:secret]
17
+ puts "FitbitAlarmsCli configuration seems corrupted."
18
+ puts "Please run `fac setup` again."
19
+ exit
20
+ end
21
+
22
+ @client = Fitgem::Client.new({ :consumer_key => auth[:consumer_key],
23
+ :consumer_secret => auth[:consumer_secret],
24
+ :token => auth[:token],
25
+ :secret => auth[:secret] })
26
+ end
27
+
28
+ def list_alarms(options)
29
+ if options[:device]
30
+ puts_device_alarms(options[:device])
31
+ else
32
+ check_response(devices = @client.devices)
33
+ devices.each do |device|
34
+ puts_device_alarms(device['id'])
35
+ end
36
+ end
37
+ end
38
+
39
+ def add_alarm(time, options)
40
+ unless /^\d{2}:\d{2}\+\d{2}:\d{2}$/.match(time)
41
+ puts_and_exit "ERROR: Invalid time. Time should be HH:MM+TZ:00 formatted (ex: 23:30+02:00)."
42
+ end
43
+
44
+ device_id = options[:device] || first_device
45
+ alarms = @client.get_alarms(device_id)
46
+ puts_and_exit "ERROR: You reached the maximum alarms count (8) on this device." if alarms["trackerAlarms"].count == MAX_ALARMS_COUNT
47
+
48
+ settings = { :device_id => device_id,
49
+ :time => time,
50
+ :enabled => true,
51
+ :recurring => false,
52
+ :weekDays => Time.now.strftime("%A").upcase
53
+ }
54
+
55
+ # symbolize_keys and update weird week_days API params
56
+ options = options.each_with_object({}) do |(k,v), h|
57
+ k = "weekDays" if k == "week_days"
58
+ h[k.to_sym] = v
59
+ end
60
+
61
+ settings.merge!(options)
62
+ check_response(@client.add_alarm(settings))
63
+
64
+ list_alarms(options)
65
+ end
66
+
67
+ def remove_alarm(alarm_id, options)
68
+ device_id = options[:device] || first_device
69
+ check_response(@client.delete_alarm(alarm_id, device_id))
70
+ list_alarms(options)
71
+ end
72
+
73
+ private
74
+
75
+ def first_device
76
+ @client.devices.first["id"]
77
+ end
78
+
79
+ def check_response(response)
80
+ puts_and_exit "ERROR: #{response["errors"]}" if response.is_a?(Hash) && response["errors"]
81
+ end
82
+
83
+ def puts_device_alarms(device_id)
84
+ puts "Device ##{device_id}\n--------------------------------"
85
+ check_response(response = @client.get_alarms(device_id))
86
+ format_alarms(response["trackerAlarms"])
87
+ end
88
+
89
+ def format_alarms(alarms)
90
+ puts_and_exit " Device not found." unless alarms
91
+ puts_and_exit " No alarms set on this device." if alarms.empty?
92
+
93
+ alarms.each do |alarm|
94
+ label = alarm['label'] ? " (#{alarm['label']})" : ""
95
+ time = alarm['time']
96
+ day = alarm['recurring'] ? "" : today_or_tomorrow(time[0..1], time[3..4], time[5..10])
97
+ recurring = alarm['recurring'] ? " every #{alarm['weekDays']}" : ""
98
+ enabled = alarm['enabled'] ? 'enabled' : 'disabled'
99
+ synced = alarm['syncedToDevice'] ? "synced" : "not synced"
100
+
101
+ puts " Alarm ##{alarm['alarmId']}#{label}, #{day}at #{alarm['time']}#{recurring} is #{enabled}/#{synced}."
102
+ end
103
+ end
104
+
105
+ def today_or_tomorrow(h, m, tz)
106
+ now = Time.now
107
+ alarm = Time.new(now.year, now.month, now.day, h, m, 0, tz)
108
+ now < alarm ? "today " : "tomorrow "
109
+ end
110
+
111
+ def puts_and_exit(message)
112
+ puts message
113
+ exit
114
+ end
115
+ end
116
+ end
@@ -0,0 +1,74 @@
1
+ module FitbitAlarmsCli
2
+ module Setup
3
+ AUTH_FILE_PATH = "#{Dir.home}/.fitbit_alarms_cli"
4
+
5
+ def self.start
6
+ if File.exists?(AUTH_FILE_PATH)
7
+ puts "You already setup FitbitAlarmsCli."
8
+ puts "Are you sure you want to setup it again? yes/no"
9
+ response = $stdin.gets
10
+ exit if response.strip != "yes"
11
+ end
12
+ run
13
+ end
14
+
15
+ private
16
+
17
+ def self.run
18
+ @auth = {}
19
+
20
+ intro
21
+ consumer_infos
22
+ tokens
23
+ congrats
24
+
25
+ rescue Exception => e
26
+ puts "An error has ocurred during authentication. Please try again."
27
+ puts e.message
28
+ #puts e.backtrace.inspect
29
+ end
30
+
31
+ def self.intro
32
+ puts "First, go register a new Fitbit application at https://dev.fitbit.com/apps/new"
33
+ puts "Fill the form and come back"
34
+ puts "Press a key to continue..."
35
+ $stdin.gets
36
+ end
37
+
38
+ def self.consumer_infos
39
+ begin
40
+ puts "Enter the consumer key you got and press enter:"
41
+ end while (key = $stdin.gets.strip).empty?
42
+ @auth[:consumer_key] = key
43
+
44
+ begin
45
+ puts "Enter the consumer secret you got and press enter:"
46
+ end while (secret = $stdin.gets.strip).empty?
47
+ @auth[:consumer_secret] = secret
48
+
49
+ @client = Fitgem::Client.new({ :consumer_key => @auth[:consumer_key],
50
+ :consumer_secret => @auth[:consumer_secret] })
51
+ end
52
+
53
+ def self.tokens
54
+ request_token = @client.authentication_request_token
55
+
56
+ puts "Your application is now set up, you now have to authorize this app access you data."
57
+ puts "Visit the following link, log in if needed, and then authorize the app."
58
+ puts request_token.authorize_url
59
+
60
+ puts "When you've authorized that app, enter the verifier code you got and press enter:"
61
+ verifier = $stdin.gets.strip
62
+ access_token = @client.authorize(request_token.token, request_token.secret, :oauth_verifier => verifier)
63
+ @auth[:token] = access_token.token
64
+ @auth[:secret] = access_token.secret
65
+
66
+ File.open(AUTH_FILE_PATH, "w") {|f| YAML.dump(@auth, f) }
67
+ end
68
+
69
+ def self.congrats
70
+ puts "Congrats, FitbitAlarmsCli is setup!"
71
+ puts "Have a look to the help to enjoy it: `fac help`"
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,3 @@
1
+ module FitbitAlarmsCli
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,7 @@
1
+ require 'test_helper'
2
+
3
+ class FitbitAlarmsCliTest < MiniTest::Unit::TestCase
4
+ def test_check
5
+ assert true
6
+ end
7
+ end
@@ -0,0 +1,17 @@
1
+ require 'simplecov'
2
+ #require 'coveralls'
3
+
4
+ SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
5
+ SimpleCov::Formatter::HTMLFormatter,
6
+ #Coveralls::SimpleCov::Formatter,
7
+ ]
8
+
9
+ SimpleCov.start do
10
+ minimum_coverage 100
11
+ end
12
+
13
+ require 'fitbit_alarms_cli'
14
+ require 'minitest'
15
+ require 'minitest/autorun'
16
+ require 'minitest/pride'
17
+
metadata ADDED
@@ -0,0 +1,62 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fitbit_alarms_cli
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Ben Colon
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-06-25 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: A CLI gem to setup Fitbit alarms
14
+ email:
15
+ - ben@colon.com.fr
16
+ executables:
17
+ - fac
18
+ extensions: []
19
+ extra_rdoc_files: []
20
+ files:
21
+ - ".gitignore"
22
+ - ".ruby-version"
23
+ - ".travis.yml"
24
+ - Gemfile
25
+ - LICENSE.txt
26
+ - README.md
27
+ - Rakefile
28
+ - bin/fac
29
+ - fitbit_alarms_cli.gemspec
30
+ - lib/fitbit_alarms_cli.rb
31
+ - lib/fitbit_alarms_cli/client.rb
32
+ - lib/fitbit_alarms_cli/setup.rb
33
+ - lib/fitbit_alarms_cli/version.rb
34
+ - test/fitbit_alarms_cli_test.rb
35
+ - test/test_helper.rb
36
+ homepage: https://github.com/bencolon/fitbit_alarms_cli
37
+ licenses:
38
+ - MIT
39
+ metadata: {}
40
+ post_install_message:
41
+ rdoc_options: []
42
+ require_paths:
43
+ - lib
44
+ required_ruby_version: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ version: '0'
49
+ required_rubygems_version: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ requirements: []
55
+ rubyforge_project:
56
+ rubygems_version: 2.2.2
57
+ signing_key:
58
+ specification_version: 4
59
+ summary: A CLI gem to setup Fitbit alarms
60
+ test_files:
61
+ - test/fitbit_alarms_cli_test.rb
62
+ - test/test_helper.rb