├── tmp
└── srd
│ ├── .dropbox_uploader
│ ├── .sifttter_redux
│ └── .sifttter_redux_log
├── Gemfile
├── .gitignore
├── test
├── test_helper.rb
└── date_range_maker_test.rb
├── .travis.yml
├── features
├── 1.ui.feature
├── step_definitions
│ └── sifttter-redux_steps.rb
├── support
│ └── env.rb
└── 2.initialization.feature
├── res
└── preference_prompts.yaml
├── LICENSE
├── lib
├── sifttter-redux
│ ├── constants.rb
│ ├── dropbox-uploader.rb
│ ├── date-range-maker.rb
│ └── sifttter.rb
└── sifttter-redux.rb
├── Rakefile
├── sifttter-redux.gemspec
├── HISTORY.md
├── bin
└── srd
└── README.md
/tmp/srd/.dropbox_uploader:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/Gemfile:
--------------------------------------------------------------------------------
1 | source 'https://rubygems.org'
2 |
3 | gemspec
4 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | Gemfile.lock
2 | .bundle
3 | .DS_Store
4 | results.html
5 | *.gem
6 | features/3.execution.feature
7 |
--------------------------------------------------------------------------------
/test/test_helper.rb:
--------------------------------------------------------------------------------
1 | require 'test/unit'
2 |
3 | # Add test libraries you want to use here, e.g. mocha
4 |
5 | class Test::Unit::TestCase
6 |
7 | # Add global extensions to the test case class here
8 |
9 | end
10 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: ruby
2 | rvm:
3 | - 2.1.0
4 | - 2.0.0
5 | - 1.9.3
6 | - jruby-19mode
7 | env:
8 | - TEST_SUITE=1.ui.feature
9 | script:
10 | - bundle exec cucumber -f progress -r features features/$TEST_SUITE
11 |
--------------------------------------------------------------------------------
/features/1.ui.feature:
--------------------------------------------------------------------------------
1 | Feature: UI
2 | As a user, when I ask for help, I should be presented
3 | with instructions on how to run the app.
4 |
5 | Scenario: Display help instructions
6 | When I get help for "srd"
7 | Then the exit status should be 0
--------------------------------------------------------------------------------
/features/step_definitions/sifttter-redux_steps.rb:
--------------------------------------------------------------------------------
1 | Given(/^a file located at "(.*?)"$/) do |filepath|
2 | expect(File).to exist(filepath)
3 | end
4 |
5 | Given(/^an empty file located at "(.*?)"$/) do |filepath|
6 | FileUtils.touch(File.expand_path(filepath))
7 | end
8 |
9 | Given(/^a file located at "(.*?)" with the contents:$/) do |filepath, contents|
10 | File.open(filepath, 'w') { |f| f.write(contents) }
11 | end
12 |
13 | Given(/^no file located at "(.*?)"$/) do |filepath|
14 | step %(the file "#{ filepath }" should not exist)
15 | end
16 |
17 | When /^I get help for "([^"]*)"$/ do |app_name|
18 | step %(I run `#{app_name} --help`)
19 | end
20 |
--------------------------------------------------------------------------------
/features/support/env.rb:
--------------------------------------------------------------------------------
1 | require 'aruba/cucumber'
2 |
3 | ENV['PATH'] = "#{File.expand_path(File.dirname(__FILE__) + '/../../bin')}#{File::PATH_SEPARATOR}#{ENV['PATH']}"
4 | LIB_DIR = File.join(File.expand_path(File.dirname(__FILE__)),'..','..','lib')
5 |
6 | Before do
7 | @aruba_timeout_seconds = 25
8 | @puts = true
9 | @original_rubylib = ENV['RUBYLIB']
10 | ENV['RUBYLIB'] = LIB_DIR + File::PATH_SEPARATOR + ENV['RUBYLIB'].to_s
11 | @original_home = ENV['HOME']
12 | ENV['HOME'] = "/tmp/srd"
13 | FileUtils.rm_rf "/tmp/srd"
14 | FileUtils.mkdir "/tmp/srd"
15 | end
16 |
17 | After do
18 | ENV['RUBYLIB'] = @original_rubylib
19 | ENV['HOME'] = @original_home
20 | end
21 |
--------------------------------------------------------------------------------
/tmp/srd/.sifttter_redux:
--------------------------------------------------------------------------------
1 | ---
2 | :sifttter_redux:
3 | :config_location: "/Users/abach/Git/sifttter-redux/features/support/../../tmp/srd/.sifttter_redux"
4 | :log_level: WARN
5 | :version: 0.5.4
6 | :sifttter_local_filepath: "/Users/abach/Git/sifttter-redux/features/support/../../tmp/srd/sifttter_download"
7 | :sifttter_remote_filepath: "/Apps/ifttt/Sifttter"
8 | :dayone_local_filepath: "/Users/abach/Git/sifttter-redux/features/support/../../tmp/srd/day_one_download"
9 | :dayone_remote_filepath: "/Apps/Day\\ One/Journal.dayone/entries"
10 | :db_uploader:
11 | :base_filepath: "/usr/local/opt"
12 | :dbu_filepath: "/usr/local/opt/Dropbox-Uploader"
13 | :exe_filepath: "/usr/local/opt/Dropbox-Uploader/dropbox_uploader.sh"
14 |
--------------------------------------------------------------------------------
/res/preference_prompts.yaml:
--------------------------------------------------------------------------------
1 | prompts:
2 | - prompt_text: Where do you want to download Sifttter files to (temporarily)?
3 | default: /tmp/sifttter
4 | config_key: sifttter_local_filepath
5 | config_section: sifttter_redux
6 | - prompt_text: Where are your Sifttter files located in Dropbox?
7 | default: /Apps/ifttt/sifttter
8 | config_key: sifttter_remote_filepath
9 | config_section: sifttter_redux
10 | - prompt_text: Where do you want to download Day One files to (temporarily)?
11 | default: /tmp/dayone
12 | config_key: dayone_local_filepath
13 | config_section: sifttter_redux
14 | - prompt_text: Where are your Day One files located in Dropbox?
15 | default: /Apps/Day\ One/Journal.dayone/entries
16 | config_key: dayone_remote_filepath
17 | config_section: sifttter_redux
18 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License
2 |
3 | Copyright (c) Tom Preston-Werner
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
--------------------------------------------------------------------------------
/lib/sifttter-redux/constants.rb:
--------------------------------------------------------------------------------
1 | module SifttterRedux
2 | # The default configuration path for Dropbox Uploader
3 | DEFAULT_DBU_CONFIG_FILEPATH = File.join(ENV['HOME'], '.dropbox_uploader')
4 |
5 | # The default local filepath of the Dropbox-Uploader directory
6 | DEFAULT_DBU_LOCAL_FILEPATH = '/usr/local/opt'
7 |
8 | # The default message to display when Dropbox Uploader is running
9 | DEFAULT_DBU_MESSAGE = 'RUNNING DROPBOX UPLOADER'
10 |
11 | # The default local filepath of the Siftter Redux config file
12 | DEFAULT_SRD_CONFIG_FILEPATH = File.join(ENV['HOME'], '.sifttter_redux')
13 |
14 | # The default local filepath of the Siftter Redux log file
15 | DEFAULT_SRD_LOG_FILEPATH = File.join(ENV['HOME'], '.sifttter_redux_log')
16 |
17 | # The Gem's description
18 | DESCRIPTION = 'A customized IFTTT-to-Day One service that allows for smart installation and automated running on a standalone *NIX device (such as a Raspberry Pi).'
19 |
20 | # The last version to require a config update
21 | NEWEST_CONFIG_VERSION = '1.0.0'
22 |
23 | # Hash of preference files
24 | PREF_FILES = {
25 | 'INIT' => File.join(File.dirname(__FILE__), '..', '..', 'res/preference_prompts.yaml')
26 | }
27 |
28 | # The Gem's summary
29 | SUMMARY = 'Automated IFTTT to Day One engine.'
30 |
31 | # The Gem's version
32 | VERSION = '1.0.6'
33 | end
34 |
--------------------------------------------------------------------------------
/Rakefile:
--------------------------------------------------------------------------------
1 | require 'rake/clean'
2 | require 'rubygems'
3 |
4 | def version
5 | contents = File.read File.expand_path('../lib/sifttter-redux/constants.rb', __FILE__)
6 | contents[/\sVERSION = '([^']+)'/, 1]
7 | end
8 |
9 | spec = eval(File.read('sifttter-redux.gemspec'))
10 |
11 | require 'rake/testtask'
12 | desc 'Run unit tests'
13 | Rake::TestTask.new do |t|
14 | t.libs << "test"
15 | t.test_files = FileList['test/*_test.rb']
16 | end
17 |
18 | require 'cucumber'
19 | require 'cucumber/rake/task'
20 | CUKE_RESULTS = 'results.html'
21 | CLEAN << CUKE_RESULTS
22 | desc 'Run Cucumber features'
23 | Cucumber::Rake::Task.new(:features) do |t|
24 | opts = "features --format html -o #{CUKE_RESULTS} --format progress -x"
25 | opts += " --tags #{ENV['TAGS']}" if ENV['TAGS']
26 | t.cucumber_opts = opts
27 | t.fork = false
28 | end
29 |
30 | desc "Release Sifttter Redux version #{ version }"
31 | task :release => :build do
32 | unless `git branch` =~ /^\* master$/
33 | puts "You must be on the master branch to release!"
34 | exit!
35 | end
36 |
37 | sh "git commit --allow-empty -a -m 'Release #{ version }'"
38 | sh "git tag v#{ version }"
39 | sh "git push origin master"
40 | sh "git push origin v#{ version }"
41 | sh "gem push pkg/sifttter-redux-#{ version }.gem"
42 | end
43 |
44 | desc "Build the gem"
45 | task :build do
46 | FileUtils.mkdir_p "pkg"
47 | sh "gem build sifttter-redux.gemspec"
48 | FileUtils.mv("./sifttter-redux-#{ version }.gem", "pkg")
49 | end
50 |
51 | task :default => [:test, :features]
52 |
--------------------------------------------------------------------------------
/sifttter-redux.gemspec:
--------------------------------------------------------------------------------
1 | # coding: utf-8
2 | lib = File.expand_path('../lib', __FILE__)
3 | $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4 | require 'sifttter-redux/constants'
5 |
6 | Gem::Specification.new do |spec|
7 | spec.name = 'sifttter-redux'
8 | spec.version = SifttterRedux::VERSION
9 | spec.authors = ['Aaron Bach']
10 | spec.email = ['bachya1208@googlemail.com']
11 | spec.summary = SifttterRedux::SUMMARY
12 | spec.description = SifttterRedux::DESCRIPTION
13 | spec.homepage = 'https://github.com/bachya/sifttter-redux'
14 | spec.license = 'MIT'
15 | spec.platform = Gem::Platform::RUBY
16 |
17 | spec.require_paths = ["lib"]
18 | spec.files = `git ls-files`.split("\n")
19 | spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
20 | spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
21 |
22 | spec.license = 'MIT'
23 | spec.rdoc_options = ['--charset=UTF-8']
24 | spec.extra_rdoc_files = %w[README.md HISTORY.md LICENSE]
25 |
26 | spec.add_development_dependency('rake', '10.1.1')
27 | spec.add_development_dependency('rdoc', '4.1.1')
28 | spec.add_development_dependency('aruba', '0.5.4')
29 | spec.add_runtime_dependency('archive-zip', '0.6.0')
30 | spec.add_runtime_dependency('chronic', '0.10.2')
31 | spec.add_runtime_dependency('cliutils', '~> 2')
32 | spec.add_runtime_dependency('gli','2.9.0')
33 | spec.add_runtime_dependency('htmlentities','4.3.1')
34 | end
35 |
--------------------------------------------------------------------------------
/tmp/srd/.sifttter_redux_log:
--------------------------------------------------------------------------------
1 | # Logfile created on 2014-03-22 08:12:43 -0600 by logger.rb/44203
2 | D, [2014-03-22T08:12:43.563366 #13209] DEBUG -- : CONFIGURING DROPBOX UPLOADER...
3 | D, [2014-03-22T08:12:43.563826 #13209] DEBUG -- : Answer to "Location for Dropbox-Uploader": /usr/local/opt
4 | W, [2014-03-22T08:12:43.563882 #13209] WARN -- : Using pre-existing Dropbox Uploader at /usr/local/opt/Dropbox-Uploader...
5 | D, [2014-03-22T08:12:43.563920 #13209] DEBUG -- : COLLECTING PREFERENCES...
6 | D, [2014-03-22T08:12:43.564297 #13209] DEBUG -- : Answer to "Temporary path to download Sifttter files to": ~/sifttter_download
7 | D, [2014-03-22T08:12:43.564661 #13209] DEBUG -- : Answer to "Path to Sifttter files in Dropbox": /Apps/ifttt/Sifttter
8 | D, [2014-03-22T08:12:43.564995 #13209] DEBUG -- : Answer to "Temporary path to download Day One files to": ~/day_one_download
9 | D, [2014-03-22T08:12:43.565542 #13209] DEBUG -- : Answer to "Path to Day One files in Dropbox": /Apps/Day\ One/Journal.dayone/entries
10 | D, [2014-03-22T08:12:43.565605 #13209] DEBUG -- : Configuration values: {:sifttter_redux=>{:config_location=>"/Users/abach/Git/sifttter-redux/features/support/../../tmp/srd/.sifttter_redux", :log_level=>"WARN", :version=>"0.5.4", :sifttter_local_filepath=>"/Users/abach/Git/sifttter-redux/features/support/../../tmp/srd/sifttter_download", :sifttter_remote_filepath=>"/Apps/ifttt/Sifttter", :dayone_local_filepath=>"/Users/abach/Git/sifttter-redux/features/support/../../tmp/srd/day_one_download", :dayone_remote_filepath=>"/Apps/Day\\ One/Journal.dayone/entries"}, :db_uploader=>{:base_filepath=>"/usr/local/opt", :dbu_filepath=>"/usr/local/opt/Dropbox-Uploader", :exe_filepath=>"/usr/local/opt/Dropbox-Uploader/dropbox_uploader.sh"}}
11 |
--------------------------------------------------------------------------------
/lib/sifttter-redux/dropbox-uploader.rb:
--------------------------------------------------------------------------------
1 | module SifttterRedux
2 | # DropboxUploader Class
3 | # Wrapper class for the Dropbox Uploader project
4 | class DropboxUploader
5 | # Stores the local filepath.
6 | # @return [String]
7 | attr_accessor :local_target
8 |
9 | # Stores the remote filepath.
10 | # @return [String]
11 | attr_accessor :remote_target
12 |
13 | # Stores the message to display.
14 | # @return [String]
15 | attr_accessor :message
16 |
17 | # Stores the verbosity level.
18 | # @return [Boolean]
19 | attr_accessor :verbose
20 |
21 | # Loads the location of dropbox_uploader.sh.
22 | # @param [String] dbu_path The local filepath to the script
23 | # @param [Logger] A Logger to use
24 | # @return [void]
25 | def initialize(dbu_path, logger = nil)
26 | @dbu = dbu_path
27 | @logger = logger
28 | end
29 |
30 | # Downloads files from Dropbox (assumes that both
31 | # local_target and remote_target have been set).
32 | # @return [void]
33 | def download
34 | if !@local_target.nil? && !@remote_target.nil?
35 | if @verbose
36 | system "#{ @dbu } download #{ @remote_target } #{ @local_target }"
37 | else
38 | exec = `#{ @dbu } download #{ @remote_target } #{ @local_target }`
39 | end
40 | else
41 | error_msg = 'Local and remote targets cannot be nil'
42 | @logger.error(error_msg) if @logger
43 | fail StandardError, error_msg
44 | end
45 | end
46 |
47 | # Uploads files tro Dropbox (assumes that both
48 | # local_target and remote_target have been set).
49 | # @return [void]
50 | def upload
51 | if !@local_target.nil? && !@remote_target.nil?
52 | if @verbose
53 | system "#{ @dbu } upload #{ @local_target } #{ @remote_target }"
54 | else
55 | exec = `#{ @dbu } upload #{ @local_target } #{ @remote_target }`
56 | end
57 | else
58 | error_msg = 'Local and remote targets cannot be nil'
59 | @logger.error(error_msg) if @logger
60 | fail StandardError, error_msg
61 | end
62 | end
63 | end
64 | end
--------------------------------------------------------------------------------
/test/date_range_maker_test.rb:
--------------------------------------------------------------------------------
1 | require 'date'
2 | require 'test_helper'
3 | require File.join(File.dirname(__FILE__), '..', 'lib/sifttter-redux/date-range-maker.rb')
4 |
5 | class DateRangeMakerTest < Test::Unit::TestCase
6 | def test_today
7 | assert_equal(SifttterRedux::DateRangeMaker.today, (Date.today..Date.today))
8 | end
9 |
10 | def test_yesterday
11 | assert_equal(SifttterRedux::DateRangeMaker.yesterday, (Date.today - 1..Date.today - 1))
12 | end
13 |
14 | def test_last_5_days
15 | assert_equal(SifttterRedux::DateRangeMaker.last_n_days(5), (Date.today - 5...Date.today))
16 | end
17 |
18 | def test_last_5_days_include_today
19 | assert_equal(SifttterRedux::DateRangeMaker.last_n_days(5, true), (Date.today - 5..Date.today))
20 | end
21 |
22 | def test_last_12_days
23 | assert_equal(SifttterRedux::DateRangeMaker.last_n_days(12), (Date.today - 12...Date.today))
24 | end
25 |
26 | def test_last_12_days_include_today
27 | assert_equal(SifttterRedux::DateRangeMaker.last_n_days(12, true), (Date.today - 12..Date.today))
28 | end
29 |
30 | def test_current_week
31 | end_date = Date.today - Date.today.wday + 7
32 | if end_date > Date.today
33 | end_date = Date.today
34 | end
35 |
36 | assert_equal(SifttterRedux::DateRangeMaker.last_n_weeks, (Date.today - Date.today.wday + 1...end_date))
37 | end
38 |
39 | def test_current_week_include_today
40 | end_date = Date.today - Date.today.wday + 7
41 | if end_date > Date.today
42 | end_date = Date.today
43 | end
44 |
45 | assert_equal(SifttterRedux::DateRangeMaker.last_n_weeks(0, true), (Date.today - Date.today.wday + 1..end_date))
46 | end
47 |
48 | def test_last_2_weeks
49 | end_date = Date.today - Date.today.wday + 7
50 | if end_date > Date.today
51 | end_date = Date.today
52 | end
53 |
54 | assert_equal(SifttterRedux::DateRangeMaker.last_n_weeks(2), (Date.today - Date.today.wday - 13...end_date))
55 | end
56 |
57 | def test_last_2_weeks_include_today
58 | end_date = Date.today - Date.today.wday + 7
59 | if end_date > Date.today
60 | end_date = Date.today
61 | end
62 |
63 | assert_equal(SifttterRedux::DateRangeMaker.last_n_weeks(2, true), (Date.today - Date.today.wday - 13..end_date))
64 | end
65 |
66 | def test_range_only_start_date
67 | assert_equal(SifttterRedux::DateRangeMaker.range("2014-02-01", nil), (Date.parse("2014-02-01")...Date.today))
68 | end
69 |
70 | def test_range_only_start_date_include_today
71 | assert_equal(SifttterRedux::DateRangeMaker.range("2014-02-01", nil, true), (Date.parse("2014-02-01")..Date.today))
72 | end
73 |
74 | def test_range_start_date_and_end_date
75 | assert_equal(SifttterRedux::DateRangeMaker.range("2014-02-01", "2014-02-05"), (Date.parse("2014-02-01")..Date.parse("2014-02-05")))
76 | end
77 |
78 | def test_range_bad_dates
79 | assert_raise ArgumentError do
80 | SifttterRedux::DateRangeMaker.range("Bad Start Date", "Bad End Date")
81 | end
82 | end
83 |
84 | def test_range_end_date_with_no_start_date
85 | assert_raise ArgumentError do
86 | SifttterRedux::DateRangeMaker.range(nil, Date.today)
87 | end
88 | end
89 |
90 | def test_range_end_date_before_start_date
91 | assert_raise ArgumentError do
92 | SifttterRedux::DateRangeMaker.range(Date.today, Date.today - 1)
93 | end
94 | end
95 |
96 | def test_range_negative_look_back
97 | assert_raise ArgumentError do
98 | SifttterRedux::DateRangeMaker.last_n_days(-5)
99 | end
100 | end
101 | end
102 |
--------------------------------------------------------------------------------
/lib/sifttter-redux/date-range-maker.rb:
--------------------------------------------------------------------------------
1 | require 'chronic'
2 |
3 | module SifttterRedux
4 | # DateRangeMaker Module
5 | # Returns a Range of dates based on supplied parameters
6 | module DateRangeMaker
7 | # Returns a date range for the last N days (including
8 | # today's date if specified).
9 | # @param [Integer} num_days The number of days to look back
10 | # @param [Boolean] include_today Should today be included?
11 | # @return [Range]
12 | def self.last_n_days(num_days, include_today = false)
13 | if num_days < 0
14 | error = 'Cannot specify a negative number of days'
15 | fail ArgumentError, error
16 | end
17 |
18 | if include_today
19 | (Date.today - num_days..Date.today)
20 | else
21 | (Date.today - num_days...Date.today)
22 | end
23 | end
24 |
25 | # Returns a date range for the last N weeks (including
26 | # today's date if specified).
27 | # @param [Integer] num_days The number of weeks to look back
28 | # @param [Boolean] include_today Should today be included?
29 | # @return [Range]
30 | def self.last_n_weeks(num_weeks = 0, include_today = false)
31 | if num_weeks < 0
32 | error = 'Cannot specify a negative number of weeks'
33 | fail ArgumentError, error
34 | end
35 |
36 | beginning_date = Date.today - Date.today.wday + 1
37 | end_date = Date.today - Date.today.wday + 7
38 |
39 | # We coerce the end date to be today if a date
40 | # greater than today has been specified.
41 | end_date = Date.today if end_date > Date.today
42 |
43 | if include_today
44 | (beginning_date - num_weeks * 7..end_date)
45 | else
46 | (beginning_date - num_weeks * 7...end_date)
47 | end
48 | end
49 |
50 | # Returns a date range for specified start dates and
51 | # end dates. Note that specifying an end date greater
52 | # than today's date will force today to be the end date.
53 | # @param [Start] start_date The start date
54 | # @param [Date] end_date The end date
55 | # @param [Hash] options Miscellaneous options
56 | # @return [Range]
57 | def self.range(start_date, end_date, include_today = false)
58 | if start_date.nil? && !end_date.nil?
59 | error = "You can't specify -t without specifying -f"
60 | fail ArgumentError, error
61 | end
62 |
63 | begin
64 | chronic_start_date = Chronic.parse(start_date).to_date
65 | rescue
66 | unless start_date.nil?
67 | error = "Invalid date provided to Chronic: #{ start_date }"
68 | fail ArgumentError, error
69 | end
70 | nil
71 | end
72 |
73 | begin
74 | chronic_end_date = Chronic.parse(end_date).to_date
75 | rescue
76 | unless end_date.nil?
77 | error = "Invalid date provided to Chronic: #{ end_date }"
78 | fail ArgumentError, error
79 | end
80 | nil
81 | end
82 |
83 | if chronic_end_date && chronic_start_date > chronic_end_date
84 | error = 'The start date must be before or equal to the end date'
85 | fail ArgumentError, error
86 | end
87 |
88 | unless chronic_start_date.nil?
89 | if chronic_end_date.nil?
90 | if include_today
91 | (chronic_start_date..Date.today)
92 | else
93 | (chronic_start_date...Date.today)
94 | end
95 | else
96 | (chronic_start_date..chronic_end_date)
97 | end
98 | end
99 | end
100 |
101 | # Returns a date range for today
102 | # @return [Range]
103 | def self.today
104 | (Date.today..Date.today)
105 | end
106 |
107 | # Returns a date range for yesterday
108 | # @return [Range]
109 | def self.yesterday
110 | (Date.today - 1..Date.today - 1)
111 | end
112 | end
113 | end
114 |
--------------------------------------------------------------------------------
/lib/sifttter-redux/sifttter.rb:
--------------------------------------------------------------------------------
1 | require 'htmlentities'
2 |
3 | module SifttterRedux
4 | # Sifttter Module
5 | # Used to examine Sifttter data and create
6 | # Day One entries as necessary.
7 | module Sifttter
8 | extend self
9 |
10 | class << self
11 | # Stores the collection of entries to create.
12 | # @return [Hash]
13 | attr_accessor :entries
14 | end
15 |
16 | # Generates an ERB template for a Day One entry
17 | # @param [String] datestamp The ISO8601 datestamp
18 | # @param [String] entrytext The text of the entry
19 | # @param [Boolean] starred Whether the entry should be starred
20 | # @param [String] uuid The UUID of the entry
21 | def generate_template(datestamp, entrytext, starred, uuid)
22 | ERB.new <<-XMLTEMPLATE
23 |
24 |
25 |
26 |
27 | Creation Date
28 | <%= datestamp %>
29 | Entry Text
30 | <%= entrytext %>
31 | Starred
32 | <<%= starred %>/>
33 | Tags
34 |
35 | daily logs
36 |
37 | UUID
38 | <%= uuid %>
39 |
40 |
41 | XMLTEMPLATE
42 | end
43 |
44 | # Opens a filepath and parses it for Sifttter
45 | # data for the passed date.
46 | # @param [String] file The filepath to parse
47 | # @param [Date] date The date to search for
48 | # @return [void]
49 | def parse_sifttter_file(filepath, date)
50 | title = File.basename(filepath).gsub(/^.*?\/([^\/]+)$/, "\\1") + "\n"
51 |
52 | date_regex = /(?:#{ date.strftime("%B") } 0?#{ date.strftime("%-d") }, #{ date.strftime("%Y") })/
53 | time_regex = /(?:\d{1,2}:\d{1,2}\s?[AaPpMm]{2})/
54 | entry_regex = /@begin\n@date\s#{ date_regex }(?: at (#{ time_regex }?)\n)?(.*?)\n@end/m
55 |
56 | contents = File.read(filepath)
57 | cur_entries = contents.scan(entry_regex)
58 | unless cur_entries.empty?
59 | @entries.merge!(title => []) unless @entries.key?(title)
60 | cur_entries.each { |e| @entries[title] << [e[0], e[1].strip] }
61 | end
62 | end
63 |
64 | # Finds Siftter data for the passed date and
65 | # creates corresponding Day One entries.
66 | # @param [Date] date The date to search for
67 | # @return [void]
68 | def self.run(date)
69 | @entries = {}
70 | uuid = SecureRandom.uuid.upcase.gsub(/-/, '').strip
71 | date_for_title = date.strftime('%B %d, %Y')
72 | datestamp = date.to_time.utc.iso8601
73 | starred = false
74 |
75 | output_dir = configuration.sifttter_redux[:dayone_local_filepath]
76 | Dir.mkdir(output_dir) unless Dir.exists?(output_dir)
77 |
78 | files = `find #{ configuration.sifttter_redux[:sifttter_local_filepath] } -type f -name "*.txt" | grep -v -i daily | sort`
79 | if files.empty?
80 | messenger.error('No Sifttter files to parse...')
81 | messenger.error('Is Dropbox Uploader configured correctly?')
82 | messenger.error("Is #{ configuration.sifttter_redux[:sifttter_remote_filepath] } the correct remote filepath?")
83 | exit!(1)
84 | end
85 |
86 | files.split("\n").each do |file|
87 | file.strip!
88 | if File.exists?(file)
89 | parse_sifttter_file(file, date)
90 | end
91 | end
92 |
93 | if @entries.length > 0
94 |
95 | entrytext = "# Things done on #{ date_for_title }\n"
96 | @entries.each do |key, value|
97 | coder = HTMLEntities.new
98 | entrytext += '### ' + key.gsub(/.txt/, '').gsub(/_/, ' ').upcase + "\n\n"
99 | value.each { |v| entrytext += "#{ coder.encode(v[1].gsub(/%time%/, v[0])) }\n" }
100 | entrytext += "\n"
101 | end
102 |
103 | template = generate_template(datestamp, entrytext, starred, uuid)
104 | fh = File.new(File.expand_path("#{ output_dir }/#{ uuid }.doentry"), 'w+')
105 | fh.puts template.result(binding)
106 | fh.close
107 | messenger.success("Entry logged for #{ date_for_title }...")
108 | else
109 | messenger.warn("No entries found for #{ date_for_title }...")
110 | end
111 | end
112 | end
113 | end
114 |
--------------------------------------------------------------------------------
/features/2.initialization.feature:
--------------------------------------------------------------------------------
1 | Feature: Initialization
2 | As a user, when I initialize Sifttter Redux,
3 | I should be guided through the process as
4 | necessary.
5 |
6 | Scenario: Basic Initialization
7 | Given no file located at "/tmp/srd/.sifttter_redux"
8 | And an empty file located at "/tmp/srd/.dropbox_uploader"
9 | When I run `srd init` interactively
10 | And I type ""
11 | And I type "/tmp/srd/sifttter_download"
12 | And I type "/Apps/ifttt/Sifttter"
13 | And I type "/tmp/srd/day_one_download"
14 | And I type "/Apps/Day\ One/Journal.dayone/entries"
15 | Then the exit status should be 0
16 | And the file "/tmp/srd/.sifttter_redux" should contain:
17 | """
18 | ---
19 | sifttter_redux:
20 | config_location: "/tmp/srd/.sifttter_redux"
21 | log_level: WARN
22 | """
23 | And the file "/tmp/srd/.sifttter_redux" should contain:
24 | """
25 | sifttter_local_filepath: "/tmp/srd/sifttter_download"
26 | sifttter_remote_filepath: "/Apps/ifttt/Sifttter"
27 | dayone_local_filepath: "/tmp/srd/day_one_download"
28 | dayone_remote_filepath: "/Apps/Day\\ One/Journal.dayone/entries"
29 | db_uploader:
30 | base_filepath: "/usr/local/opt"
31 | dbu_filepath: "/usr/local/opt/Dropbox-Uploader"
32 | exe_filepath: "/usr/local/opt/Dropbox-Uploader/dropbox_uploader.sh"
33 | """
34 |
35 | Scenario: Reinitialization (refuse)
36 | Given a file located at "/tmp/srd/.sifttter_redux" with the contents:
37 | """
38 | ---
39 | sifttter_redux:
40 | config_location: "/tmp/srd/.sifttter_redux"
41 | log_level: WARN
42 | version: 10.0
43 | sifttter_local_filepath: "/tmp/srd/sifttter_download"
44 | sifttter_remote_filepath: "/Apps/ifttt/Sifttter"
45 | dayone_local_filepath: "/tmp/srd/day_one_download"
46 | dayone_remote_filepath: "/Apps/Day\\ One/Journal.dayone/entries"
47 | db_uploader:
48 | base_filepath: "/usr/local/opt"
49 | dbu_filepath: "/usr/local/opt/Dropbox-Uploader"
50 | exe_filepath: "/usr/local/opt/Dropbox-Uploader/dropbox_uploader.sh"
51 | """
52 | And an empty file located at "/tmp/srd/.dropbox_uploader"
53 | When I run `srd init` interactively
54 | And I type ""
55 | Then the exit status should be 0
56 |
57 | Scenario: Reinitialization (accept)
58 | Given a file located at "/tmp/srd/.sifttter_redux" with the contents:
59 | """
60 | ---
61 | sifttter_redux:
62 | config_location: "/tmp/srd/.sifttter_redux"
63 | log_level: WARN
64 | version: 10.0
65 | sifttter_local_filepath: "/tmp/srd/sifttter_download"
66 | sifttter_remote_filepath: "/Apps/ifttt/Sifttter"
67 | dayone_local_filepath: "/tmp/srd/day_one_download"
68 | dayone_remote_filepath: "/Apps/Day\\ One/Journal.dayone/entries"
69 | db_uploader:
70 | base_filepath: "/usr/local/opt"
71 | dbu_filepath: "/usr/local/opt/Dropbox-Uploader"
72 | exe_filepath: "/usr/local/opt/Dropbox-Uploader/dropbox_uploader.sh"
73 | """
74 | And an empty file located at "/tmp/srd/.dropbox_uploader"
75 | When I run `srd init` interactively
76 | And I type "y"
77 | And I type ""
78 | And I type "/tmp/srd/sifttter_download2"
79 | And I type "/Apps/ifttt/Sifttter2"
80 | And I type "/tmp/srd/day_one_download2"
81 | And I type "/Apps/Day\ One/Journal.dayone/entries2"
82 | Then the exit status should be 0
83 | And the file "/tmp/srd/.sifttter_redux" should contain:
84 | """
85 | ---
86 | sifttter_redux:
87 | config_location: "/tmp/srd/.sifttter_redux"
88 | log_level: WARN
89 | """
90 | And the file "/tmp/srd/.sifttter_redux" should contain:
91 | """
92 | sifttter_local_filepath: "/tmp/srd/sifttter_download2"
93 | sifttter_remote_filepath: "/Apps/ifttt/Sifttter2"
94 | dayone_local_filepath: "/tmp/srd/day_one_download2"
95 | dayone_remote_filepath: "/Apps/Day\\ One/Journal.dayone/entries2"
96 | db_uploader:
97 | base_filepath: "/usr/local/opt"
98 | dbu_filepath: "/usr/local/opt/Dropbox-Uploader"
99 | exe_filepath: "/usr/local/opt/Dropbox-Uploader/dropbox_uploader.sh"
100 | """
101 |
102 | Scenario: Reinitialization (from scratch)
103 | Given no file located at "/tmp/srd/.sifttter_redux"
104 | And an empty file located at "/tmp/srd/.dropbox_uploader"
105 | When I run `srd init -s` interactively
106 | And I type ""
107 | And I type "/tmp/srd/sifttter_download"
108 | And I type "/Apps/ifttt/Sifttter"
109 | And I type "/tmp/srd/day_one_download"
110 | And I type "/Apps/Day\ One/Journal.dayone/entries"
111 | Then the exit status should be 0
112 | And the file "/tmp/srd/.sifttter_redux" should contain:
113 | """
114 | ---
115 | sifttter_redux:
116 | config_location: "/tmp/srd/.sifttter_redux"
117 | log_level: WARN
118 | """
119 | And the file "/tmp/srd/.sifttter_redux" should contain:
120 | """
121 | sifttter_local_filepath: "/tmp/srd/sifttter_download"
122 | sifttter_remote_filepath: "/Apps/ifttt/Sifttter"
123 | dayone_local_filepath: "/tmp/srd/day_one_download"
124 | dayone_remote_filepath: "/Apps/Day\\ One/Journal.dayone/entries"
125 | db_uploader:
126 | base_filepath: "/usr/local/opt"
127 | dbu_filepath: "/usr/local/opt/Dropbox-Uploader"
128 | exe_filepath: "/usr/local/opt/Dropbox-Uploader/dropbox_uploader.sh"
129 | """
130 |
--------------------------------------------------------------------------------
/HISTORY.md:
--------------------------------------------------------------------------------
1 | # 1.0.5 (2014-05-19)
2 |
3 | * Small addition to show date of unfound entries
4 |
5 | # 1.0.4 (2014-05-06)
6 |
7 | * Fixed a bug where date range without and end date would incorrectly include today's date
8 |
9 | # 1.0.3 (2014-05-05)
10 |
11 | * Fixed a bug in which HTML entities from IFTTT could cause srd to fail
12 | * Bumped CLIUtils version to 2.2.3
13 |
14 | # 1.0.2 (2014-04-22)
15 |
16 | * Added `-d` flag to catch up a specific date
17 | * Added an error message for instances where Dropbox Uploader might be misconfigured
18 | * Small bugfixes
19 |
20 | # 1.0.1 (2014-04-22)
21 |
22 | * Fixed a bug in which entry titles were not being cased properly
23 |
24 | # 1.0.0 (2014-04-21)
25 |
26 | * Added new Sifttter file format (which allows for any Markdown)
27 | * Added `srd upgrade` to upgrade to new format
28 | * Lots of bugfixes
29 |
30 | # 0.6.4 (2014-04-13)
31 |
32 | * Now using Configurator's `compare_version`
33 |
34 | # 0.6.3 (2014-04-12)
35 |
36 | * Updated to CLIUtils 1.3.1
37 | * Fixed namespacing error
38 | * Fixed a bug in preference prompts
39 |
40 | # 0.6.2 (2014-04-03)
41 |
42 | * Updated to CLIUtils 1.2.1
43 |
44 | # 0.6.1 (2014-04-02)
45 |
46 | * Fixed Aruba tests
47 |
48 | # 0.6.0 (2014-04-01)
49 |
50 | * Migrated to CLIUtils
51 |
52 | # 0.5.4 (2014-03-19)
53 |
54 | * Fixed several bugs related to configuration management
55 |
56 | # 0.5.3 (2014-03-18)
57 |
58 | * Fixed regression with gemspec
59 |
60 | # 0.5.2 (2014-03-18)
61 |
62 | * New Configuration management system
63 |
64 | # 0.5.1 (2014-03-18)
65 |
66 | * Fixed a bug regarding missing Methadone references
67 |
68 | # 0.5.0 (2014-03-16)
69 |
70 | * Fixed a bug where Dropbox Uploader would fail when not in "verbose mode"
71 |
72 | # 0.4.9 (2014-03-15)
73 |
74 | * Fixed a bug with importing Logger into CLIMessage
75 |
76 | # 0.4.8 (2014-03-15)
77 |
78 | * Fixed a bug in which Sifttter Redux would ignore log level specified in config file
79 | * Made all prompt entry readline-based (for easier completion options)
80 |
81 | # 0.4.7 (2014-03-14)
82 |
83 | * Reworked logging to not require Methadone
84 | * Logging more verbose and configurable in ~/.sifttter_redux
85 | * Dropbox Uploader updates
86 | * Added support for path completion when prompting user to enter a filepath
87 | * Cleaned up error handling to be displayed to user at single point
88 |
89 | # 0.4.6 (2014-03-13)
90 |
91 | * Added new error messaaging if Sifttter remote path is invalid
92 | * Removed dependencies on exernal UUID library
93 | * Removed OS module (not needed anymore)
94 |
95 | # 0.4.5 (2014-03-01)
96 |
97 | * Added Methadone logging for prompts
98 |
99 | # 0.4.4 (2014-02-28)
100 |
101 | * Fixed a prompt error when providing Dropbox-Uploader with a bad path
102 |
103 | # 0.4.3 (2014-02-26)
104 |
105 | * Fixed regression with Dropbox-Uploader
106 |
107 | # 0.4.2 (2014-02-26)
108 |
109 | * Fixed regression with Dropbox-Uploader
110 |
111 | # 0.4.1 (2014-02-26)
112 |
113 | * Added `-s` flag to `init` command for initialization from scratch
114 | * Added gem version to config file (for reference going forward)
115 | * Added message to prompt users to re-init on upgrade
116 |
117 | # 0.4.0 (2014-02-26)
118 |
119 | * Removed some hardcoded values
120 |
121 | # 0.3.9 (2014-02-25)
122 |
123 | * Smarter checking for initialization before execution
124 | * Fixed a bug in which the config file wouldn't be properly written to
125 |
126 | # 0.3.8 (2014-02-25)
127 |
128 | * Upgraded to Methadone 1.3.2 in gemspec
129 | * Redirected all Methadone logging to file
130 | * Fixed a bug in which initailization would fail under certain circumstances
131 | * Fixed a bug in which Dropbox Uploader would fail to initialize properly
132 |
133 | # 0.3.7 (2014-02-25)
134 |
135 | * Fixed a bug in which Sifttter-Redux would fail on Ruby 2.0.0 (and potentially others)
136 |
137 | # 0.3.6 (2014-02-21)
138 |
139 | * Added logging via Methadone (key interactions logged to ~/.sifttter\_redux\_log)
140 |
141 | # 0.3.5 (2014-02-21)
142 |
143 | * Updated documentation and usage message
144 |
145 | # 0.3.4 (2014-02-21)
146 |
147 | * Automatically configure Dropbox Uploader during init (if needed)
148 | * Fixed several small bugs
149 | * Added more test cases
150 |
151 | # 0.3.3 (2014-02-20)
152 |
153 | * Fixed a bug in which the SifttterRedux module wouldn't load
154 |
155 | # 0.3.2 (2014-02-20)
156 |
157 | * Added verbose flag
158 | * Big refactorings = much nicer, more modular code
159 | * Removed dependency on colored gem
160 |
161 | # 0.3.1
162 |
163 | * Removed reliance on Rails methods for first-and-last-day-of-week calculations
164 | * Fixed a bug with the gemspec
165 |
166 | # 0.3.0
167 |
168 | * Added ability to create entries for the past N days (not just 7)
169 | * Added ability to create entries for the past N weeks
170 | * Refactorings of existing DateRangeMaker class
171 | * Additional documentation
172 | * Fixed a bug with using Chronic's language parsing using `-f`
173 |
174 | # 0.2.5
175 |
176 | * Fixed a bug where execution could prematurely halt if no Day One entries were found
177 | * Fixed a bug where re-initialization could continue, even if user declines
178 | * Updated some more help documentation
179 | * Changed messaging for initialization completion
180 |
181 | # 0.2.4 (originally 0.2.3)
182 |
183 | * Updated some help documentation
184 | * Changed message re: no entries found to a warning state
185 |
186 | # 0.2.2
187 |
188 | * Fixed a bug caused by caching of old configuration results
189 |
190 | # 0.2.1
191 |
192 | * Fixed a bug where the config manager would fail on certain platforms
193 | * Fixed a bug where the path to Dropbox Uploader became malformed
194 |
195 | # 0.2.0
196 |
197 | * Implemented catch-up mode
198 |
199 | # 0.1.0
200 |
201 | * Initial release of Sifttter Redux
202 |
--------------------------------------------------------------------------------
/lib/sifttter-redux.rb:
--------------------------------------------------------------------------------
1 | require 'sifttter-redux/constants'
2 | require 'sifttter-redux/date-range-maker'
3 | require 'sifttter-redux/dropbox-uploader'
4 | require 'sifttter-redux/sifttter'
5 |
6 | # The SifttterRedux module, which wraps everything
7 | # in this gem.
8 | module SifttterRedux
9 | class << self
10 | # Stores whether initalization has completed.
11 | # @return [Boolean]
12 | attr_reader :initialized
13 |
14 | # Stores whether verbose output is turned on.
15 | # @return [Boolean]
16 | attr_accessor :verbose
17 | end
18 |
19 | # Removes temporary directories and their contents
20 | # @return [void]
21 | def self.cleanup_temp_files
22 | dirs = [
23 | configuration.sifttter_redux[:dayone_local_filepath],
24 | configuration.sifttter_redux[:sifttter_local_filepath]
25 | ]
26 |
27 | messenger.info('Removing temporary local files...')
28 | dirs.each do |d|
29 | FileUtils.rm_rf(d)
30 | messenger.debug("Removed directory: #{ d }")
31 | end
32 | end
33 |
34 | # Runs a wizard that installs Dropbox Uploader on the
35 | # local filesystem.
36 | # @param [Boolean] from_scratch
37 | # @return [void]
38 | def self.dbu_install_wizard(from_scratch = false)
39 | valid_path_chosen = false
40 |
41 | until valid_path_chosen
42 | # Prompt the user for a location to save Dropbox Uploader.
43 | if from_scratch && !configuration.db_uploader[:base_filepath].nil?
44 | default = configuration.db_uploader[:base_filepath]
45 | else
46 | default = DEFAULT_DBU_LOCAL_FILEPATH
47 | end
48 | path = messenger.prompt('Location for Dropbox-Uploader', default)
49 | path = default if path.empty?
50 | path.chop! if path.end_with?('/')
51 |
52 | # If the entered directory exists, clone the repository.
53 | if Dir.exists?(File.expand_path(path))
54 | valid_path_chosen = true
55 |
56 | dbu_path = File.join(path, 'Dropbox-Uploader')
57 | executable_path = File.join(dbu_path, 'dropbox_uploader.sh')
58 |
59 | if File.directory?(dbu_path)
60 | messenger.warn("Using pre-existing Dropbox Uploader at #{ dbu_path }...")
61 | else
62 | messenger.info("Downloading Dropbox Uploader to #{ dbu_path }...")
63 | system "git clone https://github.com/andreafabrizi/Dropbox-Uploader.git #{ dbu_path }"
64 | messenger.info('Done.')
65 | end
66 |
67 | # If the user has never configured Dropbox Uploader, have them do it here.
68 | unless File.exists?(DEFAULT_DBU_CONFIG_FILEPATH)
69 | messenger.info('Initializing Dropbox Uploader...')
70 | system "#{ executable_path }"
71 | end
72 |
73 | configuration.add_section(:db_uploader) unless configuration.data.key?(:db_uploader)
74 | configuration.db_uploader.merge!({
75 | base_filepath: path,
76 | dbu_filepath: dbu_path,
77 | exe_filepath: executable_path
78 | })
79 | else
80 | messenger.error("Sorry, but #{ path } isn't a valid directory.")
81 | end
82 | end
83 | end
84 |
85 | # Creates a date range from the supplied command line
86 | # options.
87 | # @param [Hash] options GLI command line options
88 | # @return [Range]
89 | def self.get_dates_from_options(options)
90 | if options[:c] || options[:n] || options[:w] ||
91 | options[:y] || options[:f] || options[:t] ||
92 | options[:d]
93 | # Yesterday
94 | r = DateRangeMaker.yesterday if options[:y]
95 |
96 | # Specific date
97 | r = DateRangeMaker.range(options[:d], options[:d]) if options[:d]
98 |
99 | # Current Week
100 | r = DateRangeMaker.last_n_weeks(0, options[:i]) if options[:c]
101 |
102 | # Last N Days
103 | r = DateRangeMaker.last_n_days(options[:n].to_i, options[:i]) if options[:n]
104 |
105 | # Last N Weeks
106 | r = DateRangeMaker.last_n_weeks(options[:w].to_i, options[:i]) if options[:w]
107 |
108 | # Custom Range
109 | if (options[:f] || options[:t])
110 | _dates = DateRangeMaker.range(options[:f], options[:t], options[:i])
111 |
112 | if _dates.last > Date.today
113 | messenger.warn("Ignoring overextended end date and using today's date (#{ Date.today })...")
114 | r = (_dates.first..Date.today)
115 | else
116 | r = _dates
117 | end
118 | end
119 | else
120 | r = DateRangeMaker.today
121 | end
122 |
123 | messenger.debug("Date range: #{ r }")
124 | r
125 | end
126 |
127 | # Initializes Sifttter Redux by downloading and
128 | # collecting all necessary items and info.
129 | # @param [Boolean] from_scratch
130 | # @return [void]
131 | def self.init(from_scratch = false)
132 | messenger.section('INITIALIZING...')
133 |
134 | if from_scratch
135 | configuration.reset
136 | configuration.add_section(:sifttter_redux)
137 | end
138 |
139 | configuration.sifttter_redux.merge!({
140 | config_location: configuration.config_path,
141 | log_level: 'WARN',
142 | version: SifttterRedux::VERSION,
143 | })
144 |
145 | # Run the wizard to download Dropbox Uploader.
146 | dbu_install_wizard(from_scratch = from_scratch)
147 |
148 | pm = CLIUtils::Prefs.new(SifttterRedux::PREF_FILES['INIT'], configuration)
149 | pm.ask
150 | configuration.ingest_prefs(pm)
151 |
152 | messenger.debug("Collected configuration values: #{ configuration.data }")
153 | configuration.save
154 | @initialized = true
155 | end
156 |
157 | # Notifies the user that the config file needs to be
158 | # re-done and does it.
159 | # @return [void]
160 | def self.update_config_file
161 | m = "This version needs to make some config changes. Don't worry; " \
162 | "when prompted, your current values for existing config options " \
163 | "will be presented (so it'll be easier to fly through the upgrade)."
164 | messenger.info(m)
165 | messenger.prompt('Press enter to continue')
166 | SifttterRedux.init(true)
167 | end
168 | end
169 |
--------------------------------------------------------------------------------
/bin/srd:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | # Encoding: utf-8
3 | #--------------------------------------------------------------------
4 | # Sifttter Redux
5 | #
6 | # A modification of Craig Eley's Sifttter that allows for smart
7 | # installation on a standalone *NIX device (such as a Raspberry Pi).
8 | #
9 | # Sifttter copyright Craig Eley 2014
10 | #
11 | # Copyright (c) 2014
12 | # Aaron Bach
13 | #
14 | # Permission is hereby granted, free of charge, to any person
15 | # obtaining a copy of this software and associated documentation
16 | # files (the "Software"), to deal in the Software without
17 | # restriction, including without limitation the rights to use,
18 | # copy, modify, merge, publish, distribute, sublicense, and/or sell
19 | # copies of the Software, and to permit persons to whom the
20 | # Software is furnished to do so, subject to the following
21 | # conditions:
22 | #
23 | # The above copyright notice and this permission notice shall be
24 | # included in all copies or substantial portions of the Software.
25 | #
26 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
27 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
28 | # OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
29 | # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
30 | # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
31 | # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
32 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
33 | # OTHER DEALINGS IN THE SOFTWARE.
34 | #--------------------------------------------------------------------
35 | require 'archive/zip'
36 | require 'cliutils'
37 | require 'gli'
38 | require 'sifttter-redux'
39 | require 'securerandom'
40 |
41 | include CLIUtils::Configuration
42 | include CLIUtils::Messaging
43 | include GLI::App
44 |
45 | # ======================================================
46 | # App Info
47 | # ======================================================
48 | program_desc(SifttterRedux::DESCRIPTION)
49 | version(SifttterRedux::VERSION)
50 |
51 | # ======================================================
52 | # Global Flags and Switches
53 | # ======================================================
54 | switch([:verbose], desc: 'Turns on verbose output')
55 |
56 | # ======================================================
57 | # Pre, Post, and Error
58 | # ======================================================
59 | pre do |global, command, options, args|
60 | # Load SifttterRedux configuration module.
61 | load_configuration(SifttterRedux::DEFAULT_SRD_CONFIG_FILEPATH)
62 | file_logger = Logger.new(SifttterRedux::DEFAULT_SRD_LOG_FILEPATH)
63 | file_logger.level = LOG_LEVELS[configuration.sifttter_redux[:log_level] || 'DEBUG']
64 | messenger.attach(LOGFILE: file_logger)
65 |
66 | if File.exists?(SifttterRedux::DEFAULT_SRD_CONFIG_FILEPATH)
67 | # Set the current and last config versions in the Configurator.
68 | configuration.current_version = configuration.sifttter_redux[:version]
69 | configuration.last_version = SifttterRedux::NEWEST_CONFIG_VERSION
70 |
71 | # Compare the two versions and, if needed, update.
72 | configuration.compare_version do |c, l|
73 | messenger.debug("Upgrading from #{ c } to #{ l }")
74 | SifttterRedux.update_config_file
75 | exit!(0)
76 | end
77 | else
78 | # Force the user to init if they try to run any command other than `init` first.
79 | messenger.info('You need to initialize Sifttter Redux first!')
80 | SifttterRedux.init(true)
81 | exit!(0)
82 | end
83 | true
84 | end
85 |
86 | post do |global,command,options,args|
87 | # Post logic here
88 | # Use skips_post before a command to skip this
89 | # block on that command only
90 | end
91 |
92 | on_error do |exception|
93 | messenger.error(exception.to_s)
94 | exit!(1)
95 | true
96 | end
97 |
98 | # ======================================================
99 | # Commands
100 | # ======================================================
101 | # ------------------------------------------------------
102 | # exec command
103 | #
104 | # Executes the app.
105 | # ------------------------------------------------------
106 | desc 'Execute the app'
107 | command :exec do |c|
108 | c.flag([:d], desc: 'Run catch-up mode with a particular date')
109 | c.flag([:f], desc: 'Run catch-up mode with this start date')
110 | c.flag([:n], desc: 'Run catch-up mode for the last N days')
111 | c.flag([:t], desc: 'Run catch-up mode with this end date (must also have -f)')
112 | c.flag([:w], desc: 'Run catch-up mode for the last N weeks')
113 |
114 | c.switch([:c], desc: 'Run catch-up mode from the beginning of the week to yesterday')
115 | c.switch([:i], desc: "Include today's date in catch-up")
116 | c.switch([:verbose], desc: 'Turns on verbose output')
117 | c.switch([:y], desc: 'Run catch-up mode for yesterday')
118 |
119 | c.action do |global_options, options, args|
120 | SifttterRedux.verbose = global_options[:verbose] || options[:verbose]
121 |
122 | dates = SifttterRedux::get_dates_from_options(options)
123 | unless dates.nil?
124 | first_date = dates.first
125 | second_date = dates.reverse_each.first
126 |
127 | date_string = first_date.strftime('%B %d, %Y')
128 | date_string << " to #{ second_date.strftime('%B %d, %Y') }" if first_date != second_date
129 | messenger.info("Creating #{ first_date == second_date ? 'entry' : 'entries' }: #{ date_string }")
130 |
131 | # Download Sifttter files from Dropbox.
132 | dbu = SifttterRedux::DropboxUploader.new(configuration.db_uploader[:exe_filepath])
133 | dbu.verbose = SifttterRedux.verbose
134 | dbu.local_target = configuration.sifttter_redux[:sifttter_local_filepath]
135 | dbu.remote_target = configuration.sifttter_redux[:sifttter_remote_filepath]
136 | dbu.message = 'Downloading Sifttter files...'
137 |
138 | messenger.info(dbu.message || dbu::DEFAULT_MESSAGE)
139 | dbu.download
140 | messenger.info('Done.')
141 |
142 | # Process a new Sifttter entry for each date.
143 | dates.each do |date|
144 | SifttterRedux::Sifttter.run(date)
145 | end
146 |
147 | # Upload any Day One entries to Dropbox (if there are any).
148 | unless Dir[configuration.sifttter_redux[:dayone_local_filepath] + '/*'].empty?
149 | dbu.local_target = "#{ configuration.sifttter_redux[:dayone_local_filepath] }/*"
150 | dbu.remote_target = configuration.sifttter_redux[:dayone_remote_filepath]
151 | dbu.message = 'Uploading Day One entries to Dropbox...'
152 |
153 | messenger.info(dbu.message || dbu::DEFAULT_MESSAGE)
154 | dbu.upload
155 | messenger.info('Done.')
156 | end
157 |
158 | # Remove any downloaded local files that we no longer need.
159 | SifttterRedux.cleanup_temp_files
160 | end
161 | end
162 |
163 | end
164 |
165 | # ------------------------------------------------------
166 | # init command
167 | #
168 | # Initializes the app by asking the user for information
169 | # needed torun.
170 | # ------------------------------------------------------
171 | desc 'Install and initialize dependencies'
172 | command :init do |c|
173 | c.switch([:s], desc: 'Run init from scratch (i.e., clear out all values from configuration)')
174 | c.action do |global_options, options, args|
175 | if options[:s]
176 | SifttterRedux::init(true)
177 | else
178 | long_message = "You've already initialized Sifttter Redux. Do it again?"
179 | SifttterRedux::init if messenger.prompt(long_message, 'N').downcase == 'y'
180 | end
181 | end
182 | end
183 |
184 | # ------------------------------------------------------
185 | # upgrade command
186 | #
187 | # Upgrades existing Sifttter files to the format needed
188 | # by v 1.x.x.
189 | # ------------------------------------------------------
190 | desc 'Upgrades Sifttter files to the new format'
191 | command :upgrade do |c|
192 | c.switch([:verbose], desc: 'Turns on verbose output')
193 | c.action do |global_options, options, args|
194 | SifttterRedux.verbose = global_options[:verbose] || options[:verbose]
195 |
196 | # Set the archive filepath and the files that will go into it.
197 | filename = "#{ ENV['HOME'] }/sifttter_backup_#{ Time.now.to_i }.zip"
198 |
199 | # Download Sifttter files from Dropbox.
200 | dbu = SifttterRedux::DropboxUploader.new(configuration.db_uploader[:exe_filepath])
201 | dbu.verbose = SifttterRedux.verbose
202 | dbu.local_target = configuration.sifttter_redux[:sifttter_local_filepath]
203 | dbu.remote_target = configuration.sifttter_redux[:sifttter_remote_filepath]
204 | dbu.message = "Backing up Sifttter files to #{ filename }..."
205 |
206 | messenger.info(dbu.message || dbu::DEFAULT_MESSAGE)
207 | dbu.download
208 | messenger.info('Done.')
209 |
210 | # Archive the Sifttter files.
211 | Archive::Zip.archive(filename, configuration.sifttter_redux[:sifttter_local_filepath])
212 |
213 | # Replace the old scheme with the new one.
214 | Dir.glob(configuration.sifttter_redux[:sifttter_local_filepath] + '/*.txt').each do |file|
215 | t = File.read(file)
216 | t.gsub!(/^- /, "@begin\n@date ")
217 | t.gsub!(/ - /, "\n- ")
218 | t.gsub!(/\s?@done/, '@end')
219 | messenger.debug("Replacing contents of file: #{ file }")
220 | File.open(file, 'w') { |f| f.write(t) }
221 | end
222 |
223 | # Upload the new Sifttter files back to Dropbox.
224 | dbu.local_target = "#{ configuration.sifttter_redux[:sifttter_local_filepath] }"
225 | dbu.remote_target = Pathname.new(configuration.sifttter_redux[:sifttter_remote_filepath]).dirname.to_s
226 | dbu.message = "Uploading revised Sifttter files to Dropbox..."
227 |
228 | messenger.info(dbu.message || dbu::DEFAULT_MESSAGE)
229 | dbu.upload
230 | messenger.info('Done.')
231 |
232 | # Remove any downloaded local files that we no longer need.
233 | SifttterRedux.cleanup_temp_files
234 | end
235 | end
236 |
237 | # ======================================================
238 | # Run!
239 | # ======================================================
240 | exit run(ARGV)
241 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Sifttter Redux
2 | ==============
3 | [](https://travis-ci.org/bachya/Sifttter-Redux)
4 | [](http://badge.fury.io/rb/sifttter-redux)
5 |
6 | # Upgrading From 0.x.x to 1.0.0?
7 |
8 | Make sure you read the [IFTTT Template](#ifttt-template) section.
9 |
10 | # Intro
11 |
12 | Siftter Redux is a modification of Craig Eley's
13 | [Sifttter](http://craigeley.com/post/72565974459/sifttter-an-ifttt-to-day-one-logger "Sifttter"),
14 | a script to collect information from [IFTTT](http://www.ifttt.com "IFTTT") and
15 | place it in a [Day One](http://dayoneapp.com, "Day One") journal.
16 |
17 | Siftter Redux has several fundamental differences:
18 |
19 | * Interactive logging of today's events or events in the past
20 | * "Catch Up" mode for logging several days' events at once
21 | * Packaged as a command line app, complete with documentation and help
22 | * Easy installation on cron for automated running
23 |
24 | # Prerequisites
25 |
26 | In addition to Git (which, given you being on this site, I'll assume you have),
27 | Ruby (v. 1.9.3 or greater) is needed.
28 |
29 | # Installation
30 |
31 | ```
32 | gem install sifttter-redux
33 | ```
34 |
35 | # Usage
36 |
37 | Syntax and usage can be accessed by running `srd help`:
38 |
39 | ```
40 | $ srd help
41 | NAME
42 | srd - Sifttter Redux
43 |
44 | A customized IFTTT-to-Day One service that allows for
45 | smart installation and automated running on a standalone
46 | *NIX device (such as a Raspberry Pi).
47 |
48 | SYNOPSIS
49 | srd [global options] command [command options] [arguments...]
50 |
51 | VERSION
52 | 1.0.6
53 |
54 | GLOBAL OPTIONS
55 | --help - Show this message
56 | --[no-]verbose - Turns on verbose output
57 | --version - Display the program version
58 |
59 | COMMANDS
60 | exec - Execute the script
61 | help - Shows a list of commands or help for one command
62 | init - Install and initialize dependencies
63 | ```
64 |
65 | Note that each command's options can be revealed by adding the `--help` switch
66 | after the command. For example:
67 |
68 | ```
69 | $ srd exec --help
70 | NAME
71 | exec - Execute the script
72 |
73 | SYNOPSIS
74 | srd [global options] exec [command options]
75 |
76 | COMMAND OPTIONS
77 | -c - Run catch-up mode from the beginning of the week to yesterday
78 | -f arg - Run catch-up mode with this start date (default: none)
79 | -i - Include today's date in catch-up
80 | -n arg - Run catch-up mode for the last N days (default: none)
81 | -t arg - Run catch-up mode with this end date (must also have -f) (default: none)
82 | --[no-]verbose - Turns on verbose output
83 | -w arg - Run catch-up mode for the last N weeks (default: none)
84 | -y - Run catch-up mode for yesterday
85 | ```
86 |
87 | ## IFTTT Template
88 |
89 | Version 1.0.0+ uses a new schema that allows for any type of Markdown. Thus, Sifttter
90 | files from IFTTT need to follow this format:
91 |
92 | ```
93 | @begin
94 | @date April 21, 2014 at 12:34PM
95 | **Any** sort of *Markdown* goes here...
96 | @end
97 | ```
98 |
99 | Whereas the previous Sifttter Redux only allowed output of bulleted lists, this new
100 | template style allows you to include *any* Markdown, making output like tables possibe.
101 |
102 | ### Upgrade Command
103 |
104 | Note that a new command has been introduced that attempts to upgrade to this
105 | new format. **Although the command backs up your current Sifttter files, you
106 | are strongly encouraged to make a separate, manual backup.**
107 |
108 | ```Bash
109 | $ srd upgrade
110 | ```
111 |
112 | ### Template Tokens
113 |
114 | IFTTT templates can make use of the following tokens:
115 |
116 | * `%time%`: the time the entry was created
117 |
118 | As an example, to include the entry time in a template:
119 |
120 | ```
121 | @begin
122 | @date April 21, 2014 at 12:34PM
123 | - %time%: My text goes here...
124 | @end
125 | ```
126 |
127 | ## Initialization
128 |
129 | ```
130 | $ srd init
131 | ```
132 |
133 | Initialization will perform the following steps:
134 |
135 | 1. Download [Dropbox Uploader](https://github.com/andreafabrizi/Dropbox-Uploader "Dropbox-Uploder")
136 | to a location of your choice.
137 | 2. Automatically configure Dropbox Uploader.
138 | 3. Collect some user paths (note that you can use tab completion here!):
139 | * The location on your filesystem where Sifttter files will be temporarily stored
140 | * The location of your Sifttter files in Dropbox
141 | * The location on your filesystem where Day One files will be temporarily stored
142 | * The location of your Day One files in Dropbox
143 |
144 | ## Pathing
145 |
146 | Note that when Sifttter Redux asks you for paths, it will ask for "local" and
147 | "remote" filepaths. It's important to understand the difference.
148 |
149 | ### Local Filepaths
150 |
151 | Local filepaths are, as you'd expect, filepaths on your local machine. Some
152 | examples might be:
153 |
154 | * `/tmp/my_data`
155 | * `/home/bob/ifttt/sifttter_data`
156 | * `~/sifttter`
157 |
158 | ### Remote Filepaths
159 |
160 | Remote filepaths, on the other hand, are absolute filepaths in your Dropbox
161 | folder (*as Dropbox Uploader would see them*). For instance,
162 | `/home/bob/Dropbox/apps/sifttter` is *not* a valid remote filepath; rather,
163 | `/apps/sifttter` would be correct.
164 |
165 | ## Basic Execution
166 |
167 | ```
168 | $ srd exec
169 | #### EXECUTING...
170 | ---> INFO: Creating entry for February 15, 2014...
171 | ---> INFO: Downloading Sifttter files...DONE.
172 | ---> SUCCESS: Entry logged for February 15, 2014...
173 | ---> INFO: Uploading Day One entries to Dropbox...DONE.
174 | ---> INFO: Removing downloaded Day One files...DONE.
175 | ---> INFO: Removing downloaded Sifttter files...DONE.
176 | #### EXECUTION COMPLETE!
177 | ```
178 |
179 | ## "Catch-up" Mode
180 |
181 | Sometimes, events occur that prevent Sifttter Redux from running (power loss to
182 | your device, a bad Cron job, etc.). In this case, Sifttter Redux's "catch-up"
183 | mode can be used to collect any valid journal on or before today's date.
184 |
185 | There are many ways to use this mode (note that "today" in these examples is
186 | **February 15, 2014**):
187 |
188 | ### Yesterday Catch-up
189 |
190 | To create an entry for yesterday:
191 |
192 | ```
193 | $ srd exec -y
194 | #### EXECUTING...
195 | ---> INFO: Creating entry for February 14, 2014...
196 | ---> INFO: Downloading Sifttter files...DONE.
197 | ---> SUCCESS: Entry logged for February 14, 2014...
198 | ---> INFO: Uploading Day One entries to Dropbox...DONE.
199 | ---> INFO: Removing downloaded Day One files...DONE.
200 | ---> INFO: Removing downloaded Sifttter files...DONE.
201 | #### EXECUTION COMPLETE!
202 | ```
203 |
204 | ### Catch-up for a Specific Date
205 |
206 | To create an entry for specific date:
207 |
208 | ```
209 | $ srd exec -d 2014-02-14
210 | #### EXECUTING...
211 | ---> INFO: Creating entry for February 14, 2014...
212 | ---> INFO: Downloading Sifttter files...DONE.
213 | ---> SUCCESS: Entry logged for February 14, 2014...
214 | ---> INFO: Uploading Day One entries to Dropbox...DONE.
215 | ---> INFO: Removing downloaded Day One files...DONE.
216 | ---> INFO: Removing downloaded Sifttter files...DONE.
217 | #### EXECUTION COMPLETE!
218 | ```
219 |
220 | ### Last "N" Days Catch-up
221 |
222 | Sifttter Redux allows you to specify the number of days back it should look for
223 | new entries:
224 |
225 | ```
226 | $ srd exec -n 3
227 | #### EXECUTING...
228 | ---> INFO: Creating entries for dates from February 12, 2014 to February 14, 2014...
229 | ---> INFO: Downloading Sifttter files...DONE.
230 | ---> SUCCESS: Entry logged for February 12, 2014...
231 | ---> SUCCESS: Entry logged for February 13, 2014...
232 | ---> SUCCESS: Entry logged for February 14, 2014...
233 | ---> INFO: Uploading Day One entries to Dropbox...DONE.
234 | ---> INFO: Removing downloaded Day One files...DONE.
235 | ---> INFO: Removing downloaded Sifttter files...DONE.
236 | #### EXECUTION COMPLETE!
237 |
238 | $ srd exec -n 12
239 | #### EXECUTING...
240 | ---> INFO: Creating entries for dates from February 03, 2014 to February 14, 2014...
241 | ---> INFO: Downloading Sifttter files...DONE.
242 | ---> SUCCESS: February 03, 2014...
243 | ---> SUCCESS: February 04, 2014...
244 | ---> SUCCESS: February 05, 2014...
245 | ---> SUCCESS: February 06, 2014...
246 | ---> SUCCESS: February 07, 2014...
247 | ---> SUCCESS: February 08, 2014...
248 | ---> SUCCESS: February 09, 2014...
249 | ---> SUCCESS: February 10, 2014...
250 | ---> SUCCESS: February 11, 2014...
251 | ---> SUCCESS: February 12, 2014...
252 | ---> SUCCESS: February 13, 2014...
253 | ---> SUCCESS: February 14, 2014...
254 | ---> INFO: Uploading Day One entries to Dropbox...DONE.
255 | ---> INFO: Removing downloaded Day One files...DONE.
256 | ---> INFO: Removing downloaded Sifttter files...DONE.
257 | #### EXECUTION COMPLETE!
258 | ```
259 |
260 | Note that this option goes until yesterday ("yesterday" because you might not be
261 | ready to have today's entries scanned). If you'd rather include today's date, you
262 | can always add the `-i` switch:
263 |
264 | ```
265 | $ srd exec -i -n 3
266 | #### EXECUTING...
267 | ---> INFO: Creating entries for dates from February 12, 2014 to February 15, 2014...
268 | ---> INFO: Downloading Sifttter files...DONE.
269 | ---> SUCCESS: Entry logged for February 12, 2014...
270 | ---> SUCCESS: Entry logged for February 13, 2014...
271 | ---> SUCCESS: Entry logged for February 14, 2014...
272 | ---> SUCCESS: Entry logged for February 15, 2014...
273 | ---> INFO: Uploading Day One entries to Dropbox...DONE.
274 | ---> INFO: Removing downloaded Day One files...DONE.
275 | ---> INFO: Removing downloaded Sifttter files...DONE.
276 | #### EXECUTION COMPLETE!
277 | ```
278 |
279 | ### Last "N" Weeks Catch-up
280 |
281 | Sifttter Redux also allows you to specify a number of weeks back that should be
282 | scanned for new entries:
283 |
284 | ```
285 | $ srd exec -w 1
286 | #### EXECUTING...
287 | ---> INFO: Creating entries for dates from February 03, 2014 to February 14, 2014...
288 | ---> INFO: Downloading Sifttter files...DONE.
289 | ---> SUCCESS: Entry logged for February 03, 2014...
290 | ---> SUCCESS: Entry logged for February 04, 2014...
291 | ---> SUCCESS: Entry logged for February 05, 2014...
292 | ---> SUCCESS: Entry logged for February 06, 2014...
293 | ---> SUCCESS: Entry logged for February 07, 2014...
294 | ---> SUCCESS: Entry logged for February 08, 2014...
295 | ---> SUCCESS: Entry logged for February 09, 2014...
296 | ---> SUCCESS: Entry logged for February 10, 2014...
297 | ---> SUCCESS: Entry logged for February 11, 2014...
298 | ---> SUCCESS: Entry logged for February 12, 2014...
299 | ---> SUCCESS: Entry logged for February 13, 2014...
300 | ---> SUCCESS: Entry logged for February 14, 2014...
301 | ---> INFO: Uploading Day One entries to Dropbox...DONE.
302 | ---> INFO: Removing downloaded Day One files...DONE.
303 | ---> INFO: Removing downloaded Sifttter files...DONE.
304 | #### EXECUTION COMPLETE!
305 |
306 | $ srd exec -w 3
307 | #### EXECUTING...
308 | ---> INFO: Creating entries for dates from January 20, 2014 to February 14, 2014...
309 | ---> INFO: Downloading Sifttter files...DONE.
310 | ---> SUCCESS: Entry logged for January 20, 2014...
311 | ---> SUCCESS: Entry logged for January 21, 2014...
312 | ---> SUCCESS: Entry logged for January 22, 2014...
313 | ---> SUCCESS: Entry logged for January 23, 2014...
314 | ---> SUCCESS: Entry logged for January 24, 2014...
315 | ---> SUCCESS: Entry logged for January 25, 2014...
316 | ---> SUCCESS: Entry logged for January 26, 2014...
317 | ---> SUCCESS: Entry logged for January 27, 2014...
318 | ---> SUCCESS: Entry logged for January 28, 2014...
319 | ---> SUCCESS: Entry logged for January 29, 2014...
320 | ---> SUCCESS: Entry logged for January 30, 2014...
321 | ---> SUCCESS: Entry logged for January 31, 2014...
322 | ---> SUCCESS: Entry logged for February 01, 2014...
323 | ---> SUCCESS: Entry logged for February 02, 2014...
324 | ---> SUCCESS: Entry logged for February 03, 2014...
325 | ---> SUCCESS: Entry logged for February 04, 2014...
326 | ---> SUCCESS: Entry logged for February 05, 2014...
327 | ---> SUCCESS: Entry logged for February 06, 2014...
328 | ---> SUCCESS: Entry logged for February 07, 2014...
329 | ---> SUCCESS: Entry logged for February 08, 2014...
330 | ---> SUCCESS: Entry logged for February 09, 2014...
331 | ---> SUCCESS: Entry logged for February 10, 2014...
332 | ---> SUCCESS: Entry logged for February 11, 2014...
333 | ---> SUCCESS: Entry logged for February 12, 2014...
334 | ---> SUCCESS: Entry logged for February 13, 2014...
335 | ---> SUCCESS: Entry logged for February 14, 2014...
336 | ---> INFO: Uploading Day One entries to Dropbox...DONE.
337 | ---> INFO: Removing downloaded Day One files...DONE.
338 | ---> INFO: Removing downloaded Sifttter files...DONE.
339 | #### EXECUTION COMPLETE!
340 | ```
341 |
342 | As you'd expect, you can always add the `-i` switch:
343 |
344 | ```
345 | $ srd exec -i -w 1
346 | #### EXECUTING...
347 | ---> INFO: Creating entries for dates from February 03, 2014 to February 15, 2014...
348 | ---> INFO: Downloading Sifttter files...DONE.
349 | ---> SUCCESS: Entry logged for February 03, 2014...
350 | ---> SUCCESS: Entry logged for February 04, 2014...
351 | ---> SUCCESS: Entry logged for February 05, 2014...
352 | ---> SUCCESS: Entry logged for February 06, 2014...
353 | ---> SUCCESS: Entry logged for February 07, 2014...
354 | ---> SUCCESS: Entry logged for February 08, 2014...
355 | ---> SUCCESS: Entry logged for February 09, 2014...
356 | ---> SUCCESS: Entry logged for February 10, 2014...
357 | ---> SUCCESS: Entry logged for February 11, 2014...
358 | ---> SUCCESS: Entry logged for February 12, 2014...
359 | ---> SUCCESS: Entry logged for February 13, 2014...
360 | ---> SUCCESS: Entry logged for February 14, 2014...
361 | ---> SUCCESS: Entry logged for February 15, 2014...
362 | ---> INFO: Uploading Day One entries to Dropbox...DONE.
363 | ---> INFO: Removing downloaded Day One files...DONE.
364 | ---> INFO: Removing downloaded Sifttter files...DONE.
365 | #### EXECUTION COMPLETE!
366 | ```
367 |
368 | ### Date Range Catch-up
369 |
370 | To create entries for a range of dates:
371 |
372 | ```
373 | $ srd exec -f 2014-02-01 -t 2014-02-12
374 | #### EXECUTING...
375 | ---> INFO: Creating entries for dates from February 01, 2014 to February 12, 2014...
376 | ---> INFO: Downloading Sifttter files...DONE.
377 | ---> SUCCESS: Entry logged for February 01, 2014...
378 | ---> SUCCESS: Entry logged for February 02, 2014...
379 | ---> SUCCESS: Entry logged for February 03, 2014...
380 | ---> SUCCESS: Entry logged for February 04, 2014...
381 | ---> SUCCESS: Entry logged for February 05, 2014...
382 | ---> SUCCESS: Entry logged for February 06, 2014...
383 | ---> SUCCESS: Entry logged for February 07, 2014...
384 | ---> SUCCESS: Entry logged for February 08, 2014...
385 | ---> SUCCESS: Entry logged for February 09, 2014...
386 | ---> SUCCESS: Entry logged for February 10, 2014...
387 | ---> SUCCESS: Entry logged for February 11, 2014...
388 | ---> SUCCESS: Entry logged for February 12, 2014...
389 | ---> INFO: Uploading Day One entries to Dropbox...DONE.
390 | ---> INFO: Removing downloaded Day One files...DONE.
391 | ---> INFO: Removing downloaded Sifttter files...DONE.
392 | #### EXECUTION COMPLETE!
393 | ```
394 |
395 | Even more simply, to create entries from a specific point until yesterday
396 | ("yesterday" because you might not be ready to have today's entries scanned):
397 |
398 | ```
399 | $ srd exec -f 2014-02-01
400 | #### EXECUTING...
401 | ---> INFO: Creating entries for dates from February 01, 2014 to February 12, 2014...
402 | ---> INFO: Downloading Sifttter files...DONE.
403 | ---> SUCCESS: Entry logged for February 01, 2014...
404 | ---> SUCCESS: Entry logged for February 02, 2014...
405 | ---> SUCCESS: Entry logged for February 03, 2014...
406 | ---> SUCCESS: Entry logged for February 04, 2014...
407 | ---> SUCCESS: Entry logged for February 05, 2014...
408 | ---> SUCCESS: Entry logged for February 06, 2014...
409 | ---> SUCCESS: Entry logged for February 07, 2014...
410 | ---> SUCCESS: Entry logged for February 08, 2014...
411 | ---> SUCCESS: Entry logged for February 09, 2014...
412 | ---> SUCCESS: Entry logged for February 10, 2014...
413 | ---> SUCCESS: Entry logged for February 11, 2014...
414 | ---> SUCCESS: Entry logged for February 12, 2014...
415 | ---> INFO: Uploading Day One entries to Dropbox...DONE.
416 | ---> INFO: Removing downloaded Day One files...DONE.
417 | ---> INFO: Removing downloaded Sifttter files...DONE.
418 | #### EXECUTION COMPLETE!
419 | ```
420 |
421 | In this case, once more, you can use the trusty `-i` switch if you want:
422 |
423 | ```
424 | $ srd exec -i -f 2014-02-01
425 | #### EXECUTING...
426 | ---> INFO: Creating entries for dates from February 01, 2014 to February 15, 2014...
427 | ---> INFO: Downloading Sifttter files...DONE.
428 | ---> SUCCESS: Entry logged for February 01, 2014...
429 | ---> SUCCESS: Entry logged for February 02, 2014...
430 | ---> SUCCESS: Entry logged for February 03, 2014...
431 | ---> SUCCESS: Entry logged for February 04, 2014...
432 | ---> SUCCESS: Entry logged for February 05, 2014...
433 | ---> SUCCESS: Entry logged for February 06, 2014...
434 | ---> SUCCESS: Entry logged for February 07, 2014...
435 | ---> SUCCESS: Entry logged for February 08, 2014...
436 | ---> SUCCESS: Entry logged for February 09, 2014...
437 | ---> SUCCESS: Entry logged for February 10, 2014...
438 | ---> SUCCESS: Entry logged for February 11, 2014...
439 | ---> SUCCESS: Entry logged for February 12, 2014...
440 | ---> SUCCESS: Entry logged for February 13, 2014...
441 | ---> SUCCESS: Entry logged for February 14, 2014...
442 | ---> SUCCESS: Entry logged for February 15, 2014...
443 | ---> INFO: Uploading Day One entries to Dropbox...DONE.
444 | ---> INFO: Removing downloaded Day One files...DONE.
445 | ---> INFO: Removing downloaded Sifttter files...DONE.
446 | #### EXECUTION COMPLETE!
447 | ```
448 |
449 | Two notes to be aware of:
450 |
451 | * `-f` and `-t` are *inclusive* parameters, meaning that when specified, those
452 | dates will be included when searching for Siftter data.
453 | * Although you can specify `-f` by itself, you cannot specify `-t` by itself.
454 |
455 | Sifttter Redux makes use of the excellent
456 | [Chronic gem](https://github.com/mojombo/chronic "Chronic"), which provides
457 | natural language parsing for dates and times. This means that you can run
458 | commands with more "human" dates:
459 |
460 | ```
461 | $ srd exec -f "last monday" -t "yesterday"
462 | #### EXECUTING...
463 | ---> INFO: Creating entries for dates from February 10, 2014 to February 14, 2014...
464 | ---> INFO: Downloading Sifttter files...DONE.
465 | ---> SUCCESS: Entry logged for February 10, 2014...
466 | ---> SUCCESS: Entry logged for February 11, 2014...
467 | ---> SUCCESS: Entry logged for February 12, 2014...
468 | ---> SUCCESS: Entry logged for February 13, 2014...
469 | ---> SUCCESS: Entry logged for February 14, 2014...
470 | ---> INFO: Uploading Day One entries to Dropbox...DONE.
471 | ---> INFO: Removing downloaded Day One files...DONE.
472 | ---> INFO: Removing downloaded Sifttter files...DONE.
473 | #### EXECUTION COMPLETE!
474 | ```
475 |
476 | See [Chronic's Examples section](https://github.com/mojombo/chronic#examples "Chronic Examples")
477 | for more examples.
478 |
479 | # Cron Job
480 |
481 | By installing an entry to a `crontab`, Sifttter Redux can be run automatically
482 | on a schedule. The aim of this project was to use a Raspberry Pi; as such, the
483 | instructions below are specifically catered to that platform. That said, it
484 | should be possible to install and configure on any *NIX platform.
485 |
486 | One issue that arises is the loading of the bundled gems; because cron runs in a
487 | limited environment, it does not automatically know where to find installed gems.
488 |
489 | ## Using RVM
490 |
491 | If your Raspberry Pi uses RVM, this `crontab` entry will do:
492 |
493 | ```
494 | 55 23 * * * /bin/bash -l -c 'source "$HOME/.rvm/scripts/rvm" && srd exec'
495 | ```
496 |
497 | ## Globally Installing Bundled Gems
498 |
499 | Another option is to install the bundled gems to the global gemset:
500 |
501 | ```
502 | $ bundle install --global
503 | ```
504 |
505 | # Logging
506 |
507 | Sifttter Redux logs a lot of good info to `~/.sifttter_redux_log`. It makes use
508 | of Ruby's standard log levels:
509 |
510 | * DEBUG
511 | * INFO
512 | * WARN
513 | * ERROR
514 | * FATAL
515 | * UNKNOWN
516 |
517 | If you want to see more or less in your log files, simply change the `log_level`
518 | value in `~/.sifttter_redux` to your desired level.
519 |
520 | # Bugs and Feature Requests
521 |
522 | My current roadmap can be found on my
523 | [Trello board](https://trello.com/b/z4vl3YxC/sifttter-redux "Sifttter Redux Trello Board").
524 |
525 | To report bugs with or suggest features/changes for Sifttter Redux, please use
526 | the [Issues Page](http://github.com/bachya/sifttter-redux/issues).
527 |
528 | Contributions are welcome and encouraged. To contribute:
529 |
530 | * [Fork Sifttter Redux](http://github.com/bachya/sifttter-redux/fork).
531 | * Create a branch for your contribution (`git checkout -b new-feature`).
532 | * Commit your changes (`git commit -am 'Added this new feature'`).
533 | * Push to the branch (`git push origin new-feature`).
534 | * Create a new [Pull Request](http://github.com/bachya/sifttter-redux/compare/).
535 |
536 | # License
537 |
538 | (The MIT License)
539 |
540 | Copyright © 2014 Aaron Bach
541 |
542 | Permission is hereby granted, free of charge, to any person obtaining a copy of
543 | this software and associated documentation files (the 'Software'), to deal in the
544 | Software without restriction, including without limitation the rights to use,
545 | copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
546 | Software, and to permit persons to whom the Software is furnished to do so,
547 | subject to the following conditions:
548 |
549 | The above copyright notice and this permission notice shall be included in all
550 | copies or substantial portions of the Software.
551 |
552 | THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
553 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
554 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
555 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
556 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
557 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
558 |
559 | # Credits
560 |
561 | * Craig Eley for [Sifttter](http://craigeley.com/post/72565974459/sifttter-an-ifttt-to-day-one-logger "Sifttter")
562 | and for giving me the idea for Sifttter Redux
563 | * Dave Copeland for [GLI](https://github.com/davetron5000/gli "GLI")
564 | * Andrea Fabrizi for [Dropbox Uploader](https://github.com/andreafabrizi/Dropbox-Uploader "Dropbox Uploader")
565 | * ~~Tom Preston-Werner~~ (sorry: can't
566 | support [harrassment](http://www.businessinsider.com/github-co-founder-suspended-2014-3 "GitHub Founder Tom Preston-Werner Suspended After Harassment Allegations"))
567 | ~~and~~ Lee Jarvis for [Chronic](https://github.com/mojombo/chronic "Chronic")
568 |
--------------------------------------------------------------------------------