fc-reminder 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: b5ce7bf3d6d953a9e54908ae34a2bd2396baf817
4
+ data.tar.gz: bcdc3d656757ae1435d8d0ffe91ef6994727cc0b
5
+ SHA512:
6
+ metadata.gz: 534d323b3629151c2f241ce61db8bd44df904192f587023dfcbf654f23f3fb21a7eafc872ebefb77a808ab4813e83039c0996e409ea40c4c17c0a6fe2c8ead6d
7
+ data.tar.gz: 41f6f401684ace0fae51de6e0aa4b7bb53cb188a9293447cbc481e26dd9c88f86a246db0d4962c80d13b752de5c8d3ea86c198241710008abe38c2d4571c3992
@@ -0,0 +1,18 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ coverage
6
+ InstalledFiles
7
+ lib/bundler/man
8
+ pkg
9
+ rdoc
10
+ spec/reports
11
+ test/tmp
12
+ test/version_tmp
13
+ tmp
14
+
15
+ # YARD artifacts
16
+ .yardoc
17
+ _yardoc
18
+ doc/
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'http://rubygems.org'
2
+
3
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,27 @@
1
+ Copyright (c) 2013, Kamil Kieliszczyk
2
+ All rights reserved.
3
+
4
+ Redistribution and use in source and binary forms, with or without modification,
5
+ are permitted provided that the following conditions are met:
6
+
7
+ * Redistributions of source code must retain the above copyright notice, this
8
+ list of conditions and the following disclaimer.
9
+
10
+ * Redistributions in binary form must reproduce the above copyright notice, this
11
+ list of conditions and the following disclaimer in the documentation and/or
12
+ other materials provided with the distribution.
13
+
14
+ * Neither the name of the {organization} nor the names of its
15
+ contributors may be used to endorse or promote products derived from
16
+ this software without specific prior written permission.
17
+
18
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
19
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
22
+ ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
25
+ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,10 @@
1
+ fc-reminder
2
+ ===========
3
+
4
+ Football Continuous Reminder
5
+
6
+ ## Copyright and License
7
+
8
+ Copyright (c) 2013, Kamil Kieliszczyk and Contributors. All Rights Reserved.
9
+
10
+ This project is licenced under the [BSD 3-Clause License](LICENSE).
@@ -0,0 +1,13 @@
1
+ require 'rubygems'
2
+ require 'bundler/gem_tasks'
3
+
4
+ Bundler.setup(:default, :development)
5
+
6
+ require 'rspec/core'
7
+ require 'rspec/core/rake_task'
8
+
9
+ RSpec::Core::RakeTask.new(:spec) do |spec|
10
+ spec.pattern = FileList['spec/**/*_spec.rb']
11
+ end
12
+
13
+ task default: :spec
@@ -0,0 +1,90 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+ require 'mixlib/cli'
5
+ require 'fc-reminder'
6
+
7
+ class FCReminderCLI
8
+ include Mixlib::CLI
9
+
10
+ BIN_BASENAME = File.basename(__FILE__)
11
+ HOME_DIR = '~/fcreminder'
12
+
13
+ banner "Usage: #{BIN_BASENAME} [options] start|stop|restart|run"
14
+
15
+ option :team,
16
+ short: '-t STRING',
17
+ long: '--team STRING',
18
+ required: true,
19
+ on: :head,
20
+ description: 'Team name'
21
+
22
+ option :recipient,
23
+ short: '-r STRING',
24
+ long: '--recipient STRING',
25
+ required: true,
26
+ on: :head,
27
+ description: 'Recipient data'
28
+
29
+ option :check,
30
+ short: '-c HH:MM',
31
+ long: '--check HH:MM',
32
+ default: '12:00',
33
+ description: 'Time at which presence of a match will be checked (default: 12:00)'
34
+
35
+ option :daemon,
36
+ short: '-D',
37
+ long: '--daemon',
38
+ default: false,
39
+ boolean: true,
40
+ description: 'Daemonize process (default: false)'
41
+
42
+ option :dir,
43
+ short: '-d',
44
+ long: '--dir DIR',
45
+ default: File.expand_path(HOME_DIR),
46
+ description: "Directory to change to once the process starts (default: #{File.expand_path(HOME_DIR)})",
47
+ proc: lambda { |dir| File.expand_path(dir) }
48
+
49
+ option :monitor,
50
+ short: '-m',
51
+ long: '--monitor',
52
+ default: false,
53
+ boolean: true,
54
+ description: 'Start monitor process (default: false)'
55
+
56
+ option :identifier,
57
+ short: '-i STRING',
58
+ long: '--identifier STRING',
59
+ description: 'An identifier for the process (default: value of --team)'
60
+
61
+ option :log,
62
+ short: '-l',
63
+ long: '--log',
64
+ default: false,
65
+ boolean: true,
66
+ description: 'Redirect both STDOUT and STDERR to a logfile named FCReminder.<team>.output in the directory defined in --log-dir (default: false)'
67
+
68
+ option :logdir,
69
+ long: '--log-dir DIR',
70
+ default: File.expand_path("#{HOME_DIR}/log"),
71
+ description: "A specific directory to put the log files into (default: #{File.expand_path("#{HOME_DIR}/log")}",
72
+ proc: lambda { |dir| File.expand_path(dir) }
73
+
74
+ def run
75
+ parse_options
76
+ config[:argv] = opt_parser.parse!(ARGV)
77
+ create_dir(config[:dir])
78
+ create_dir(config[:logdir])
79
+ config
80
+ end
81
+
82
+ private
83
+
84
+ def create_dir(dir)
85
+ Dir.mkdir(dir) unless File.exists?(dir)
86
+ end
87
+ end
88
+
89
+ FCReminder::Runner.new(FCReminderCLI.new.run).start
90
+
@@ -0,0 +1,31 @@
1
+ $:.push File.expand_path('../lib', __FILE__)
2
+ require 'fc-reminder/version'
3
+
4
+ Gem::Specification.new do |spec|
5
+ spec.name = 'fc-reminder'
6
+ spec.version = FCReminder::VERSION
7
+ spec.authors = ['Kamil Kieliszczyk']
8
+ spec.email = ['kamil@kieliszczyk.net']
9
+ spec.description = 'Simple reminder about an upcoming football game'
10
+ spec.summary = 'Simple reminder about an upcoming football game'
11
+ spec.homepage = 'https://github.com/kiela/fc-reminder'
12
+
13
+ spec.platform = Gem::Platform::RUBY
14
+ spec.required_rubygems_version = '>= 1.3.6'
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ['lib']
20
+
21
+ spec.add_dependency 'mechanize', '~> 2.7.3'
22
+ spec.add_dependency 'twilio-ruby', '~> 3.11.4'
23
+ spec.add_dependency 'mixlib-cli', '~> 1.3.0'
24
+ spec.add_dependency 'daemons', '~> 1.1.9'
25
+ spec.add_dependency 'clockwork', '~> 0.7.0'
26
+
27
+ spec.add_development_dependency 'bundler', '~> 1.3'
28
+ spec.add_development_dependency 'rake'
29
+ spec.add_development_dependency 'rspec', '~> 3.0.0.beta1'
30
+ spec.add_development_dependency 'fakeweb'
31
+ end
@@ -0,0 +1,13 @@
1
+ require 'fc-reminder/version'
2
+ require 'fc-reminder/reminder'
3
+ require 'fc-reminder/gateways/base'
4
+ require 'fc-reminder/gateways/twilio'
5
+ require 'fc-reminder/providers/base'
6
+ require 'fc-reminder/providers/livescore'
7
+ require 'fc-reminder/runner'
8
+
9
+ module FCReminder
10
+ def self.build(&customization_block)
11
+ Reminder.new(&customization_block)
12
+ end
13
+ end
@@ -0,0 +1,10 @@
1
+ module FCReminder
2
+ module Gateways
3
+ class Base
4
+ attr_accessor :config
5
+
6
+ def send(recipient:, data:)
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,30 @@
1
+ require 'twilio-ruby'
2
+
3
+ module FCReminder
4
+ module Gateways
5
+ class Twilio < Base
6
+ def send(recipient:, data:)
7
+ client = ::Twilio::REST::Client.new(
8
+ config[:account_sid],
9
+ config[:auth_token]
10
+ )
11
+ client.account.messages.create(
12
+ from: config[:phone_number],
13
+ to: recipient,
14
+ body: message(data)
15
+ )
16
+ end
17
+
18
+ private
19
+
20
+ def message(data)
21
+ if data.empty?
22
+ "No match for today"
23
+ else
24
+ "Reminder of today's match in #{data[:country]} (#{data[:league]})"\
25
+ " between #{data[:team1]} and #{data[:team2]} at #{data[:time]}"
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,23 @@
1
+ require 'mechanize'
2
+
3
+ module FCReminder
4
+ module Providers
5
+ class Base
6
+ attr_reader :client
7
+
8
+ def initialize
9
+ @client = Mechanize.new do |agent|
10
+ agent.user_agent_alias = "Linux Firefox"
11
+ end
12
+ end
13
+
14
+ def url
15
+ ""
16
+ end
17
+
18
+ def run(team_name:)
19
+ Hash.new
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,59 @@
1
+ module FCReminder
2
+ module Providers
3
+ class LiveScore < Base
4
+ BASE_URL = "http://www.livescore.com"
5
+
6
+ def url
7
+ "#{BASE_URL}/soccer/#{Time.now.strftime("%Y-%m-%d")}"
8
+ end
9
+
10
+ def run(team_name:)
11
+ cell = search(page: client.get(url), team_name: team_name.downcase)
12
+ cell.nil? ? super : prepare_output_from(cell)
13
+ end
14
+
15
+ private
16
+
17
+ def search(page:, team_name:)
18
+ page.search(".content table.league-table td").find do |td|
19
+ has_team?(td) and team_match?(td, team_name)
20
+ end
21
+ end
22
+
23
+ def has_team?(cell)
24
+ %w(fh fa).include? cell.attributes["class"].value
25
+ end
26
+
27
+ def team_match?(cell, team_name)
28
+ cell.text.strip.downcase == team_name
29
+ end
30
+
31
+ def prepare_output_from(cell)
32
+ r = Hash.new
33
+ r.merge!(fetch(attrs: league_attrs, source: cell.parent.parent))
34
+ r.merge!(fetch(attrs: match_attrs, source: cell.parent))
35
+ r
36
+ end
37
+
38
+ def fetch(attrs:, source:)
39
+ attrs.inject({}) { |h,(k,v)| h[k] = source.search(v).text.strip; h }
40
+ end
41
+
42
+ def league_attrs
43
+ {
44
+ country: 'span.league > a',
45
+ league: 'span.league > span > a',
46
+ }
47
+ end
48
+
49
+ def match_attrs
50
+ {
51
+ time: 'td.fd',
52
+ team1: 'td.fh',
53
+ team2: 'td.fa'
54
+ }
55
+ end
56
+ end
57
+ end
58
+ end
59
+
@@ -0,0 +1,41 @@
1
+ module FCReminder
2
+ class Reminder
3
+ attr_reader :provider, :gateway
4
+ attr_accessor :team_name, :recipient
5
+
6
+ def initialize(&customization_block)
7
+ @provider = Providers::LiveScore.new
8
+ @gateway = Gateways::Twilio.new
9
+ eval_block &customization_block
10
+ end
11
+
12
+ def provider=(obj)
13
+ if obj.kind_of? Providers::Base
14
+ @provider = obj
15
+ else
16
+ raise 'Provider should inherits from FCReminder::Providers::Base'
17
+ end
18
+ end
19
+
20
+ def gateway=(obj)
21
+ if obj.kind_of? Gateways::Base
22
+ @gateway = obj
23
+ else
24
+ raise 'Gateway should inherits from FCReminder::Gateways::Base'
25
+ end
26
+ end
27
+
28
+ def run(&customization_block)
29
+ eval_block &customization_block
30
+ result = provider.run(team_name: team_name)
31
+ gateway.send(recipient: recipient, data: result) unless result.empty?
32
+ end
33
+
34
+ private
35
+
36
+ def eval_block(&block)
37
+ instance_eval &block if block_given?
38
+ end
39
+ end
40
+ end
41
+
@@ -0,0 +1,68 @@
1
+ require 'daemons'
2
+ require 'clockwork'
3
+
4
+ module FCReminder
5
+ class Runner
6
+ PROCESS_NAME = 'FCReminder'
7
+ attr_reader :options, :reminder
8
+
9
+ def initialize(options)
10
+ @options = options
11
+ @reminder = initialize_reminder
12
+ end
13
+
14
+ def start
15
+ set_reminder(@reminder, @options)
16
+ @options[:daemon] ? daemonize(@options) : run
17
+ end
18
+
19
+ private
20
+
21
+ def initialize_reminder
22
+ FCReminder.build do |config|
23
+ config.gateway.config = {
24
+ account_sid: ENV['TWILIO_ACCOUNT_SID'],
25
+ auth_token: ENV['TWILIO_AUTH_TOKEN'],
26
+ phone_number: ENV['TWILIO_PHONE_NUMBER']
27
+ }
28
+ end
29
+ end
30
+
31
+ def set_reminder(reminer, options)
32
+ Clockwork.every(1.day, 'fc-reminder.check', at: options[:check]) do
33
+ reminder.run do |conf|
34
+ conf.team_name = options[:team]
35
+ conf.recipient = options[:recipient]
36
+ end
37
+ end
38
+ end
39
+
40
+ def run
41
+ Clockwork::run
42
+ end
43
+
44
+ def daemonize(options)
45
+ name = process_name(options)
46
+ opts = daemonize_options(options)
47
+ Daemons.run_proc(name, opts) { run }
48
+ end
49
+
50
+ def process_name(options)
51
+ arr = [PROCESS_NAME]
52
+ arr.push(options[:identifier] ? options[:identifier] : options[:team])
53
+ arr.join('.')
54
+ end
55
+
56
+ def daemonize_options(options)
57
+ {
58
+ ARGV: options[:argv],
59
+ dir_mode: :normal,
60
+ dir: options[:dir],
61
+ monitor: options[:monitor],
62
+ log_dir: options[:logdir],
63
+ log_output: options[:log]
64
+ }
65
+ end
66
+ end
67
+ end
68
+
@@ -0,0 +1,3 @@
1
+ module FCReminder
2
+ VERSION = '0.1.0'
3
+ end
@@ -0,0 +1,21 @@
1
+ require 'spec_helper'
2
+
3
+ describe FCReminder::Gateways::Base do
4
+ subject(:gateway) { FCReminder::Gateways::Base.new }
5
+
6
+ context "setters" do
7
+ it "allows to set config attribute" do
8
+ config = {foo: 'bar'}
9
+ expect(gateway.config).to be_nil
10
+ gateway.config = config
11
+ expect(gateway.config).to eq(config)
12
+ end
13
+ end
14
+
15
+ context "#send" do
16
+ it "responds to send method" do
17
+ expect(gateway).to respond_to(:send)
18
+ end
19
+ end
20
+ end
21
+
@@ -0,0 +1,11 @@
1
+ require 'spec_helper'
2
+
3
+ describe FCReminder::Gateways::Twilio do
4
+ subject(:gateway) { FCReminder::Gateways::Twilio.new }
5
+
6
+ context "#initialize" do
7
+ it "should be instance of FCReminder::Gateways::Base" do
8
+ expect(gateway).to be_kind_of(FCReminder::Gateways::Base)
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,30 @@
1
+ require 'spec_helper'
2
+
3
+ describe FCReminder::Providers::Base do
4
+ subject(:provider) { FCReminder::Providers::Base.new }
5
+ let(:team_name) { "Barcelona" }
6
+
7
+ context "#initialize" do
8
+ it "initializes HTTP client" do
9
+ expect(provider.client).not_to be_nil
10
+ end
11
+
12
+ it "disallows to change client" do
13
+ expect(provider).not_to respond_to(:client=)
14
+ end
15
+ end
16
+
17
+ context "#url" do
18
+ it "returns empty string" do
19
+ expect(provider.url).to be_empty
20
+ end
21
+ end
22
+
23
+ context "#run" do
24
+ it "returns empty instance of Hash" do
25
+ expect(provider.run(team_name: team_name)).to be_instance_of(Hash)
26
+ expect(provider.run(team_name: team_name)).to be_empty
27
+ end
28
+ end
29
+ end
30
+
@@ -0,0 +1,44 @@
1
+ require 'spec_helper'
2
+
3
+ describe FCReminder::Providers::LiveScore do
4
+ subject(:provider) { FCReminder::Providers::LiveScore.new }
5
+ let(:team_name) { "Barcelona" }
6
+
7
+ context "#initialize" do
8
+ it "should be instance of FCReminder::Providers::Base" do
9
+ expect(provider).to be_kind_of(FCReminder::Providers::Base)
10
+ end
11
+ end
12
+
13
+ context "#url" do
14
+ it "returns valid url" do
15
+ expect(provider.url).to match(/^#{URI::regexp}$/)
16
+ end
17
+ end
18
+
19
+ context "#run" do
20
+ context "there is no match that day" do
21
+ before(:each) { fake_page_without_match(provider.url) }
22
+
23
+ it "returns default value" do
24
+ default_value = FCReminder::Providers::Base.new.run(team_name: team_name)
25
+ expect(provider.run(team_name: team_name)).to eq(default_value)
26
+ end
27
+ end
28
+
29
+ context "there is a match that day" do
30
+ before(:each) { fake_page_with_match(provider.url) }
31
+
32
+ it "returns non-empty instance of Hash" do
33
+ expect(provider.run(team_name: team_name)).to be_an_instance_of(Hash)
34
+ expect(provider.run(team_name: team_name)).not_to be_empty
35
+ end
36
+
37
+ %w(country league time team1 team2).each do |attr|
38
+ it "has return value which includes #{attr}" do
39
+ expect(provider.run(team_name: team_name)).to have_key(attr.to_sym)
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,117 @@
1
+ require 'spec_helper'
2
+
3
+ class TestProvider < FCReminder::Providers::Base
4
+ end
5
+
6
+ class TestGateway < FCReminder::Gateways::Base
7
+ end
8
+
9
+ describe FCReminder::Reminder do
10
+ let(:team_name) { "Team Name" }
11
+ let(:recipient) { "+1234567890" }
12
+
13
+ context "#initialize" do
14
+ it "sets default values" do
15
+ reminder = FCReminder.build
16
+ expect(reminder.provider).to be_kind_of(FCReminder::Providers::Base)
17
+ expect(reminder.gateway).to be_kind_of(FCReminder::Gateways::Base)
18
+ end
19
+
20
+ it "allows to configure attributes by using a block" do
21
+ team, receiver = team_name, recipient
22
+
23
+ reminder = FCReminder.build do |config|
24
+ config.team_name = team
25
+ config.recipient = receiver
26
+ end
27
+
28
+ expect(reminder.team_name).to eq(team)
29
+ expect(reminder.recipient).to eq(receiver)
30
+ end
31
+ end
32
+
33
+ context "setters" do
34
+ subject(:reminder) { FCReminder.build }
35
+
36
+ it "allows to set team_name attribute" do
37
+ expect(reminder.team_name).to be_nil
38
+ reminder.team_name = team_name
39
+ expect(reminder.team_name).to eq(team_name)
40
+ end
41
+
42
+ it "allows to set recipient attribute" do
43
+ expect(reminder.recipient).to be_nil
44
+ reminder.recipient = recipient
45
+ expect(reminder.recipient).to eq(recipient)
46
+ end
47
+
48
+ context "provider" do
49
+ it "disallows to set when instance doesn't inherit from FCReminder::Providers::Base" do
50
+ expect{ reminder.provider = Object.new }.to raise_error
51
+ end
52
+
53
+ it "allows to set when instance inherits from FCReminder::Providers::Base" do
54
+ obj = TestProvider.new
55
+ expect(reminder.provider).not_to eq(obj)
56
+ reminder.provider = obj
57
+ expect(reminder.provider).to eq(obj)
58
+ end
59
+ end
60
+
61
+ context "gateway" do
62
+ it "disallows to set when instance doesn't inherit from FCReminder::Gateways::Base" do
63
+ expect{ reminder.gateway = Object.new }.to raise_error
64
+ end
65
+
66
+ it "allows to set when instance inherits from FCReminder::Gateways::Base" do
67
+ obj = TestGateway.new
68
+ expect(reminder.gateway).not_to eq(obj)
69
+ reminder.gateway = obj
70
+ expect(reminder.gateway).to eq(obj)
71
+ end
72
+ end
73
+ end
74
+
75
+ context "#run" do
76
+ subject(:reminder) { FCReminder.build }
77
+ before(:each) { fake_page_with_match(reminder.provider.url) }
78
+ before(:each) { reminder.gateway.stub(:send) {} }
79
+
80
+ it "allows to set consumer data by using a block" do
81
+ expect(reminder.team_name).to be_nil
82
+ expect(reminder.recipient).to be_nil
83
+
84
+ team, receiver = team_name, recipient
85
+ reminder.run do |config|
86
+ config.team_name = team
87
+ config.recipient = receiver
88
+ end
89
+
90
+ expect(reminder.team_name).to eq(team)
91
+ expect(reminder.recipient).to eq(receiver)
92
+ end
93
+
94
+ it "calls provider for data" do
95
+ reminder.provider.stub(:run) { Hash.new }
96
+ expect(reminder.provider).to receive(:run).with(team_name: team_name)
97
+
98
+ reminder.team_name = team_name
99
+ reminder.recipient = recipient
100
+ reminder.run
101
+ end
102
+
103
+ it "calls gateway for sending message" do
104
+ result = {foo: 'bar'}
105
+ reminder.provider.stub(:run) { result }
106
+ expect(reminder.gateway).to receive(:send).with(
107
+ recipient: recipient,
108
+ data: result
109
+ )
110
+
111
+ reminder.team_name = team_name
112
+ reminder.recipient = recipient
113
+ reminder.run
114
+ end
115
+ end
116
+ end
117
+
@@ -0,0 +1,64 @@
1
+ require 'spec_helper'
2
+
3
+ describe FCReminder::Runner do
4
+ let(:options) { {foo: "bar"} }
5
+
6
+ context "#initialize" do
7
+ subject(:runner) { FCReminder::Runner.new(options) }
8
+
9
+ it "sets options" do
10
+ expect(runner.options).to eq(options)
11
+ end
12
+
13
+ it "initializes reminder" do
14
+ expect(runner.reminder).to be_an_instance_of(FCReminder::Reminder)
15
+ end
16
+ end
17
+
18
+ context "setters" do
19
+ subject(:runner) { FCReminder::Runner.new(options) }
20
+
21
+ it "disallows to change options after initializing" do
22
+ expect(runner).not_to respond_to(:options=)
23
+ end
24
+
25
+ it "disallows to change reminder after initializing" do
26
+ expect(runner).not_to respond_to(:reminder=)
27
+ end
28
+ end
29
+
30
+ context "#start" do
31
+ it "sets reminder" do
32
+ options = {daemon: false}
33
+ runner = FCReminder::Runner.new(options)
34
+
35
+ Clockwork.stub(:every) { |&block| block.call }
36
+ runner.reminder.stub(:run) {}
37
+ runner.stub(:run) {}
38
+
39
+ expect(runner.reminder).to receive(:run)
40
+ runner.start
41
+ end
42
+
43
+ it "starts normal process" do
44
+ options = {daemon: false}
45
+ runner = FCReminder::Runner.new(options)
46
+
47
+ runner.stub(:run) {}
48
+
49
+ expect(runner).to receive(:run)
50
+ runner.start
51
+ end
52
+
53
+ it "starts daemon process" do
54
+ options = {daemon: true}
55
+ runner = FCReminder::Runner.new(options)
56
+
57
+ runner.stub(:daemonize) {}
58
+
59
+ expect(runner).to receive(:daemonize)
60
+ runner.start
61
+ end
62
+ end
63
+ end
64
+
@@ -0,0 +1,7 @@
1
+ require 'spec_helper'
2
+
3
+ describe FCReminder do
4
+ it 'has a version number' do
5
+ expect(FCReminder::VERSION).not_to be_nil
6
+ end
7
+ end
@@ -0,0 +1,10 @@
1
+ require 'spec_helper'
2
+
3
+ describe FCReminder do
4
+ context "#build" do
5
+ it "returns an instance of FCReminder::Reminder" do
6
+ expect(FCReminder.build).to be_instance_of(FCReminder::Reminder)
7
+ end
8
+ end
9
+ end
10
+
@@ -0,0 +1,6 @@
1
+ GEM_ROOT = File.expand_path("../../", __FILE__)
2
+ $:.unshift File.join(GEM_ROOT, "lib")
3
+
4
+ require 'fc-reminder'
5
+ Dir[File.join(GEM_ROOT, "spec", "support", "**/*.rb")].each { |f| require f }
6
+
@@ -0,0 +1,41 @@
1
+ <div class="content">
2
+ <table class="league-table">
3
+ <colgroup><col class="cold">
4
+ <col class="colh">
5
+ <col class="cols">
6
+ <col class="cola">
7
+ </colgroup><tbody><tr>
8
+ <th colspan="4">
9
+ <span class="league">
10
+ <a href="/soccer/spain/"><strong>Spain</strong></a> - <span><a href="/soccer/spain/primera-division/">Liga BBVA</a></span>
11
+ </span>
12
+ <span class="date">December 1</span>
13
+ </th>
14
+ </tr>
15
+ <tr class="even">
16
+ <td class="fd"> 12:00 </td>
17
+ <td class="fh"> Real Betis </td>
18
+ <td class="fs"> ? - ? </td>
19
+ <td class="fa"> Rayo Vallecano </td>
20
+ </tr>
21
+ <tr>
22
+ <td class="fd"> 17:00 </td>
23
+ <td class="fh"> Granada </td>
24
+ <td class="fs"> ? - ? </td>
25
+ <td class="fa"> Sevilla </td>
26
+ </tr>
27
+ <tr class="even">
28
+ <td class="fd"> 19:00 </td>
29
+ <td class="fh"> Valencia </td>
30
+ <td class="fs"> ? - ? </td>
31
+ <td class="fa"> Osasuna </td>
32
+ </tr>
33
+ <tr>
34
+ <td class="fd"> 21:00 </td>
35
+ <td class="fh"> Athletic Bilbao </td>
36
+ <td class="fs"> ? - ? </td>
37
+ <td class="fa"> Barcelona </td>
38
+ </tr>
39
+ </tbody></table>
40
+ </div>
41
+
@@ -0,0 +1,52 @@
1
+ <div class="content">
2
+ <table class="league-table">
3
+ <colgroup><col class="cold">
4
+ <col class="colh">
5
+ <col class="cols">
6
+ <col class="cola">
7
+ </colgroup><tbody><tr>
8
+ <th colspan="4">
9
+ <span class="league">
10
+ <a href="/soccer/england/"><strong>England</strong></a> - <span><a href="/soccer/england/premier-league/">Premier League</a></span>
11
+ </span>
12
+ <span class="date">November 30</span>
13
+ </th>
14
+ </tr>
15
+ <tr class="even">
16
+ <td class="fd"> 16:00 </td>
17
+ <td class="fh"> Aston Villa </td>
18
+ <td class="fs"> ? - ? </td>
19
+ <td class="fa"> Sunderland </td>
20
+ </tr>
21
+ <tr>
22
+ <td class="fd"> 16:00 </td>
23
+ <td class="fh"> Cardiff City </td>
24
+ <td class="fs"> ? - ? </td>
25
+ <td class="fa"> Arsenal </td>
26
+ </tr>
27
+ <tr class="even">
28
+ <td class="fd"> 16:00 </td>
29
+ <td class="fh"> Everton </td>
30
+ <td class="fs"> ? - ? </td>
31
+ <td class="fa"> Stoke City </td>
32
+ </tr>
33
+ <tr>
34
+ <td class="fd"> 16:00 </td>
35
+ <td class="fh"> Norwich City </td>
36
+ <td class="fs"> ? - ? </td>
37
+ <td class="fa"> Crystal Palace </td>
38
+ </tr>
39
+ <tr class="even">
40
+ <td class="fd"> 16:00 </td>
41
+ <td class="fh"> West Ham United </td>
42
+ <td class="fs"> ? - ? </td>
43
+ <td class="fa"> Fulham </td>
44
+ </tr>
45
+ <tr>
46
+ <td class="fd"> 18:30 </td>
47
+ <td class="fh"> Newcastle United </td>
48
+ <td class="fs"> ? - ? </td>
49
+ <td class="fa"> West Bromwich Albion </td>
50
+ </tr>
51
+ </tbody></table>
52
+ </div>
@@ -0,0 +1,18 @@
1
+ require 'fakeweb'
2
+
3
+ FakeWeb.allow_net_connect = false
4
+
5
+ def fake_page_without_match(url)
6
+ file = File.join(GEM_ROOT, "spec", "support", "fakeweb", "fake_page_without_match.html")
7
+ fake_html_page url, File.read(file)
8
+ end
9
+
10
+ def fake_page_with_match(url)
11
+ file = File.join(GEM_ROOT, "spec", "support", "fakeweb", "fake_page_with_match.html")
12
+ fake_html_page url, File.read(file)
13
+ end
14
+
15
+ def fake_html_page(url, body)
16
+ FakeWeb.register_uri(:get, url, body: body, content_type: "text/html")
17
+ end
18
+
metadata ADDED
@@ -0,0 +1,210 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fc-reminder
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Kamil Kieliszczyk
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-12-03 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.3
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.3
27
+ - !ruby/object:Gem::Dependency
28
+ name: twilio-ruby
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 3.11.4
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 3.11.4
41
+ - !ruby/object:Gem::Dependency
42
+ name: mixlib-cli
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 1.3.0
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 1.3.0
55
+ - !ruby/object:Gem::Dependency
56
+ name: daemons
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 1.1.9
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 1.1.9
69
+ - !ruby/object:Gem::Dependency
70
+ name: clockwork
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: 0.7.0
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: 0.7.0
83
+ - !ruby/object:Gem::Dependency
84
+ name: bundler
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '1.3'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '1.3'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rake
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: rspec
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: 3.0.0.beta1
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: 3.0.0.beta1
125
+ - !ruby/object:Gem::Dependency
126
+ name: fakeweb
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ description: Simple reminder about an upcoming football game
140
+ email:
141
+ - kamil@kieliszczyk.net
142
+ executables:
143
+ - fc-reminder
144
+ extensions: []
145
+ extra_rdoc_files: []
146
+ files:
147
+ - ".gitignore"
148
+ - ".rspec"
149
+ - Gemfile
150
+ - LICENSE
151
+ - README.md
152
+ - Rakefile
153
+ - bin/fc-reminder
154
+ - fc-reminder.gemspec
155
+ - lib/fc-reminder.rb
156
+ - lib/fc-reminder/gateways/base.rb
157
+ - lib/fc-reminder/gateways/twilio.rb
158
+ - lib/fc-reminder/providers/base.rb
159
+ - lib/fc-reminder/providers/livescore.rb
160
+ - lib/fc-reminder/reminder.rb
161
+ - lib/fc-reminder/runner.rb
162
+ - lib/fc-reminder/version.rb
163
+ - spec/fc-reminder/gateways/base_spec.rb
164
+ - spec/fc-reminder/gateways/twilio_spec.rb
165
+ - spec/fc-reminder/providers/base_spec.rb
166
+ - spec/fc-reminder/providers/livescore_spec.rb
167
+ - spec/fc-reminder/reminder_spec.rb
168
+ - spec/fc-reminder/runner_spec.rb
169
+ - spec/fc-reminder/version_spec.rb
170
+ - spec/fc-reminder_spec.rb
171
+ - spec/spec_helper.rb
172
+ - spec/support/fakeweb/fake_page_with_match.html
173
+ - spec/support/fakeweb/fake_page_without_match.html
174
+ - spec/support/helpers.rb
175
+ homepage: https://github.com/kiela/fc-reminder
176
+ licenses: []
177
+ metadata: {}
178
+ post_install_message:
179
+ rdoc_options: []
180
+ require_paths:
181
+ - lib
182
+ required_ruby_version: !ruby/object:Gem::Requirement
183
+ requirements:
184
+ - - ">="
185
+ - !ruby/object:Gem::Version
186
+ version: '0'
187
+ required_rubygems_version: !ruby/object:Gem::Requirement
188
+ requirements:
189
+ - - ">="
190
+ - !ruby/object:Gem::Version
191
+ version: 1.3.6
192
+ requirements: []
193
+ rubyforge_project:
194
+ rubygems_version: 2.1.11
195
+ signing_key:
196
+ specification_version: 4
197
+ summary: Simple reminder about an upcoming football game
198
+ test_files:
199
+ - spec/fc-reminder/gateways/base_spec.rb
200
+ - spec/fc-reminder/gateways/twilio_spec.rb
201
+ - spec/fc-reminder/providers/base_spec.rb
202
+ - spec/fc-reminder/providers/livescore_spec.rb
203
+ - spec/fc-reminder/reminder_spec.rb
204
+ - spec/fc-reminder/runner_spec.rb
205
+ - spec/fc-reminder/version_spec.rb
206
+ - spec/fc-reminder_spec.rb
207
+ - spec/spec_helper.rb
208
+ - spec/support/fakeweb/fake_page_with_match.html
209
+ - spec/support/fakeweb/fake_page_without_match.html
210
+ - spec/support/helpers.rb