sifttter-redux 0.3.1 → 0.3.2

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,105 @@
1
+ require 'sifttter_redux/cli_message.rb'
2
+ require 'sifttter_redux/configuration.rb'
3
+ require 'sifttter_redux/date_range_maker.rb'
4
+ require 'sifttter_redux/extensions.rb'
5
+ require 'sifttter_redux/dbu.rb'
6
+ require 'sifttter_redux/os.rb'
7
+ require 'sifttter_redux/sifttter.rb'
8
+
9
+ # ======================================================
10
+ # SifttterRedux Module
11
+ #
12
+ # Wrapper module for all other modules in this project
13
+ # ======================================================
14
+
15
+ module SifttterRedux
16
+ using CliMessage
17
+ using Configuration
18
+
19
+ # ----------------------------------------------------
20
+ # Constants
21
+ # ----------------------------------------------------
22
+ DBU_LOCAL_FILEPATH = '/usr/local/opt'
23
+ DO_REMOTE_FILEPATH = "/Apps/Day\\ One/Journal.dayone/entries"
24
+ DO_LOCAL_FILEPATH = '/tmp/dayone'
25
+ SRD_CONFIG_FILEPATH = File.join(ENV['HOME'], '.sifttter_redux')
26
+ SFT_LOCAL_FILEPATH = '/tmp/sifttter'
27
+ SFT_REMOTE_FILEPATH = '/Apps/ifttt/sifttter'
28
+
29
+ @verbose_output = true
30
+
31
+ # ----------------------------------------------------
32
+ # initialize_procedures method
33
+ #
34
+ # Initializes Sifttter Redux by downloading and
35
+ # collecting all necessary items and info.
36
+ # @return Void
37
+ # ----------------------------------------------------
38
+ def self.init
39
+ # Re-initialize the configuration data.
40
+ Configuration.reset
41
+ Configuration.add_section('sifttter_redux')
42
+ Configuration['sifttter_redux'].merge!('config_location' => Configuration.config_path)
43
+
44
+ # Run the wizard to download Dropbox Uploader.
45
+ DBU::install_wizard
46
+
47
+ # Collect other misc. preferences.
48
+ CliMessage.section_block('COLLECTING PREFERENCES...') do
49
+ pref_prompts = [
50
+ {
51
+ prompt: 'Location for downloaded Sifttter files from Dropbox',
52
+ default: SFT_LOCAL_FILEPATH,
53
+ key: 'sifttter_local_filepath',
54
+ section: 'sifttter_redux'
55
+ },
56
+ {
57
+ prompt: 'Location of Sifttter files in Dropbox',
58
+ default: SFT_REMOTE_FILEPATH,
59
+ key: 'sifttter_remote_filepath',
60
+ section: 'sifttter_redux'
61
+ },
62
+ {
63
+ prompt: 'Location for downloaded Day One files from Dropbox',
64
+ default: DO_LOCAL_FILEPATH,
65
+ key: 'dayone_local_filepath',
66
+ section: 'sifttter_redux'
67
+ },
68
+ {
69
+ prompt: 'Location of Day One files in Dropbox',
70
+ default: DO_REMOTE_FILEPATH,
71
+ key: 'dayone_remote_filepath',
72
+ section: 'sifttter_redux'
73
+ }
74
+ ]
75
+
76
+ pref_prompts.each do |prompt|
77
+ pref = CliMessage.prompt(prompt[:prompt], prompt[:default])
78
+ Configuration[prompt[:section]].merge!(prompt[:key] => pref)
79
+ end
80
+ end
81
+
82
+ Configuration.save
83
+ end
84
+
85
+ # ----------------------------------------------------
86
+ # verbose method
87
+ #
88
+ # Returns the verbosity state.
89
+ # @return Bool
90
+ # ----------------------------------------------------
91
+ def self.verbose
92
+ @verbose_output
93
+ end
94
+
95
+ # ----------------------------------------------------
96
+ # verbose= method
97
+ #
98
+ # Sets the verbosity state.
99
+ # @return Void
100
+ # ----------------------------------------------------
101
+ def self.verbose=(verbose)
102
+ @verbose_output = verbose
103
+ end
104
+
105
+ end
@@ -0,0 +1,126 @@
1
+ module SifttterRedux
2
+ # ======================================================
3
+ # CliManager Module
4
+ # Singleton to manage common CLI interfacing
5
+ # ======================================================
6
+ module CliMessage
7
+ # ----------------------------------------------------
8
+ # error method
9
+ #
10
+ # Outputs a formatted-red error message.
11
+ # @param m The message to output
12
+ # @return Void
13
+ # ----------------------------------------------------
14
+ def self.error(m)
15
+ puts "---> ERROR: #{ m }".red
16
+ end
17
+
18
+ # ----------------------------------------------------
19
+ # info method
20
+ #
21
+ # Outputs a formatted-blue informational message.
22
+ # @param m The message to output
23
+ # @return Void
24
+ # ----------------------------------------------------
25
+ def self.info(m)
26
+ puts "---> INFO: #{ m }".blue
27
+ end
28
+
29
+ # ----------------------------------------------------
30
+ # info_block method
31
+ #
32
+ # Wraps a block in an opening and closing info message.
33
+ # @param m1 The opening message to output
34
+ # @param m2 The closing message to output
35
+ # @param multiline Whether the message should be multiline
36
+ # @return Void
37
+ # ----------------------------------------------------
38
+ def self.info_block(m1, m2 = 'Done.', multiline = false)
39
+ if multiline
40
+ info(m1)
41
+ else
42
+ print "---> INFO: #{ m1 }".blue
43
+ end
44
+
45
+ yield
46
+
47
+ if multiline
48
+ info(m2)
49
+ else
50
+ puts m2.blue
51
+ end
52
+ end
53
+
54
+ # ----------------------------------------------------
55
+ # prompt method
56
+ #
57
+ # Outputs a prompt, collects the user's response, and
58
+ # returns it.
59
+ # @param prompt The prompt to output
60
+ # @param default The default option
61
+ # @return String
62
+ # ----------------------------------------------------
63
+ def self.prompt(prompt, default)
64
+ print "#{ prompt } [default: #{ default }]: "
65
+ choice = $stdin.gets.chomp
66
+ if choice.empty?
67
+ return default
68
+ else
69
+ return choice
70
+ end
71
+ end
72
+
73
+ # ----------------------------------------------------
74
+ # section method
75
+ #
76
+ # Outputs a formatted-orange section message.
77
+ # @param m The message to output
78
+ # @return Void
79
+ # ----------------------------------------------------
80
+ def self.section(m)
81
+ puts "#### #{ m }".purple
82
+ end
83
+
84
+ # ----------------------------------------------------
85
+ # section_block method
86
+ #
87
+ # Wraps a block in an opening and closing section
88
+ # message.
89
+ # @param m1 The opening message to output
90
+ # @param m2 The closing message to output
91
+ # @param multiline A multiline message or not
92
+ # @return Void
93
+ # ----------------------------------------------------
94
+ def self.section_block(m, multiline = true)
95
+ if multiline
96
+ section(m)
97
+ else
98
+ print "#### #{ m }".purple
99
+ end
100
+
101
+ yield
102
+ end
103
+
104
+ # ----------------------------------------------------
105
+ # success method
106
+ #
107
+ # Outputs a formatted-green success message.
108
+ # @param m The message to output
109
+ # @return Void
110
+ # ----------------------------------------------------
111
+ def self.success(m)
112
+ puts "---> SUCCESS: #{ m }".green
113
+ end
114
+
115
+ # ----------------------------------------------------
116
+ # warning method
117
+ #
118
+ # Outputs a formatted-yellow warning message.
119
+ # @param m The message to output
120
+ # @return Void
121
+ # ----------------------------------------------------
122
+ def self.warning(m)
123
+ puts "---> WARNING: #{ m }".yellow
124
+ end
125
+ end
126
+ end
@@ -0,0 +1,122 @@
1
+ require 'yaml'
2
+
3
+ module SifttterRedux
4
+ # ======================================================
5
+ # Configuration Module
6
+ #
7
+ # Manages any configuration values and the flat file
8
+ # into which they get stored.
9
+ # ======================================================
10
+ module Configuration
11
+ # ----------------------------------------------------
12
+ # [] method
13
+ #
14
+ # Returns the Hash of data for a particular section.
15
+ # @param section_name The section in which to look
16
+ # @return Hash
17
+ # ----------------------------------------------------
18
+ def self.[](section_name)
19
+ @data[section_name]
20
+ end
21
+
22
+ # ----------------------------------------------------
23
+ # add_section method
24
+ #
25
+ # Creates a new section in the configuration data.
26
+ # @param section_name The section to add
27
+ # @return Void
28
+ # ----------------------------------------------------
29
+ def self.add_section(section_name)
30
+ if !self.section_exists?(section_name)
31
+ @data[section_name] = {}
32
+ else
33
+ CliMessage.warning("Can't create already-existing section: #{section_name}")
34
+ end
35
+ end
36
+
37
+ # ----------------------------------------------------
38
+ # config_path method
39
+ #
40
+ # Returns the filepath to the flat configuration file.
41
+ # @return String
42
+ # ----------------------------------------------------
43
+ def self.config_path
44
+ @config_path
45
+ end
46
+
47
+ # ----------------------------------------------------
48
+ # delete_section method
49
+ #
50
+ # Deletes a section from the configuration data.
51
+ # @param section_name The section to delete
52
+ # @return Void
53
+ # ----------------------------------------------------
54
+ def self.delete_section(section_name)
55
+ if self.section_exists?(section_name)
56
+ @data.delete(section_name)
57
+ else
58
+ CliMessage.warning("Can't delete non-existing section: #{section_name}")
59
+ end
60
+ end
61
+
62
+ # ----------------------------------------------------
63
+ # load method
64
+ #
65
+ # Loads the configuration data (if it exists) and sets
66
+ # the filepath to the flat file.
67
+ # @param path The filepath
68
+ # @return Void
69
+ # ----------------------------------------------------
70
+ def self.load(path)
71
+ @config_path = path
72
+
73
+ if File.exists?(path)
74
+ @data = YAML.load_file(path)
75
+ else
76
+ @data = {}
77
+ end
78
+ end
79
+
80
+ # ----------------------------------------------------
81
+ # reset method
82
+ #
83
+ # Clears the configuration data.
84
+ # @return Void
85
+ # ----------------------------------------------------
86
+ def self.reset
87
+ @data = {}
88
+ end
89
+
90
+ # ----------------------------------------------------
91
+ # save method
92
+ #
93
+ # Saves the configuration data to the previously
94
+ # stored flat file.
95
+ # @return Void
96
+ # ----------------------------------------------------
97
+ def self.save
98
+ File.open(@config_path, 'w') { |f| f.write(@data.to_yaml) }
99
+ end
100
+
101
+ # ----------------------------------------------------
102
+ # section_exists? method
103
+ #
104
+ # Checks for the existance of the passed section.
105
+ # @param section_name The section to look for
106
+ # @return Bool
107
+ # ----------------------------------------------------
108
+ def self.section_exists?(section_name)
109
+ @data.key?(section_name)
110
+ end
111
+
112
+ # ----------------------------------------------------
113
+ # to_s method
114
+ #
115
+ # Method to output this Module as a String.
116
+ # @return Void
117
+ # ----------------------------------------------------
118
+ def self.to_s
119
+ puts @data
120
+ end
121
+ end
122
+ end
@@ -0,0 +1,120 @@
1
+ require 'chronic'
2
+
3
+ module SifttterRedux
4
+ # ======================================================
5
+ # Configuration Module
6
+ #
7
+ # Manages any configuration values and the flat file
8
+ # into which they get stored.
9
+ # ======================================================
10
+ module DateRangeMaker
11
+
12
+ # ------------------------------------------------------
13
+ # last_n_days method
14
+ #
15
+ # Returns a date range for the last N days (including
16
+ # today's date if specified).
17
+ # @param num_days The number of days to look back
18
+ # @param include_today Should today be included?
19
+ # @return Range
20
+ # ------------------------------------------------------
21
+ def self.last_n_days(num_days, include_today = false)
22
+ fail ArgumentError, 'Cannot specify a negative number of days' if num_days < 0
23
+
24
+ if include_today
25
+ (Date.today - num_days..Date.today)
26
+ else
27
+ (Date.today - num_days...Date.today)
28
+ end
29
+ end
30
+
31
+ # ------------------------------------------------------
32
+ # last_n_weeks method
33
+ #
34
+ # Returns a date range for the last N weeks (including
35
+ # today's date if specified).
36
+ # @param num_days The number of weeks to look back
37
+ # @param include_today Should today be included?
38
+ # @return Range
39
+ # ------------------------------------------------------
40
+ def self.last_n_weeks(num_weeks = 0, include_today = false)
41
+ fail ArgumentError, 'Cannot specify a negative number of weeks' if num_weeks < 0
42
+
43
+ beginning_date = Date.today - Date.today.wday + 1
44
+ end_date = Date.today - Date.today.wday + 7
45
+
46
+ # We coerce the end date to be today if a date
47
+ # greater than today has been specified.
48
+ end_date = Date.today if end_date > Date.today
49
+
50
+ if include_today
51
+ (beginning_date - num_weeks * 7..end_date)
52
+ else
53
+ (beginning_date - num_weeks * 7...end_date)
54
+ end
55
+ end
56
+
57
+ # ------------------------------------------------------
58
+ # range method
59
+ #
60
+ # Returns a date range for specified start dates and
61
+ # end dates. Note that specifying an end date greater
62
+ # than today's date will force today to be the end date.
63
+ # @param start_date The start date
64
+ # @param end_date The end date
65
+ # @param options Miscellaneous options hash
66
+ # @return Range
67
+ # ------------------------------------------------------
68
+ def self.from_to(start_date, end_date, include_today = false)
69
+ fail ArgumentError, "You can't specify -t without specifying -f" if start_date.nil? && !end_date.nil?
70
+
71
+ begin
72
+ chronic_start_date = Chronic.parse(start_date).to_date
73
+ rescue
74
+ fail ArgumentError, "Invalid date provided to Chronic: #{ start_date }" unless start_date.nil?
75
+ nil
76
+ end
77
+
78
+ begin
79
+ chronic_end_date = Chronic.parse(end_date).to_date
80
+ rescue
81
+ fail ArgumentError, "Invalid date provided to Chronic: #{ end_date }" unless end_date.nil?
82
+ nil
83
+ end
84
+
85
+ fail ArgumentError, 'The start date must be before or equal to the end date' if chronic_end_date && chronic_start_date > chronic_end_date
86
+
87
+ unless chronic_start_date.nil?
88
+ if chronic_end_date.nil?
89
+ if include_today
90
+ (chronic_start_date..Date.today)
91
+ else
92
+ (chronic_start_date...Date.today)
93
+ end
94
+ else
95
+ (chronic_start_date..chronic_end_date)
96
+ end
97
+ end
98
+ end
99
+
100
+ # ------------------------------------------------------
101
+ # today method
102
+ #
103
+ # Returns a date range for today
104
+ # @return Range
105
+ # ------------------------------------------------------
106
+ def self.today
107
+ (Date.today..Date.today)
108
+ end
109
+
110
+ # ------------------------------------------------------
111
+ # yesterday method
112
+ #
113
+ # Returns a date range for yesterday
114
+ # @return Range
115
+ # ------------------------------------------------------
116
+ def self.yesterday
117
+ (Date.today - 1..Date.today - 1)
118
+ end
119
+ end
120
+ end