ifocustt 0.0.4 → 0.0.5

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0dfe2365976e3a78b145968a9fab127547b5ac71
4
- data.tar.gz: baa95c3b6ef52e3ce59fdb2b1dc8c3d3c44a61a3
3
+ metadata.gz: 22f03cae719f85527a009f572e56a83656de450d
4
+ data.tar.gz: 908196a2a331ea2bd9fbfa925ad71cadab6a08d8
5
5
  SHA512:
6
- metadata.gz: c40175f09eb1a141a0e9ed408b65749f619431070a422e5ee1a9bd5be45c1e42867dad4390cbbcdfd8d72992dfd5833e652df197494651a111b0304bdeffc69d
7
- data.tar.gz: 616585264fe4dda64aa48cd16f07a795f17e69dbcaf9ac6137fa517a90c9d195660df4159ff8cb832d3b80d8493f482cca1aa6f03c76a655724bd9e6c4fb3546
6
+ metadata.gz: 38199fdef0d916b4008d57ca34be834f9ece7fe7b5feb720a88c42a28d4a89af4896262a8939fc464abd9f3dca9f853f40d986be7b9c2a8510146c2fcf704d7b
7
+ data.tar.gz: a7619afde1039e458d07b4a2852f1ec61b713471d7bef3cd73316e1b94aac812d418ee4c9cca3a9d6828a4aee2bca016fc2bbd04799450e578582caab9845ef7
data/lib/focus/action.rb CHANGED
@@ -4,9 +4,39 @@ require "interactor"
4
4
  module Focus
5
5
  class FailedActionError < StandardError; end
6
6
 
7
+ # A small wrapper to an Action's context.
8
+ # If an attribute is defined in the context, it will be returned.
9
+ # Otherwise, a lookup within Focus::Config will take place.
10
+ class ContextualConfiguration
11
+ attr_reader :context
12
+
13
+ def initialize(context)
14
+ @context = context
15
+ end
16
+
17
+ def method_missing(m, *args, &block) # rubocop:disable MethodMissing
18
+ context.send(m) || Config.send(m, *args, &block)
19
+ end
20
+ end
21
+
7
22
  class Action
8
23
  include Interactor
9
24
 
25
+ def perform; end
26
+
27
+ def error_message
28
+ "#{self.class.to_s.split('::').last} failed"
29
+ end
30
+
31
+ # This method is used internally and should not be used within actions.
32
+ def call
33
+ perform
34
+ end
35
+
36
+ def config
37
+ ContextualConfiguration.new(context)
38
+ end
39
+
10
40
  private
11
41
 
12
42
  def focus_target
@@ -29,26 +59,27 @@ module Focus
29
59
  focus_seconds * 0.2
30
60
  end
31
61
 
32
- def evaluate_step(klass, args)
62
+ def fail_action!(opts = {})
63
+ raise ArgumentError, "An `:error` key must be provided to fail an action" unless (opts.keys & [:error, "error"]).any?
64
+ context.fail!(opts.merge(action: self.class.to_s.split("::").last))
65
+ end
66
+
67
+ def _evaluate_step(klass, args)
33
68
  action = klass.to_s.gsub(/^.*::/, "")
34
69
  step = "Running #{action}..."
35
70
 
36
71
  Focus::STDOUT.step(step, quiet: context.quiet) do
37
72
  result = klass.call(args)
38
- raise FailedActionError, error_message(result) unless result.success?
73
+ raise FailedActionError, _failed_action_error(result) unless result.success?
39
74
  end
40
75
  end
41
76
 
42
- def error_message(obj)
77
+ def _failed_action_error(obj)
43
78
  "#{obj.action}: #{obj.error}"
44
79
  end
45
80
 
46
81
  def debug_output(*args)
47
82
  Focus::STDOUT.debug_output args
48
83
  end
49
-
50
- def fail_action!(opts = {})
51
- context.fail!(opts.merge(action: self.class.to_s.split("::").last))
52
- end
53
84
  end
54
85
  end
@@ -1,15 +1,9 @@
1
1
  module Focus
2
2
  class ChangeBlinkColor < Action
3
- def call
4
- context.fail! unless perform
5
- end
6
-
7
- private
8
-
9
3
  def perform
10
- url = "#{Config.blink_server}/fadeToRGB?rgb=%#{context.color}"
11
- res = HTTParty.get(url)
12
- res.code == 200
4
+ url = "#{config.blink_server}/fadeToRGB?rgb=%#{context.color}"
5
+ res = Utils::WebClient.get(url)
6
+ fail_action!(error: "Could not change blink(1) color.") unless res.success?
13
7
  end
14
8
  end
15
9
  end
@@ -1,15 +1,12 @@
1
1
  module Focus
2
2
  class ChangeSlackDoNotDisturb < Action
3
- def call
4
- context.fail! unless perform
3
+ def perform
4
+ res = Utils::WebClient.post(url)
5
+ fail_action!(error: res) unless res.success?
5
6
  end
6
7
 
7
8
  private
8
9
 
9
- def perform
10
- Config.slack_token ? HTTParty.post(url) : true
11
- end
12
-
13
10
  def url
14
11
  if context.enabled
15
12
  "#{base_url}&num_minutes=#{focus_minutes}"
@@ -19,7 +16,7 @@ module Focus
19
16
  end
20
17
 
21
18
  def base_url
22
- "#{Config.slack_api_url}/#{action}?token=#{Config.slack_token}"
19
+ "#{config.slack_api_url}/#{action}?token=#{config.slack_token}"
23
20
  end
24
21
 
25
22
  def action
@@ -1,20 +1,18 @@
1
1
  module Focus
2
2
  class ChangeSlackPresence < Action
3
- def call
4
- context.fail! unless perform
3
+ def perform
4
+ res = Utils::WebClient.post url
5
+ fail_action!(error: res) unless res.success?
5
6
  end
6
7
 
7
8
  private
8
9
 
9
- def perform
10
- token = Config.slack_token
11
- if token
12
- url = "#{Config.slack_api_url}/users.setPresence?token=#{token}&presence=#{presence}"
13
- res = HTTParty.post url
14
- res.code == 200
15
- else
16
- true
17
- end
10
+ def token
11
+ config.slack_token
12
+ end
13
+
14
+ def url
15
+ "#{config.slack_api_url}/users.setPresence?token=#{token}&presence=#{presence}"
18
16
  end
19
17
 
20
18
  def presence
@@ -1,14 +1,14 @@
1
1
  require "fileutils"
2
2
  module Focus
3
3
  class LogFocusTime < Action
4
- def call
4
+ def perform
5
5
  update_log
6
6
  end
7
7
 
8
8
  private
9
9
 
10
10
  def update_log
11
- file = File.expand_path Config.focus_history_file
11
+ file = File.expand_path config.focus_history_file
12
12
  new_file = File.exist?(file)
13
13
 
14
14
  File.open(file, "a") do |fo|
@@ -1,14 +1,14 @@
1
1
  module Focus
2
2
  class PostWorkLogToJira < Action
3
- def call
3
+ def perform
4
4
  return unless jira_ticket && seconds_focused >= 60
5
- HTTParty.post(issue_url, options)
5
+ Utils::WebClient.post(issue_url, options)
6
6
  end
7
7
 
8
8
  private
9
9
 
10
10
  def issue_url
11
- "#{Config.jira_url}/issue/#{jira_ticket}/worklog"
11
+ "#{config.jira_url}/issue/#{jira_ticket}/worklog"
12
12
  end
13
13
 
14
14
  def options
@@ -24,7 +24,7 @@ module Focus
24
24
  end
25
25
 
26
26
  def auth
27
- { username: Config.jira_username, password: Config.jira_password }
27
+ { username: config.jira_username, password: config.jira_password }
28
28
  end
29
29
 
30
30
  def headers
@@ -1,6 +1,6 @@
1
1
  module Focus
2
2
  class RunShellCommand < Action
3
- def call
3
+ def perform
4
4
  system(context.command.to_s)
5
5
  end
6
6
  end
@@ -1,8 +1,8 @@
1
1
  module Focus
2
2
  class StartBlinkServer < Action
3
- def call
3
+ def perform
4
4
  verify_blink_server_installed
5
- HTTParty.get(Config.blink_server)
5
+ Utils::WebClient.get(config.blink_server)
6
6
  rescue Errno::ECONNREFUSED
7
7
  start_blink_server
8
8
  end
@@ -13,7 +13,7 @@ module Focus
13
13
  error_msg = \
14
14
  "Blink server not installed. Run `npm install -g node-blink1-server`."
15
15
 
16
- raise ArgumentError, error_msg unless blink_server_installed?
16
+ fail_action!(error: error_msg) unless blink_server_installed?
17
17
  end
18
18
 
19
19
  def blink_server_installed?
@@ -22,7 +22,7 @@ module Focus
22
22
 
23
23
  def start_blink_server
24
24
  fork do
25
- system("blink1-server #{Config.blink_port} &>/dev/null")
25
+ system("blink1-server #{config.blink_port} &>/dev/null")
26
26
  end
27
27
  end
28
28
  end
@@ -7,8 +7,10 @@ module Focus
7
7
 
8
8
  attr_reader :action
9
9
 
10
- def call
10
+ def perform
11
11
  context.actions = ConfigLoader.load("actions")
12
+ parse_jira_ticket
13
+ Focus::STDOUT.puts_line "Starting focus..."
12
14
  context.daemonize ? fork { _actions } : _actions
13
15
  end
14
16
 
@@ -25,6 +27,11 @@ module Focus
25
27
  happy_message
26
28
  end
27
29
 
30
+ def parse_jira_ticket
31
+ context.jira_ticket = Utils::ParseJiraTicketFromGitBranch.call.jira_ticket
32
+ Focus::STDOUT.puts_line "Working on JIRA ticket: '#{context.jira_ticket}'" if context.jira_ticket
33
+ end
34
+
28
35
  def focus
29
36
  @action = :focus
30
37
  perform_actions "OnFocus"
@@ -95,7 +102,7 @@ module Focus
95
102
  klass = constantize(action)
96
103
  args = downcase(keyword_arguments)
97
104
 
98
- evaluate_step klass, with_default_context(args)
105
+ _evaluate_step klass, with_default_context(args)
99
106
  end
100
107
  end
101
108
  end
@@ -1,19 +1,18 @@
1
1
  module Focus
2
2
  class StartRescueTime < Action
3
- def call
4
- context.fail! unless perform
3
+ def perform
4
+ res = Utils::WebClient.post url
5
+ fail_action!(error: res) unless res.success?
5
6
  end
6
7
 
7
8
  private
8
9
 
9
- def perform
10
- token = Config.ifttt_maker_key
11
- if token
12
- url = "https://maker.ifttt.com/trigger/#{event}/with/key/#{token}"
13
- HTTParty.post url
14
- else
15
- true
16
- end
10
+ def token
11
+ config.ifttt_maker_key
12
+ end
13
+
14
+ def url
15
+ "https://maker.ifttt.com/trigger/#{event}/with/key/#{token}"
17
16
  end
18
17
 
19
18
  def event
@@ -1,15 +1,14 @@
1
1
  module Focus
2
2
  class StrobeBlinkColor < Action
3
- def call
4
- context.fail! unless perform
3
+ def perform
4
+ res = Utils::WebClient.get(url)
5
+ fail_action!(error: res) unless res.success?
5
6
  end
6
7
 
7
8
  private
8
9
 
9
- def perform
10
- url = "#{Config.blink_server}/pattern?rgb=%#{context.color}&time=1.5&repeats=0"
11
- res = HTTParty.get(url)
12
- res.code == 200
10
+ def url
11
+ "#{config.blink_server}/pattern?rgb=%#{context.color}&time=1.5&repeats=0"
13
12
  end
14
13
  end
15
14
  end
@@ -1,11 +1,16 @@
1
1
  module Focus
2
2
  class ToggleMacNotificationCenter < Action
3
- def call
4
- toggle if uname == "Darwin"
3
+ def perform
4
+ fail_action!(error: "This action only works on MacOSX") unless mac?
5
+ toggle
5
6
  end
6
7
 
7
8
  private
8
9
 
10
+ def mac?
11
+ uname == "Darwin"
12
+ end
13
+
9
14
  def uname
10
15
  `uname`.chomp
11
16
  end
data/lib/focus/cli.rb CHANGED
@@ -32,6 +32,7 @@ module Focus
32
32
  end
33
33
 
34
34
  opts.on("-t", "--target=TARGET", "Specify what you are focusing on") do |t|
35
+ raise ArgumentError, "#{t} is not a valid target name" if t =~ /^\d+(\.\d)?$/
35
36
  args.target = t
36
37
  end
37
38
 
data/lib/focus/config.rb CHANGED
@@ -6,15 +6,18 @@ module Focus
6
6
  class Config < OpenStruct
7
7
  class << self
8
8
  def method_missing(m, *args, &block) # rubocop:disable MethodMissing
9
- config.env(m) || config.send(m, *args, &block) || raise_undefined_config(m)
9
+ config = new
10
+ config.send(m, *args, &block) || env(m) || raise_undefined_config(m)
10
11
  end
11
12
 
12
- def config
13
- @config ||= new
13
+ private
14
+
15
+ def env(m)
16
+ ENV[m.to_s.upcase]
14
17
  end
15
18
 
16
19
  def raise_undefined_config(m)
17
- error = "(#{m}) neither `ENV['#{m.to_s.upcase}']` or `.focus.yml#config.#{m}` are defined"
20
+ error = "(#{m}) neither `.focus.yml#config.#{m}` or `ENV['#{m.to_s.upcase}']` are defined"
18
21
  raise MissingConfiguration, error
19
22
  end
20
23
  end
@@ -25,10 +28,6 @@ module Focus
25
28
  ingest _hardcoded
26
29
  end
27
30
 
28
- def env(m)
29
- ENV[m.to_s.upcase]
30
- end
31
-
32
31
  private
33
32
 
34
33
  def configurations
@@ -0,0 +1,13 @@
1
+ module Focus
2
+ module Utils
3
+ class WebClient < Util
4
+ class << self
5
+ %i(get post).each do |action|
6
+ define_method(action) do |url, opts = {}|
7
+ HTTParty.send(action, url, opts)
8
+ end
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
data/lib/focus/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Focus
2
- VERSION = "0.0.4".freeze
2
+ VERSION = "0.0.5".freeze
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ifocustt
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
4
+ version: 0.0.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - John Mason
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-03-15 00:00:00.000000000 Z
11
+ date: 2017-03-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: httparty
@@ -92,7 +92,6 @@ files:
92
92
  - LICENSE.txt
93
93
  - assets/focus.jpg
94
94
  - bin/focus
95
- - bin/focus.sh
96
95
  - config/default.yml
97
96
  - lib/focus.rb
98
97
  - lib/focus/action.rb
@@ -117,6 +116,7 @@ files:
117
116
  - lib/focus/util.rb
118
117
  - lib/focus/utils.rb
119
118
  - lib/focus/utils/parse_jira_ticket_from_git_branch.rb
119
+ - lib/focus/utils/web_client.rb
120
120
  - lib/focus/version.rb
121
121
  homepage: http://github.com/binarymason/ifocustt
122
122
  licenses:
data/bin/focus.sh DELETED
@@ -1,136 +0,0 @@
1
- #!/bin/sh
2
- #
3
- # USAGE:
4
- #
5
- # focus [minutes=25] [target=?|JIRA ticket in git branch]
6
-
7
- git_branch_name() { git rev-parse --abbrev-ref HEAD 2>/dev/null; }
8
- jira_ticket() {
9
- local branch=$(git_branch_name)
10
- local ticket=$(echo $branch | sed 's/.*\([a-zA-Z]\{2\}-[0-9]\{2\}\)/\1/') # TODO
11
- if [ "$ticket" == "$branch" ]
12
- then
13
- echo "?"
14
- else
15
- echo "$ticket"
16
- fi
17
- }
18
-
19
- FOCUS_MINUTES="${1-25}"
20
- FOCUS_TARGET="${2-$(jira_ticket)}"
21
- FOCUS_HISTORY_FILE="$HOME/.focus_history"
22
-
23
- info() { printf -- "\033[00;34m..\033[0m %s " "$*"; }
24
- ok() { echo "\033[00;32m✓\033[0m"; }
25
- abort() { echo "!!! $*" >&2; exit 1; }
26
- epoch() { date +%s; }
27
- print_line() { printf "%-15s %-15s %-15s\n" "$1" "$2" "$3"; }
28
- title() { print_line "EPOCH" "FOCUS_TIME" "TARGET"; }
29
- event() { print_line "$(epoch)" "$FOCUS_MINUTES" "$@"; }
30
- add_to_history() { "$@" >> "$FOCUS_HISTORY_FILE"; }
31
-
32
- log_focus() {
33
- info "Updating ~/.focus_history"
34
- if [ ! -f "$FOCUS_HISTORY_FILE" ]; then add_to_history title; fi
35
- add_to_history event "$FOCUS_TARGET"
36
- ok
37
- }
38
-
39
- quietly() {
40
- "$@" &>/dev/null
41
- }
42
-
43
- SLACK_TOKEN=$(cat ~/.secrets/slack-token 2>/dev/null)
44
- SLACK_AWAY="away"
45
- SLACK_AVAILABLE="auto"
46
-
47
- change_slack_presence() {
48
- if [ -n "$SLACK_TOKEN" ]
49
- then
50
- local presence="$1"
51
- info "Changing slack presence to $presence"
52
- local setpresenceurl="https://slack.com/api/users.setPresence?token=$SLACK_TOKEN&presence=$presence&pretty=1"
53
- curl -X POST "$setpresenceurl" &>/dev/null && ok
54
- fi
55
- }
56
-
57
- BLINK_PORT="8754"
58
- BLINK_SERVER="http://localhost:$BLINK_PORT/blink1"
59
- BLINK_RED="23EA5B5B"
60
- BLINK_GREEN="233AF23A"
61
- BLINK_ORANGE="23FFBF00"
62
- start_blink_server() {
63
- if ! command -v blink1-server &> /dev/null
64
- then
65
- abort 'Blink server not installed. Run `npm install -g node-blink1-server`.'
66
- else
67
- quietly curl "$BLINK_SERVER" || blink1-server "$BLINK_PORT" &
68
- fi
69
- }
70
-
71
- change_blink_color() {
72
- local color="$1"
73
- info "Changing blink to $color"
74
- curl "$BLINK_SERVER/fadeToRGB?rgb=%$color" &>/dev/null && ok
75
- }
76
-
77
- strobe_blink_color() {
78
- local color="$1"
79
- local seconds="$2"
80
- local blink_rate="0.5" # both on and off together finishes in one second
81
- curl "$BLINK_SERVER/blink?rgb=%$color&time=$blink_rate&repeats=$seconds" &>/dev/null && ok
82
- }
83
-
84
- IFTTT_MAKER_KEY=$(cat ~/.secrets/ifttt-maker 2>/dev/null)
85
- start_rescue_time() {
86
- if [ -n "$IFTTT_MAKER_KEY" ]
87
- then
88
- local event="rescue_time_focus_start"
89
- info "Firing $event blink(1) event to IFTT"
90
- curl -X POST https://maker.ifttt.com/trigger/${event}/with/key/${IFTTT_MAKER_KEY} &>/dev/null && ok
91
- fi
92
- }
93
-
94
- start_slack_do_not_disturb() {
95
- if [ -n "$SLACK_TOKEN" ]
96
- then
97
- local url="https://slack.com/api/dnd.setSnooze?token=$SLACK_TOKEN&num_minutes=$FOCUS_MINUTES&pretty=1"
98
- info "Changing slack to do not disturb for $FOCUS_MINUTES minutes"
99
- curl -X POST "$url" &>/dev/null && ok
100
- fi
101
- }
102
-
103
- disable_mac_notification_center() {
104
- if [ "$(uname)" == "Darwin" ]
105
- then
106
- info "Disabling Mac OSX notification center"
107
- quietly launchctl unload -w /System/Library/LaunchAgents/com.apple.notificationcenterui.plist
108
- ok
109
- fi
110
- }
111
-
112
- enable_mac_notification_center() {
113
- if [ "$(uname)" == "Darwin" ]
114
- then
115
- launchctl load -w /System/Library/LaunchAgents/com.apple.notificationcenterui.plist
116
- fi
117
- }
118
-
119
- cleanup(){
120
- local focus_seconds=$(echo "$FOCUS_MINUTES * 60" | bc)
121
- local break_seconds=$(echo "$focus_seconds * .2" | bc)
122
- sleep "$focus_seconds" && quietly strobe_blink_color "$BLINK_ORANGE" "$break_seconds"
123
- sleep "$break_seconds" && \
124
- quietly change_slack_presence "$SLACK_AVAILABLE"
125
- quietly enable_mac_notification_center
126
- quietly change_blink_color "$BLINK_GREEN"
127
- }
128
-
129
- disable_mac_notification_center
130
- start_rescue_time
131
- start_blink_server
132
- change_slack_presence "$SLACK_AWAY"
133
- start_slack_do_not_disturb
134
- log_focus
135
- change_blink_color "$BLINK_RED"
136
- cleanup &