extracare2of 0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +1 -0
- data/.ruby-version +1 -0
- data/Gemfile +7 -0
- data/README.md +53 -0
- data/bin/extracare2of +7 -0
- data/config/config.yml +6 -0
- data/db/coupons.db +0 -0
- data/extracare2of.gemspec +27 -0
- data/lib/ExtraCare2OF/authentication.rb +39 -0
- data/lib/ExtraCare2OF/database.rb +65 -0
- data/lib/ExtraCare2OF/runner.rb +107 -0
- data/lib/ExtraCare2OF/services.rb +113 -0
- data/lib/ExtraCare2OF/settings.rb +27 -0
- data/lib/ExtraCare2OF/version.rb +3 -0
- data/lib/extracare2of.rb +13 -0
- metadata +145 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: d174fbafa72c46930ecc9a9b8bb6de7d1f31a935
|
4
|
+
data.tar.gz: 07364580e6775bc782038da7cdcbbaacbd184354
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 1f4dfd3c0818b0178869f2a6bb2d434d0750b2a5dff458817882d8092903e115b41c69f5793bc353c82c1645c3605e5a44e401c014b39523a894b1c3ec302665
|
7
|
+
data.tar.gz: eb25c94b7957907b398d4ed0550b88eace0b4fffd4575940c2ccfeca0170362d67d04d187f29639405e369df887264a9fe5be06dc9931a4c99b3adc6cec13187
|
data/.gitignore
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
Gemfile.lock
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.1.1
|
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
|
2
|
+
# ExtraCare Reminders
|
3
|
+
|
4
|
+
## Synopsis
|
5
|
+
|
6
|
+
This script will send CVS ExtraCare coupon reminders to [OmniFocus][6764-001], [iCloud Reminders][6764-002], [Things for Mac][6764-003], or [DueApp][6764-004]. It includes SQLite database support for tracking previously imported coupons and will set task name, due date, start date, and a note
|
7
|
+
|
8
|
+
This script performs the following actions:
|
9
|
+
|
10
|
+
+ Logs into [CVS mobile][6764-005] web
|
11
|
+
+ Scans the ExtraCare page for active coupons on your card/account
|
12
|
+
+ Checks coupons against the database for previously imported coupons
|
13
|
+
+ Sends every new coupon to the task manager of your choice
|
14
|
+
|
15
|
+
## Code Example
|
16
|
+
|
17
|
+
$ ruby bin/extracare2of username password
|
18
|
+
$ Looking for coupons...
|
19
|
+
$ ----
|
20
|
+
$ Title: 10% off skincare products
|
21
|
+
$ - Due Date: 8/10/2013
|
22
|
+
$ - Start Date: 8/1/2013
|
23
|
+
$ - Note: Reedemable in-store only
|
24
|
+
|
25
|
+
|
26
|
+
|
27
|
+
## Installation
|
28
|
+
|
29
|
+
Bundle install
|
30
|
+
|
31
|
+
Edit `config/config.yml` to choose which reminder app you'd like to use.
|
32
|
+
|
33
|
+
## Todo
|
34
|
+
|
35
|
+
+ Parse ExtraBucks... I need to wait for CVS to send me some before I can figure out the right regular expression
|
36
|
+
+ Handle deals that require action, i.e., activate coupon via web
|
37
|
+
|
38
|
+
_Note: This is for paper coupons only. The actual coupons are on your CVS receipts. This script merely sets reminders for you to use them._
|
39
|
+
|
40
|
+
## Credits
|
41
|
+
|
42
|
+
This ruby script borrows some code from [ttscoff's][6764-006] [otask](http://brettterpstra.com/2011/07/02/otask-cli-for-omnifocus/) CLI OmniFocus gem.
|
43
|
+
|
44
|
+
## License
|
45
|
+
|
46
|
+
Licensed under the [MIT License][6764-007]
|
47
|
+
[6764-001]: http://www.omnigroup.com/products/omnifocus/ "OmniFocus for Mac - The Omni Group"
|
48
|
+
[6764-002]: http://support.apple.com/kb/ht4861 "iCloud: Calendar Events, Reminders, To Dos, and Tasks behavior ..."
|
49
|
+
[6764-003]: http://culturedcode.com/things/ "Things - task management for Mac & iOS | Cultured Code"
|
50
|
+
[6764-004]: http://www.dueapp.com/ "Due: The Superfast Reminder App for iPhone & iPad"
|
51
|
+
[6764-005]: http://www.cvs.com/promo/promoLandingTemplate.jsp?promoLandingId=mobile-apps "CVS Mobile Apps - CVS pharmacy"
|
52
|
+
[6764-006]: https://github.com/ttscoff "ttscoff (Brett Terpstra) · GitHub"
|
53
|
+
[6764-007]: http://opensource.org/licenses/MIT "The MIT License (MIT) | Open Source Initiative"
|
data/bin/extracare2of
ADDED
data/config/config.yml
ADDED
data/db/coupons.db
ADDED
File without changes
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'extracare2of/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "extracare2of"
|
8
|
+
spec.version = ExtraCare2OF::VERSION
|
9
|
+
spec.authors = ["Nick Prokesch"]
|
10
|
+
spec.email = ["nick@prokes.ch"]
|
11
|
+
spec.summary = %q{send CVS ExtraCare coupon reminders to OmniFocus}
|
12
|
+
spec.description = %q{Logs into CVS account, adds coupons with due dates to OmniFocus, remembers imported coupons}
|
13
|
+
spec.homepage = "https://github.com/prokizzle/extracare2of"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.require_paths = ["lib"]
|
18
|
+
spec.bindir = 'bin'
|
19
|
+
spec.executables << 'extracare2of'
|
20
|
+
|
21
|
+
spec.add_dependency "mechanize", "~> 2.7"
|
22
|
+
spec.add_dependency "amatch", "~> 0.2"
|
23
|
+
spec.add_dependency "rb-appscript", "~> 0.6"
|
24
|
+
spec.add_dependency "highline", "~> 1.6"
|
25
|
+
spec.add_dependency "chronic", "~> 0.10"
|
26
|
+
spec.add_dependency "sqlite3", "~> 1.3"
|
27
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module ExtraCare2OF
|
2
|
+
class Authentication
|
3
|
+
attr_reader :hash
|
4
|
+
|
5
|
+
def initialize(args)
|
6
|
+
@username = args[:username]
|
7
|
+
@password = args[:password]
|
8
|
+
@agent = Mechanize.new
|
9
|
+
@hash = Hash.new
|
10
|
+
end
|
11
|
+
|
12
|
+
def login
|
13
|
+
page = @agent.get("https://m.cvs.com/mt/www.cvs.com/account/login.jsp")
|
14
|
+
form = page.forms.first
|
15
|
+
form['/atg/userprofiling/ProfileFormHandler.value.login'] = @username
|
16
|
+
form['/atg/userprofiling/ProfileFormHandler.value.password'] = @password
|
17
|
+
page = form.submit
|
18
|
+
@page = page
|
19
|
+
sleep 3
|
20
|
+
# puts page.parser.xpath("//body").to_html
|
21
|
+
end
|
22
|
+
|
23
|
+
def request(link, request_id)
|
24
|
+
@hash[request_id] = {ready: false}
|
25
|
+
url = URI.escape(link)
|
26
|
+
@agent.read_timeout=30
|
27
|
+
temp = @agent.get(url)
|
28
|
+
# @log.debug "#{@url}"
|
29
|
+
returned_body = temp.parser.xpath("//body").to_html.to_s
|
30
|
+
@hash[request_id] = {url: url.to_s, body: returned_body, html: temp, ready: true}
|
31
|
+
{url: url.to_s, body: returned_body, html: temp, hash: request_id.to_i}
|
32
|
+
end
|
33
|
+
|
34
|
+
def logged_in?
|
35
|
+
/Welcome/.match(@page.parser.xpath("//body").to_html) == true
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
require 'sqlite3'
|
2
|
+
|
3
|
+
module ExtraCare2OF
|
4
|
+
class Database
|
5
|
+
attr_accessor :add_user
|
6
|
+
attr_reader :add_user
|
7
|
+
|
8
|
+
def initialize(args)
|
9
|
+
@handle = args[ :username]
|
10
|
+
open
|
11
|
+
create_tables
|
12
|
+
tasks
|
13
|
+
end
|
14
|
+
|
15
|
+
def tasks
|
16
|
+
begin
|
17
|
+
# @db.execute("alter table matches add column emailed integer")
|
18
|
+
rescue
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def create_tables
|
23
|
+
begin
|
24
|
+
@db.execute("CREATE TABLE coupons(
|
25
|
+
id integer,
|
26
|
+
name text,
|
27
|
+
due_date integer,
|
28
|
+
start_date text,
|
29
|
+
handle text,
|
30
|
+
PRIMARY KEY(id)
|
31
|
+
)
|
32
|
+
")
|
33
|
+
rescue
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
|
38
|
+
def open
|
39
|
+
@db = SQLite3::Database.new( "./db/coupons.db" )
|
40
|
+
end
|
41
|
+
|
42
|
+
def close
|
43
|
+
@db.close
|
44
|
+
end
|
45
|
+
|
46
|
+
def add_coupon(args)
|
47
|
+
|
48
|
+
name = args[:name].to_s
|
49
|
+
due_date = args[:due_date].to_s
|
50
|
+
start_date = args[:start_date].to_s
|
51
|
+
unless coupon_exists?(name)
|
52
|
+
# begin
|
53
|
+
@db.execute("insert into coupons(name, due_date, start_date, handle) values (?,?,?,?)", name, due_date, start_date, @handle)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def coupon_exists?(name)
|
58
|
+
temp = @db.execute( "select 1 where exists(
|
59
|
+
select 1
|
60
|
+
from coupons
|
61
|
+
where name = ?
|
62
|
+
) ", [name] ).any?
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,107 @@
|
|
1
|
+
|
2
|
+
module ExtraCare2OF
|
3
|
+
class Runner
|
4
|
+
|
5
|
+
def initialize(args)
|
6
|
+
@username = args[:username]
|
7
|
+
@password = args[:password]
|
8
|
+
@db = ExtraCare2OF::Database.new(username: @username)
|
9
|
+
@browser = ExtraCare2OF::Authentication.new(username: @username, password: @password)
|
10
|
+
@settings = Settings.new
|
11
|
+
@browser.login
|
12
|
+
@count = 0
|
13
|
+
# p @rewards_source
|
14
|
+
end
|
15
|
+
|
16
|
+
def async_response(url)
|
17
|
+
request_id = Time.now.to_i
|
18
|
+
@browser.request(url, request_id)
|
19
|
+
until @browser.hash[request_id][:ready]
|
20
|
+
sleep 0.1
|
21
|
+
end
|
22
|
+
@browser.hash[request_id]
|
23
|
+
end
|
24
|
+
|
25
|
+
# [fix] - rewards scanner not picking up all deals
|
26
|
+
# [todo] - add extrabucks support
|
27
|
+
def get_coupons
|
28
|
+
@rewards_source = async_response("https://m.cvs.com/mt/www.cvs.com/extracare/landing.jsp")[:body]
|
29
|
+
if $debug
|
30
|
+
puts @rewards_source
|
31
|
+
exit
|
32
|
+
end
|
33
|
+
@deals_array = Array.new
|
34
|
+
rewards = @rewards_source.scan(/<div class="un_exEntry">\n.+\>(.+)\<.div><.div.+$\n.+\>(.+)\<.div.+$\n.+\>(.+)\<.div.+$\n.+$/)
|
35
|
+
rewards.each do |deal|
|
36
|
+
name = deal[0]
|
37
|
+
due_date = deal[1]
|
38
|
+
note = deal[2]
|
39
|
+
# defer_date = deal[3]
|
40
|
+
@deals_array.push({:name => name,:due_date => parse_date(due_date), :defer_date => Time.now, :note => note})
|
41
|
+
end
|
42
|
+
@deals_array
|
43
|
+
end
|
44
|
+
|
45
|
+
def send_bucks_to_card
|
46
|
+
bucks = @rewards_source.scan(regex)
|
47
|
+
bucks.each do |buck|
|
48
|
+
link = buck.match(url)
|
49
|
+
link_page = @browser.request(link)
|
50
|
+
confirmation = @browser.request(button)
|
51
|
+
if confirmation == regex
|
52
|
+
puts "Extra Bucks sent to card"
|
53
|
+
else
|
54
|
+
puts "Error: Unable to send to card"
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
#borrowed from ttscoff's otask
|
60
|
+
def parse_date(datestring)
|
61
|
+
days = 0
|
62
|
+
if datestring =~ /^\+(\d+)$/
|
63
|
+
days = (60 * 60 * 24 * $1.to_i)
|
64
|
+
newdate = Time.now + days
|
65
|
+
else
|
66
|
+
newdate = Chronic.parse(datestring, {:context => :future, :ambiguous_time_range => 8})
|
67
|
+
end
|
68
|
+
# parsed = newdate.strftime('%D %l:%M%p').gsub(/\s+/,' ');
|
69
|
+
# return parsed =~ /1969/ ? false : parsed
|
70
|
+
return newdate
|
71
|
+
end
|
72
|
+
|
73
|
+
def process_coupon(coupon)
|
74
|
+
# puts " - Sending #{get_coupons.size} tasks to OF"
|
75
|
+
unless @db.coupon_exists?(coupon[:name])
|
76
|
+
@db.add_coupon(name: coupon[:name], due_date: coupon[:due_date], defer_date: coupon[:defer_date])
|
77
|
+
puts "----"
|
78
|
+
puts " Title: #{coupon[:name]}"
|
79
|
+
puts " - Due Date: #{coupon[:due_date]}"
|
80
|
+
puts " - Start Date: #{coupon[:defer_date]}"
|
81
|
+
puts " - Note: #{coupon[:note]}"
|
82
|
+
CreateTask::OmniFocus.new(coupon.to_hash) if @settings.use_omnifocus
|
83
|
+
CreateTask::Reminders.new(coupon.to_hash) if @settings.use_reminders
|
84
|
+
CreateTask::Things.new(coupon.to_hash) if @settings.use_things
|
85
|
+
CreateTask::DueApp.new(coupon.to_hash) if @settings.use_dueapp
|
86
|
+
# Services::Reminders.new(coupon.to_hash)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
|
91
|
+
def run
|
92
|
+
puts "Looking for coupons..."
|
93
|
+
@result = get_coupons
|
94
|
+
@result.each {|coupon| process_coupon(coupon)}
|
95
|
+
if @count > 0
|
96
|
+
puts "Sent #{@count} coupons to OmniFocus"
|
97
|
+
else
|
98
|
+
puts "No new coupons found."
|
99
|
+
end
|
100
|
+
# puts "Sending extra bucks to card"
|
101
|
+
# send_bucks_to_card
|
102
|
+
# puts "Done"
|
103
|
+
# exit
|
104
|
+
end
|
105
|
+
|
106
|
+
end
|
107
|
+
end
|
@@ -0,0 +1,113 @@
|
|
1
|
+
module CreateTask
|
2
|
+
require 'chronic'
|
3
|
+
|
4
|
+
class OmniFocus
|
5
|
+
require 'appscript'#;include Appscript
|
6
|
+
|
7
|
+
|
8
|
+
def initialize(args)
|
9
|
+
args[:due_date] = parse_date(args[:due_date]) if args[:due_date]
|
10
|
+
args[:defer_date] = parse_date(args[:defer_date]) if args[:defer_date]
|
11
|
+
|
12
|
+
of = app("OmniFocus")
|
13
|
+
@dd= of.default_document
|
14
|
+
@dd.make(:new => :inbox_task, :with_properties => args.to_hash)
|
15
|
+
end
|
16
|
+
|
17
|
+
def parse_date(datestring)
|
18
|
+
days = 0
|
19
|
+
if datestring =~ /^\+(\d+)$/
|
20
|
+
days = (60 * 60 * 24 * $1.to_i)
|
21
|
+
newdate = Time.now + days
|
22
|
+
else
|
23
|
+
newdate = Chronic.parse(datestring.to_s, {:context => :future, :ambiguous_time_range => 8})
|
24
|
+
end
|
25
|
+
# parsed = newdate.strftime('%D %l:%M%p').gsub(/\s+/,' ');
|
26
|
+
# return parsed =~ /1969/ ? false : parsed
|
27
|
+
return newdate
|
28
|
+
end
|
29
|
+
|
30
|
+
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
class Reminders
|
35
|
+
# include 'helper'
|
36
|
+
def initialize(args)
|
37
|
+
name = args[:name]
|
38
|
+
# due_date = parse_date(args[:due_date])
|
39
|
+
due_date = args[:due_date]
|
40
|
+
remind = %x{osascript <<'APPLESCRIPT'
|
41
|
+
set d_date to date "#{due_date}"
|
42
|
+
tell application "Reminders" to show (make new reminder with properties {name:"#{name}", due date:(d_date)})
|
43
|
+
APPLESCRIPT}
|
44
|
+
end
|
45
|
+
|
46
|
+
def parse_date(datestring)
|
47
|
+
days = 0
|
48
|
+
if datestring =~ /^\+(\d+)$/
|
49
|
+
days = (60 * 60 * 24 * $1.to_i)
|
50
|
+
newdate = Time.now + days
|
51
|
+
else
|
52
|
+
newdate = Chronic.parse(datestring, {:context => :future, :ambiguous_time_range => 8})
|
53
|
+
end
|
54
|
+
# parsed = newdate.strftime('%D %l:%M%p').gsub(/\s+/,' ');
|
55
|
+
# return parsed =~ /1969/ ? false : parsed
|
56
|
+
return newdate
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
|
61
|
+
class DueApp
|
62
|
+
# include 'helper'
|
63
|
+
def initialize(args)
|
64
|
+
name = args[:name]
|
65
|
+
# due_date = parse_date(args[:due_date])
|
66
|
+
due_date = args[:due_date]
|
67
|
+
remind =%x{osascript << 'APPLESCRIPT'
|
68
|
+
set d_date to date "#{due_date}"
|
69
|
+
set theURl to "due:///add?title=#{name}&due_date=" & d_date
|
70
|
+
tell application "Finder" to open location theURl
|
71
|
+
tell application "Due" to activate
|
72
|
+
delay 0.5 -- This delay can be tweaked for your system
|
73
|
+
tell application "Due" to activate
|
74
|
+
tell application "System Events" to key code 36
|
75
|
+
delay 1 -- This delay can be tweaked for your system
|
76
|
+
APPLESCRIPT
|
77
|
+
}
|
78
|
+
|
79
|
+
end
|
80
|
+
|
81
|
+
def parse_date(datestring)
|
82
|
+
days = 0
|
83
|
+
if datestring =~ /^\+(\d+)$/
|
84
|
+
days = (60 * 60 * 24 * $1.to_i)
|
85
|
+
newdate = Time.now + days
|
86
|
+
else
|
87
|
+
newdate = Chronic.parse(datestring, {:context => :future, :ambiguous_time_range => 8})
|
88
|
+
end
|
89
|
+
# parsed = newdate.strftime('%D %l:%M%p').gsub(/\s+/,' ');
|
90
|
+
# return parsed =~ /1969/ ? false : parsed
|
91
|
+
return newdate
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
class Things
|
96
|
+
def initialize(args)
|
97
|
+
name = args[:name]
|
98
|
+
due_date = args[:due_date]
|
99
|
+
notes = args[:notes]
|
100
|
+
tags = args[:tag]
|
101
|
+
remind = %x{osascript << 'APPLESCRIPT'
|
102
|
+
set d_date to date "#{due_date}"
|
103
|
+
tell application "Things"
|
104
|
+
set newToDo to make new to do with properties {name: "#{name}"}
|
105
|
+
set newToDo's notes to "#{notes}"
|
106
|
+
set newToDo's due date to d_date
|
107
|
+
set tag names of newToDo to "#{tags}"
|
108
|
+
end tell
|
109
|
+
APPLESCRIPT}
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module ExtraCare2OF
|
2
|
+
class Settings
|
3
|
+
attr_reader :debug, :use_omnifocus, :use_reminders, :use_things, :use_dueapp
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
@filename = File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "config", "config.yml"))
|
7
|
+
unless File.exists?(@filename)
|
8
|
+
config = {services: {
|
9
|
+
:use_omnifocus => true,
|
10
|
+
:use_reminders => false,
|
11
|
+
:use_things => false,
|
12
|
+
:use_dueapp => false
|
13
|
+
}
|
14
|
+
}
|
15
|
+
File.open(@filename, "w") do |f|
|
16
|
+
f.write(config.to_yaml)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
@settings = YAML.load_file(@filename)
|
20
|
+
@use_omnifocus = @settings[:services][:use_omnifocus]
|
21
|
+
@use_reminders = @settings[:services][:use_reminders]
|
22
|
+
@use_things = @settings[:services][:use_things]
|
23
|
+
@use_dueapp = @settings[:services][:use_dueapp]
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
data/lib/extracare2of.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
require 'highline/import'
|
3
|
+
require 'appscript';include Appscript
|
4
|
+
require 'amatch';include Amatch
|
5
|
+
require 'chronic'
|
6
|
+
require 'mechanize'
|
7
|
+
require 'open-uri'
|
8
|
+
|
9
|
+
module ExtraCare2OF
|
10
|
+
Dir[File.dirname(__FILE__) + '/extracare2of/*.rb'].each do |file|
|
11
|
+
require file
|
12
|
+
end
|
13
|
+
end
|
metadata
ADDED
@@ -0,0 +1,145 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: extracare2of
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: '0.2'
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Nick Prokesch
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-08-19 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: mechanize
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '2.7'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '2.7'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: amatch
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0.2'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0.2'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rb-appscript
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0.6'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0.6'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: highline
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '1.6'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '1.6'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: chronic
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0.10'
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0.10'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: sqlite3
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '1.3'
|
90
|
+
type: :runtime
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '1.3'
|
97
|
+
description: Logs into CVS account, adds coupons with due dates to OmniFocus, remembers
|
98
|
+
imported coupons
|
99
|
+
email:
|
100
|
+
- nick@prokes.ch
|
101
|
+
executables:
|
102
|
+
- extracare2of
|
103
|
+
extensions: []
|
104
|
+
extra_rdoc_files: []
|
105
|
+
files:
|
106
|
+
- ".gitignore"
|
107
|
+
- ".ruby-version"
|
108
|
+
- Gemfile
|
109
|
+
- README.md
|
110
|
+
- bin/extracare2of
|
111
|
+
- config/config.yml
|
112
|
+
- db/coupons.db
|
113
|
+
- extracare2of.gemspec
|
114
|
+
- lib/ExtraCare2OF/authentication.rb
|
115
|
+
- lib/ExtraCare2OF/database.rb
|
116
|
+
- lib/ExtraCare2OF/runner.rb
|
117
|
+
- lib/ExtraCare2OF/services.rb
|
118
|
+
- lib/ExtraCare2OF/settings.rb
|
119
|
+
- lib/ExtraCare2OF/version.rb
|
120
|
+
- lib/extracare2of.rb
|
121
|
+
homepage: https://github.com/prokizzle/extracare2of
|
122
|
+
licenses:
|
123
|
+
- MIT
|
124
|
+
metadata: {}
|
125
|
+
post_install_message:
|
126
|
+
rdoc_options: []
|
127
|
+
require_paths:
|
128
|
+
- lib
|
129
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
130
|
+
requirements:
|
131
|
+
- - ">="
|
132
|
+
- !ruby/object:Gem::Version
|
133
|
+
version: '0'
|
134
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - ">="
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0'
|
139
|
+
requirements: []
|
140
|
+
rubyforge_project:
|
141
|
+
rubygems_version: 2.2.2
|
142
|
+
signing_key:
|
143
|
+
specification_version: 4
|
144
|
+
summary: send CVS ExtraCare coupon reminders to OmniFocus
|
145
|
+
test_files: []
|