sifttter-redux 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- data/.gitignore +8 -0
- data/HISTORY.md +7 -0
- data/LICENSE +21 -0
- data/README.md +227 -0
- data/Rakefile +44 -0
- data/Sifttter-Redux.gemspec +30 -0
- data/bin/srd +212 -0
- data/lib/Sifttter-Redux/cli-message.rb +135 -0
- data/lib/Sifttter-Redux/config-manager.rb +136 -0
- data/lib/Sifttter-Redux/constants.rb +15 -0
- data/lib/Sifttter-Redux/date-range-maker.rb +102 -0
- data/lib/Sifttter-Redux/methods.rb +190 -0
- data/lib/Sifttter-Redux/os.rb +47 -0
- data/lib/Sifttter-Redux.rb +6 -0
- data/test/catch_up_test.rb +56 -0
- data/test/test_helper.rb +9 -0
- metadata +129 -0
@@ -0,0 +1,135 @@
|
|
1
|
+
#| ======================================================
|
2
|
+
#| CliManager Module
|
3
|
+
#| Singleton to manage common CLI interfacing
|
4
|
+
#| ======================================================
|
5
|
+
module CliMessage
|
6
|
+
|
7
|
+
ERROR = 1
|
8
|
+
INFO = 2
|
9
|
+
SECTION = 3
|
10
|
+
WARNING = 4
|
11
|
+
|
12
|
+
#| ------------------------------------------------------
|
13
|
+
#| error method
|
14
|
+
#|
|
15
|
+
#| Outputs a formatted-red error message.
|
16
|
+
#| @param message The message to output
|
17
|
+
#| @return Void
|
18
|
+
#| ------------------------------------------------------
|
19
|
+
def self.error(message, addNewline = true)
|
20
|
+
if addNewline
|
21
|
+
puts "---> ERROR: #{message}".red
|
22
|
+
else
|
23
|
+
print "---> ERROR: #{message}".red
|
24
|
+
end
|
25
|
+
|
26
|
+
@@last_message_type = ERROR
|
27
|
+
end
|
28
|
+
|
29
|
+
#| ------------------------------------------------------
|
30
|
+
#| finish_message method
|
31
|
+
#|
|
32
|
+
#| Finishes a previous message by appending "DONE" in the
|
33
|
+
#| correct color.
|
34
|
+
#| @return Void
|
35
|
+
#| ------------------------------------------------------
|
36
|
+
def self.finish_message(message)
|
37
|
+
case @@last_message_type
|
38
|
+
when ERROR
|
39
|
+
puts message.red
|
40
|
+
when INFO
|
41
|
+
puts message.blue
|
42
|
+
when SECTION
|
43
|
+
puts message.green
|
44
|
+
when WARNING
|
45
|
+
puts message.yellow
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
#| ------------------------------------------------------
|
50
|
+
#| info method
|
51
|
+
#|
|
52
|
+
#| Outputs a formatted-blue informational message.
|
53
|
+
#| @param message The message to output
|
54
|
+
#| @return Void
|
55
|
+
#| ------------------------------------------------------
|
56
|
+
def self.info(message, addNewline = true)
|
57
|
+
if addNewline
|
58
|
+
puts "---> INFO: #{message}".blue
|
59
|
+
else
|
60
|
+
print "---> INFO: #{message}".blue
|
61
|
+
end
|
62
|
+
|
63
|
+
@@last_message_type = INFO
|
64
|
+
end
|
65
|
+
|
66
|
+
#| ------------------------------------------------------
|
67
|
+
#| prompt method
|
68
|
+
#|
|
69
|
+
#| Outputs a prompt, collects the user's response, and
|
70
|
+
#| returns it.
|
71
|
+
#| @param prompt The prompt to output
|
72
|
+
#| @param default The default option
|
73
|
+
#| @return String
|
74
|
+
#| ------------------------------------------------------
|
75
|
+
def self.prompt(prompt, default)
|
76
|
+
print "#{prompt} [default: #{default}]: "
|
77
|
+
choice = $stdin.gets.chomp
|
78
|
+
if choice.empty?
|
79
|
+
return default
|
80
|
+
else
|
81
|
+
return choice
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
#| ------------------------------------------------------
|
86
|
+
#| section method
|
87
|
+
#|
|
88
|
+
#| Outputs a formatted-orange section message.
|
89
|
+
#| @param message The message to output
|
90
|
+
#| @return Void
|
91
|
+
#| ------------------------------------------------------
|
92
|
+
def self.section(message, addNewline = true)
|
93
|
+
if addNewline
|
94
|
+
puts "#### #{message}".green
|
95
|
+
else
|
96
|
+
print "#### #{message}".green
|
97
|
+
end
|
98
|
+
|
99
|
+
@@last_message_type = SECTION
|
100
|
+
end
|
101
|
+
|
102
|
+
#| ------------------------------------------------------
|
103
|
+
#| success method
|
104
|
+
#|
|
105
|
+
#| Outputs a formatted-green success message.
|
106
|
+
#| @param message The message to output
|
107
|
+
#| @return Void
|
108
|
+
#| ------------------------------------------------------
|
109
|
+
def self.success(message, addNewline = true)
|
110
|
+
if addNewline
|
111
|
+
puts "---> SUCCESS: #{message}".green
|
112
|
+
else
|
113
|
+
print "---> SUCCESS: #{message}".green
|
114
|
+
end
|
115
|
+
|
116
|
+
@@last_message_type = WARNING
|
117
|
+
end
|
118
|
+
|
119
|
+
#| ------------------------------------------------------
|
120
|
+
#| warning method
|
121
|
+
#|
|
122
|
+
#| Outputs a formatted-yellow warning message.
|
123
|
+
#| @param message The message to output
|
124
|
+
#| @return Void
|
125
|
+
#| ------------------------------------------------------
|
126
|
+
def self.warning(message, addNewline = true)
|
127
|
+
if addNewline
|
128
|
+
puts "---> WARNING: #{message}".yellow
|
129
|
+
else
|
130
|
+
print "---> WARNING: #{message}".yellow
|
131
|
+
end
|
132
|
+
|
133
|
+
@@last_message_type = WARNING
|
134
|
+
end
|
135
|
+
end
|
@@ -0,0 +1,136 @@
|
|
1
|
+
require 'singleton'
|
2
|
+
|
3
|
+
#| ======================================================
|
4
|
+
#| ConfigManager Class
|
5
|
+
#|
|
6
|
+
#| Singleton to manage the YAML config file
|
7
|
+
#| for this script
|
8
|
+
#| ======================================================
|
9
|
+
|
10
|
+
class ConfigManager
|
11
|
+
include Singleton
|
12
|
+
|
13
|
+
attr_accessor :configFile
|
14
|
+
|
15
|
+
#| ------------------------------------------------------
|
16
|
+
#| initialize method
|
17
|
+
#|
|
18
|
+
#| Initializes this singleton with data from the config
|
19
|
+
#| file. If the file doesn't exist, an empty hash is
|
20
|
+
#| created in anticipation of future config saves.
|
21
|
+
#| @return Void
|
22
|
+
#| ------------------------------------------------------
|
23
|
+
def initialize
|
24
|
+
@configFile = SifttterRedux::SRD_CONFIG_FILEPATH
|
25
|
+
|
26
|
+
if File.exists?(SifttterRedux::SRD_CONFIG_FILEPATH)
|
27
|
+
@data = YAML.load_file(SifttterRedux::SRD_CONFIG_FILEPATH)
|
28
|
+
@data.each do |k, v|
|
29
|
+
define_singleton_method(k) { return v }
|
30
|
+
end
|
31
|
+
else
|
32
|
+
@data = {}
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
#| ------------------------------------------------------
|
37
|
+
#| _dump method
|
38
|
+
#|
|
39
|
+
#| Convenience method that dumps the configuration hash's
|
40
|
+
#| data.
|
41
|
+
#| @return Void
|
42
|
+
#| ------------------------------------------------------
|
43
|
+
def _dump
|
44
|
+
puts @data
|
45
|
+
end
|
46
|
+
|
47
|
+
#| ------------------------------------------------------
|
48
|
+
#| add_to_section method
|
49
|
+
#|
|
50
|
+
#| Adds a hash to the configuration data.
|
51
|
+
#| @param hash The hash to add to configuration
|
52
|
+
#| @param section The section into which the hash goes
|
53
|
+
#| @return Void
|
54
|
+
#| ------------------------------------------------------
|
55
|
+
def add_to_section(hash, section)
|
56
|
+
unless @data.has_key?(section)
|
57
|
+
CliMessage.warning("Attempting to insert into a non-existing section: #{section}; skipping...")
|
58
|
+
return
|
59
|
+
end
|
60
|
+
|
61
|
+
@data[section].merge!(hash)
|
62
|
+
end
|
63
|
+
|
64
|
+
#| ------------------------------------------------------
|
65
|
+
#| create_section method
|
66
|
+
#|
|
67
|
+
#| Creates a new section in the configuration hash.
|
68
|
+
#| @param section The section to create
|
69
|
+
#| @return Void
|
70
|
+
#| ------------------------------------------------------
|
71
|
+
def create_section(section)
|
72
|
+
if @data.has_key?(section)
|
73
|
+
CliMessage.warning("Attempting to create existing section (#{section}); skipping...")
|
74
|
+
return
|
75
|
+
end
|
76
|
+
|
77
|
+
define_singleton_method(section) { return @data[section] }
|
78
|
+
@data.merge!(section => {})
|
79
|
+
end
|
80
|
+
|
81
|
+
#| ------------------------------------------------------
|
82
|
+
#| delete_section method
|
83
|
+
#|
|
84
|
+
#| Deletes a section in the configuration hash.
|
85
|
+
#| @param section The section to delete
|
86
|
+
#| @return Void
|
87
|
+
#| ------------------------------------------------------
|
88
|
+
def delete_section(section)
|
89
|
+
unless @data.has_key?(section)
|
90
|
+
CliMessage.warning("Attempting to delete non-existing section (#{section}); skipping...")
|
91
|
+
return
|
92
|
+
end
|
93
|
+
|
94
|
+
remove_singleton_method(section)
|
95
|
+
@data.delete(section)
|
96
|
+
end
|
97
|
+
|
98
|
+
#| ------------------------------------------------------
|
99
|
+
#| remove_singleton_method method
|
100
|
+
#|
|
101
|
+
#| Removes a hash from the configuration data based on
|
102
|
+
#| its key.
|
103
|
+
#| @param hash The hash key remove
|
104
|
+
#| @param section The section from which the key comes
|
105
|
+
#| @return Void
|
106
|
+
#| ------------------------------------------------------
|
107
|
+
def remove_from_section(key, section)
|
108
|
+
unless @data.has_key?(section) && @data[section].has_key?(key)
|
109
|
+
CliMessage.warning("Attempting to remove a non-existing key: #{section}.#{key}; skipping...")
|
110
|
+
return
|
111
|
+
end
|
112
|
+
|
113
|
+
@data[section].delete(key)
|
114
|
+
end
|
115
|
+
|
116
|
+
#| ------------------------------------------------------
|
117
|
+
#| reset method
|
118
|
+
#|
|
119
|
+
#| Clears out the configuration data by resetting the hash.
|
120
|
+
#| @return Void
|
121
|
+
#| ------------------------------------------------------
|
122
|
+
def reset
|
123
|
+
@data = {}
|
124
|
+
end
|
125
|
+
|
126
|
+
#| ------------------------------------------------------
|
127
|
+
#| save_configuration method
|
128
|
+
#|
|
129
|
+
#| Saves the configuration data to the filesystem.
|
130
|
+
#| @return File
|
131
|
+
#| ------------------------------------------------------
|
132
|
+
def save_configuration
|
133
|
+
return File.open(@configFile, 'w') { |f| f.write(@data.to_yaml) }
|
134
|
+
end
|
135
|
+
|
136
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module SifttterRedux
|
2
|
+
VERSION = "0.2.0"
|
3
|
+
|
4
|
+
# Sifttter and Sifttter Redux Constants
|
5
|
+
SRD_CONFIG_FILEPATH = File.join(ENV['HOME'], '.sifttter_redux')
|
6
|
+
SFT_LOCAL_FILEPATH = "/tmp/sifttter"
|
7
|
+
SFT_REMOTE_FILEPATH = "/Apps/ifttt/sifttter"
|
8
|
+
|
9
|
+
# Dropbox Upload Constants
|
10
|
+
DBU_LOCAL_FILEPATH = "/usr/local/opt"
|
11
|
+
|
12
|
+
# Day One Constants
|
13
|
+
DO_REMOTE_FILEPATH = "/Apps/Day\\ One/Journal.dayone/entries"
|
14
|
+
DO_LOCAL_FILEPATH = "/tmp/dayone"
|
15
|
+
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
require 'chronic'
|
2
|
+
|
3
|
+
class DateRangeMakerError < StandardError
|
4
|
+
def initialize(msg = "You've triggered a DateRangeMakerError")
|
5
|
+
super
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
class BadChronicDateError < DateRangeMakerError
|
10
|
+
def initialize(msg = "Invalid date provided to Chronic...")
|
11
|
+
super
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
class BadDateOrderError < DateRangeMakerError
|
16
|
+
def initialize(msg = "The start date must be before or equal to the end date...")
|
17
|
+
super
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
class InvalidFlagsError < DateRangeMakerError
|
22
|
+
def initialize(msg = "You can't specify -t without specifying -f...")
|
23
|
+
super
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
#| ======================================================
|
28
|
+
#| DateRangeMaker Class
|
29
|
+
#|
|
30
|
+
#| Singleton to manage the YAML config file
|
31
|
+
#| for this script
|
32
|
+
#| ======================================================
|
33
|
+
class DateRangeMaker
|
34
|
+
|
35
|
+
def initialize
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
def last_seven_days(include_today = false)
|
40
|
+
if (include_today)
|
41
|
+
_r = (Date.today - 7..Date.today)
|
42
|
+
else
|
43
|
+
_r = (Date.today - 7...Date.today)
|
44
|
+
end
|
45
|
+
|
46
|
+
return _r
|
47
|
+
end
|
48
|
+
|
49
|
+
def range(options = {})
|
50
|
+
|
51
|
+
opts = {
|
52
|
+
:start_date => Date.today,
|
53
|
+
:end_date => nil,
|
54
|
+
:include_today => false
|
55
|
+
}
|
56
|
+
|
57
|
+
options.each do |k, v|
|
58
|
+
k = k.to_sym
|
59
|
+
raise ArgumentError, "Unknown property: #{k}" unless opts.key?(k)
|
60
|
+
opts[k] = v
|
61
|
+
end
|
62
|
+
|
63
|
+
begin
|
64
|
+
chronic_start_date = Chronic.parse(opts[:start_date]).to_date
|
65
|
+
rescue
|
66
|
+
raise BadChronicDateError.new("Invalid date provided to Chronic: #{opts[:start_date]}") if !opts[:start_date].nil?
|
67
|
+
nil
|
68
|
+
end
|
69
|
+
|
70
|
+
begin
|
71
|
+
chronic_end_date = Chronic.parse(opts[:end_date]).to_date
|
72
|
+
rescue
|
73
|
+
raise BadChronicDateError.new("Invalid date provided to Chronic: #{opts[:end_date]}") if !opts[:end_date].nil?
|
74
|
+
nil
|
75
|
+
end
|
76
|
+
|
77
|
+
raise InvalidFlagsError.new if (opts[:start_date].nil? && !opts[:end_date].nil?)
|
78
|
+
raise BadDateOrderError.new if (chronic_end_date && chronic_start_date > chronic_end_date)
|
79
|
+
|
80
|
+
if (!chronic_start_date.nil?)
|
81
|
+
if (chronic_end_date.nil?)
|
82
|
+
if (opts[:include_today])
|
83
|
+
dates = (chronic_start_date..Date.today)
|
84
|
+
else
|
85
|
+
dates = (chronic_start_date...Date.today)
|
86
|
+
end
|
87
|
+
else
|
88
|
+
dates = (chronic_start_date..chronic_end_date)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
return dates
|
93
|
+
end
|
94
|
+
|
95
|
+
def today
|
96
|
+
return (Date.today..Date.today)
|
97
|
+
end
|
98
|
+
|
99
|
+
def yesterday
|
100
|
+
return (Date.today - 1..Date.today - 1)
|
101
|
+
end
|
102
|
+
end
|
@@ -0,0 +1,190 @@
|
|
1
|
+
#| ======================================================
|
2
|
+
#| METHODS
|
3
|
+
#| ======================================================
|
4
|
+
|
5
|
+
#| ------------------------------------------------------
|
6
|
+
#| collect_preferences method
|
7
|
+
#|
|
8
|
+
#| Collects preferences from the user and stores the
|
9
|
+
#| entered values into a configuration file.
|
10
|
+
#| @return Void
|
11
|
+
#| ------------------------------------------------------
|
12
|
+
def collect_preferences
|
13
|
+
CliMessage.section('COLLECTING PREFERENCES...')
|
14
|
+
|
15
|
+
pref = CliMessage.prompt("Location for downloaded Sifttter files from Dropbox", SifttterRedux::SFT_LOCAL_FILEPATH)
|
16
|
+
$config.add_to_section({"sifttter_local_filepath" => pref}, "sifttter_redux")
|
17
|
+
|
18
|
+
pref = CliMessage.prompt("Location of Sifttter files in Dropbox", SifttterRedux::SFT_REMOTE_FILEPATH)
|
19
|
+
$config.add_to_section({"sifttter_remote_filepath" => pref}, "sifttter_redux")
|
20
|
+
|
21
|
+
pref = CliMessage.prompt("Location for downloaded Day One files from Dropbox", SifttterRedux::DO_LOCAL_FILEPATH)
|
22
|
+
$config.add_to_section({"dayone_local_filepath" => pref}, "sifttter_redux")
|
23
|
+
|
24
|
+
pref = CliMessage.prompt("Location of Day One files in Dropbox", SifttterRedux::DO_REMOTE_FILEPATH)
|
25
|
+
$config.add_to_section({"dayone_remote_filepath" => pref}, "sifttter_redux")
|
26
|
+
end
|
27
|
+
|
28
|
+
#| ------------------------------------------------------
|
29
|
+
#| download_sifttter_files method
|
30
|
+
#|
|
31
|
+
#| Downloads Sifttter files from Dropbox
|
32
|
+
#| @return Void
|
33
|
+
#| ------------------------------------------------------
|
34
|
+
def download_sifttter_files
|
35
|
+
# Download all Sifttter files from Dropbox.
|
36
|
+
CliMessage.info('Downloading Sifttter files...', false)
|
37
|
+
`#{$db_uploader} download #{$config.sifttter_redux["sifttter_remote_filepath"]} #{$config.sifttter_redux["sifttter_local_filepath"]}`
|
38
|
+
CliMessage.finish_message('DONE.')
|
39
|
+
end
|
40
|
+
|
41
|
+
#| ------------------------------------------------------
|
42
|
+
#| initialize_procedures method
|
43
|
+
#|
|
44
|
+
#| Initializes Sifttter Redux by downloading and collecting
|
45
|
+
#| all necessary items and info.
|
46
|
+
#| @return Void
|
47
|
+
#| ------------------------------------------------------
|
48
|
+
def initialize_procedures
|
49
|
+
$config.reset
|
50
|
+
$config.create_section("sifttter_redux")
|
51
|
+
$config.add_to_section({"config_location" => $config.configFile}, "sifttter_redux")
|
52
|
+
|
53
|
+
install_db_uploader
|
54
|
+
collect_preferences
|
55
|
+
|
56
|
+
CliMessage.section("INITIALIZATION COMPLETE!")
|
57
|
+
|
58
|
+
$config.save_configuration
|
59
|
+
end
|
60
|
+
|
61
|
+
#| ------------------------------------------------------
|
62
|
+
#| install_db_uploader method
|
63
|
+
#|
|
64
|
+
#| Installs Dropbox Uploader to a user-specified location
|
65
|
+
#| by cloning the git repository.
|
66
|
+
#| @return Void
|
67
|
+
#| ------------------------------------------------------
|
68
|
+
def install_db_uploader
|
69
|
+
valid_directory_chosen = false
|
70
|
+
|
71
|
+
CliMessage.section('DOWNLOADING DROPBOX UPLOADER...')
|
72
|
+
|
73
|
+
# Create a new configuration section for Dropbox-Uploader
|
74
|
+
$config.create_section("db_uploader")
|
75
|
+
|
76
|
+
until valid_directory_chosen
|
77
|
+
# Prompt the user for a location to save Dropbox Uploader. "
|
78
|
+
db_uploader_location = CliMessage.prompt("Location for Dropbox-Uploader", SifttterRedux::DBU_LOCAL_FILEPATH)
|
79
|
+
db_uploader_location.chop! if db_uploader_location.end_with?('/')
|
80
|
+
db_uploader_location = "/usr/local/opt" if db_uploader_location.empty?
|
81
|
+
|
82
|
+
# If the entered directory exists, clone the repository.
|
83
|
+
if File.directory?(db_uploader_location)
|
84
|
+
valid_directory_chosen = true
|
85
|
+
db_uploader_location << "/Dropbox-Uploader"
|
86
|
+
|
87
|
+
# If, for some reason, Dropbox Uploader alread exists at this location,
|
88
|
+
# skip the clone.
|
89
|
+
if File.directory?(db_uploader_location)
|
90
|
+
CliMessage.info("You seem to already have Dropbox Uploader at this location; skipping...")
|
91
|
+
else
|
92
|
+
%x{git clone https://github.com/andreafabrizi/Dropbox-Uploader.git #{db_uploader_location}}
|
93
|
+
end
|
94
|
+
|
95
|
+
# Save config data to YAML.
|
96
|
+
$config.add_to_section({"local_filepath" => db_uploader_location}, "db_uploader")
|
97
|
+
else
|
98
|
+
puts "Sorry, but #{db_uploader_location} isn't a valid directory."
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
#| ------------------------------------------------------
|
104
|
+
#| run_sifttter method
|
105
|
+
#|
|
106
|
+
#| Modified form of Sifttter
|
107
|
+
#|
|
108
|
+
#| Sifttter: An IFTTT-to-Day One Logger by Craig Eley 2014
|
109
|
+
#| Based on tp-dailylog.rb by Brett Terpstra 2012
|
110
|
+
#| @param date The date to use when scanning Sifttter files
|
111
|
+
#| @return Void
|
112
|
+
#| ------------------------------------------------------
|
113
|
+
def run_sifttter(date)
|
114
|
+
uuid_command = "uuidgen" if OS.mac?
|
115
|
+
uuid_command = "uuid" if OS.linux?
|
116
|
+
uuid = %x{#{uuid_command}}.gsub(/-/,'').strip
|
117
|
+
|
118
|
+
date_for_title = date.strftime('%B %d, %Y')
|
119
|
+
datestamp = date.to_time.utc.iso8601
|
120
|
+
starred = false
|
121
|
+
|
122
|
+
template = ERB.new <<-XMLTEMPLATE
|
123
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
124
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
125
|
+
<plist version="1.0">
|
126
|
+
<dict>
|
127
|
+
<key>Creation Date</key>
|
128
|
+
<date><%= datestamp %></date>
|
129
|
+
<key>Entry Text</key>
|
130
|
+
<string><%= entrytext %></string>
|
131
|
+
<key>Starred</key>
|
132
|
+
<<%= starred %>/>
|
133
|
+
<key>Tags</key>
|
134
|
+
<array>
|
135
|
+
<string>daily logs</string>
|
136
|
+
</array>
|
137
|
+
<key>UUID</key>
|
138
|
+
<string><%= uuid %></string>
|
139
|
+
</dict>
|
140
|
+
</plist>
|
141
|
+
XMLTEMPLATE
|
142
|
+
|
143
|
+
date_regex = "#{date.strftime('%B')} 0?#{date.strftime('%-d')}, #{date.strftime('%Y')}"
|
144
|
+
time_regex = "\d{1,2}:\d{1,2}\s?[AaPpMm]{2}"
|
145
|
+
|
146
|
+
files = %x{find #{$config.sifttter_redux["sifttter_local_filepath"]} -type f -name '*.txt' | grep -v -i daily | sort}
|
147
|
+
|
148
|
+
projects = []
|
149
|
+
files.split("\n").each do |file|
|
150
|
+
if File.exists?(file.strip)
|
151
|
+
f = File.open(file.strip, encoding: 'UTF-8')
|
152
|
+
lines = f.read
|
153
|
+
f.close
|
154
|
+
project = "### " + File.basename(file).gsub(/^.*?\/([^\/]+)$/,"\\1") + "\n"
|
155
|
+
|
156
|
+
found_completed = false
|
157
|
+
lines.each_line do |line|
|
158
|
+
if line =~ /&/
|
159
|
+
line.gsub!(/[&]/, 'and')
|
160
|
+
end
|
161
|
+
if line =~ /#{date_regex}/
|
162
|
+
found_completed = true
|
163
|
+
project += line.gsub(/@done/,'').gsub(/#{date_regex}\s(-|at)\s/, '').gsub(/#{time_regex}\s-\s/, '').strip + "\n"
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
167
|
+
if found_completed
|
168
|
+
projects.push(project)
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
if projects.length <=0
|
173
|
+
CliMessage.error("No entries found...")
|
174
|
+
exit!
|
175
|
+
end
|
176
|
+
|
177
|
+
if projects.length > 0
|
178
|
+
entrytext = "# Things done on #{date_for_title}\n\n"
|
179
|
+
projects.each do |project|
|
180
|
+
entrytext += project.gsub(/.txt/, ' ') + "\n\n"
|
181
|
+
end
|
182
|
+
|
183
|
+
Dir.mkdir($config.sifttter_redux["dayone_local_filepath"]) if !Dir.exists?($config.sifttter_redux["dayone_local_filepath"])
|
184
|
+
|
185
|
+
fh = File.new(File.expand_path($config.sifttter_redux["dayone_local_filepath"] + "/" + uuid + ".doentry"), 'w+')
|
186
|
+
fh.puts template.result(binding)
|
187
|
+
fh.close
|
188
|
+
CliMessage.success("Entry logged for #{date_for_title}...")
|
189
|
+
end
|
190
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
#| ======================================================
|
2
|
+
#| OS Module
|
3
|
+
#|
|
4
|
+
#| Module to easily find the running operating system
|
5
|
+
#| ======================================================
|
6
|
+
module OS
|
7
|
+
|
8
|
+
#| ------------------------------------------------------
|
9
|
+
#| linux? method
|
10
|
+
#|
|
11
|
+
#| Returns true if the host OS is Linux (false otherwise).
|
12
|
+
#| @return Bool
|
13
|
+
#| ------------------------------------------------------
|
14
|
+
def OS.linux?
|
15
|
+
OS.unix? and not OS.mac?
|
16
|
+
end
|
17
|
+
|
18
|
+
#| ------------------------------------------------------
|
19
|
+
#| mac? method
|
20
|
+
#|
|
21
|
+
#| Returns true if the host OS is OS X (false otherwise).
|
22
|
+
#| @return Bool
|
23
|
+
#| ------------------------------------------------------
|
24
|
+
def OS.mac?
|
25
|
+
(/darwin/ =~ RUBY_PLATFORM) != nil
|
26
|
+
end
|
27
|
+
|
28
|
+
#| ------------------------------------------------------
|
29
|
+
#| unix? method
|
30
|
+
#|
|
31
|
+
#| Returns true if the host OS is Unix (false otherwise).
|
32
|
+
#| @return Bool
|
33
|
+
#| ------------------------------------------------------
|
34
|
+
def OS.unix?
|
35
|
+
!OS.windows?
|
36
|
+
end
|
37
|
+
|
38
|
+
#| ------------------------------------------------------
|
39
|
+
#| windows? method
|
40
|
+
#|
|
41
|
+
#| Returns true if the host OS is Windows (false otherwise).
|
42
|
+
#| @return Bool
|
43
|
+
#| ------------------------------------------------------
|
44
|
+
def OS.windows?
|
45
|
+
(/cygwin|mswin|mingw|bccwin|wince|emx/ =~ RUBY_PLATFORM) != nil
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'date'
|
2
|
+
require 'test_helper'
|
3
|
+
require File.join(File.dirname(__FILE__), '..', 'lib/Sifttter-Redux/date-range-maker.rb')
|
4
|
+
|
5
|
+
class DefaultTest < Test::Unit::TestCase
|
6
|
+
|
7
|
+
def setup
|
8
|
+
$drm = DateRangeMaker.new
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_today
|
12
|
+
assert_equal($drm.today, (Date.today..Date.today))
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_yesterday
|
16
|
+
assert_equal($drm.yesterday, (Date.today - 1..Date.today - 1))
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_last_7_days
|
20
|
+
assert_equal($drm.last_seven_days, (Date.today - 7...Date.today))
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_last_7_days_include_today
|
24
|
+
assert_equal($drm.last_seven_days(true), (Date.today - 7..Date.today))
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_range_only_start_date
|
28
|
+
assert_equal($drm.range({:start_date => "2014-02-01"}), (Date.parse("2014-02-01")...Date.today))
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_range_only_start_date_include_today
|
32
|
+
assert_equal($drm.range({:start_date => "2014-02-01", :include_today => true}), (Date.parse("2014-02-01")..Date.today))
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_range_start_date_and_end_date
|
36
|
+
assert_equal($drm.range({:start_date => "2014-02-01", :end_date => "2014-02-05"}), (Date.parse("2014-02-01")..Date.parse("2014-02-05")))
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_range_bad_dates
|
40
|
+
assert_raise BadChronicDateError do
|
41
|
+
$drm.range({:start_date => "Bad Start Date", :end_date => "Bad End Date"})
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def test_range_end_date_with_no_start_date
|
46
|
+
assert_raise InvalidFlagsError do
|
47
|
+
$drm.range({:start_date => nil, :end_date => Date.today})
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_range_end_date_before_start_date
|
52
|
+
assert_raise BadDateOrderError do
|
53
|
+
$drm.range({:start_date => Date.today, :end_date => Date.today - 1})
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|