feed2email 0.2.3 → 0.3.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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: bf67c31096e64a3b8e790b968fbd7fecd5384c78
4
+ data.tar.gz: 0a7567b5e3b8aa17aa9977d9a5485fa5d6fec138
5
+ SHA512:
6
+ metadata.gz: e187b0d14d5687d410b9860b6ab5cbeed2fe5d38764d95da23f460a198f607547cc8b35e5faae8b65a74c2d0add7259ab37cfec13607ff9c3de0643d0264eda6
7
+ data.tar.gz: 4d735364a8a9f84d6a66de1c3a7f622056517ec72dd04f648c2a9fad9966ea188f44dea1c5222f9b1c3ff7f64ae64f81f66970e5b4733272ec8b5e0c10f65907
data/CHANGELOG.md CHANGED
@@ -1,3 +1,10 @@
1
+ ### 0.3.0
2
+
3
+ * Add logging
4
+ * Do not sync fetch time if there was an error
5
+ * Extract email address from entry author
6
+ * Prepend feed URI to path entry permalinks
7
+
1
8
  ### 0.2.3
2
9
 
3
10
  * Isolate feed processing failures
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- feed2email (0.2.3)
4
+ feed2email (0.3.0)
5
5
  feedzirra
6
6
  mail
7
7
 
@@ -10,7 +10,7 @@ GEM
10
10
  specs:
11
11
  activesupport (3.1.12)
12
12
  multi_json (~> 1.0)
13
- builder (3.2.2)
13
+ builder (3.2.0)
14
14
  curb (0.7.18)
15
15
  feedzirra (0.1.3)
16
16
  activesupport (~> 3.1.1)
@@ -22,25 +22,24 @@ GEM
22
22
  rake (>= 0.8.7)
23
23
  rdoc (~> 3.8)
24
24
  sax-machine (~> 0.1.0)
25
- i18n (0.6.5)
26
- json (1.8.0)
25
+ i18n (0.6.4)
26
+ json (1.7.7)
27
27
  loofah (1.2.1)
28
28
  nokogiri (>= 1.4.4)
29
- mail (2.5.4)
29
+ mail (2.5.3)
30
+ i18n (>= 0.4.0)
30
31
  mime-types (~> 1.16)
31
32
  treetop (~> 1.4.8)
32
- mime-types (1.24)
33
- mini_portile (0.5.1)
34
- multi_json (1.7.9)
35
- nokogiri (1.6.0)
36
- mini_portile (~> 0.5.0)
33
+ mime-types (1.22)
34
+ multi_json (1.7.2)
35
+ nokogiri (1.5.9)
37
36
  polyglot (0.3.3)
38
- rake (10.1.0)
37
+ rake (10.0.4)
39
38
  rdoc (3.12.2)
40
39
  json (~> 1.4)
41
40
  sax-machine (0.1.0)
42
41
  nokogiri (> 0.0.0)
43
- treetop (1.4.15)
42
+ treetop (1.4.12)
44
43
  polyglot
45
44
  polyglot (>= 0.3.1)
46
45
 
data/README.md CHANGED
@@ -42,7 +42,9 @@ pair is separated with a colon: `foo: bar`
42
42
 
43
43
  * `recipient` (required) is the email address to send email to
44
44
  * `send_delay` (optional) is the number of seconds to wait between each email to
45
- avoid SMTP server throttling errors (default is `10`; use `0` to turn off)
45
+ avoid SMTP server throttling errors (default is `10`; use `0` to disable)
46
+ * `log_path` (optional) is the _absolute_ path to the log file (default is
47
+ `true` which logs to standard output; use `false` to disable)
46
48
 
47
49
  ### SMTP
48
50
 
@@ -74,9 +76,19 @@ interface setup and working in your system. I suggest [msmtp][] or [Postfix][].
74
76
  ## Use
75
77
 
76
78
  Create `~/.feed2email/feeds.yml` and add the address of each feed you want to
77
- subscribe to, prefixed with a dash and a space.
79
+ subscribe to, prefixed with a dash and a space:
78
80
 
79
- Then run it:
81
+ ~~~ yaml
82
+ - https://github.com/agorf/feed2email/commits.atom
83
+ ~~~
84
+
85
+ To disable a feed temporarily, comment it:
86
+
87
+ ~~~ yaml
88
+ #- https://github.com/agorf/feed2email/commits.atom
89
+ ~~~
90
+
91
+ You are now ready to run the program:
80
92
 
81
93
  ~~~ sh
82
94
  $ feed2email
data/lib/feed2email.rb CHANGED
@@ -1,11 +1,14 @@
1
1
  require 'cgi'
2
2
  require 'feedzirra'
3
3
  require 'fileutils'
4
+ require 'logger'
4
5
  require 'mail'
5
6
  require 'net/smtp'
7
+ require 'singleton'
6
8
  require 'yaml'
7
9
 
8
10
  require 'feed2email/config'
11
+ require 'feed2email/logger'
9
12
  require 'feed2email/version'
10
13
  require 'feed2email/core_ext'
11
14
  require 'feed2email/mail'
@@ -20,7 +20,14 @@ module Feed2Email
20
20
  end
21
21
 
22
22
  def process
23
- to_mail.send if to_be_sent?
23
+ log :debug, "Processing entry #{uri} ..."
24
+
25
+ if send?
26
+ log :debug, 'Sending email...'
27
+ to_mail.send
28
+ else
29
+ log :debug, 'Entry should not be sent; skipping...'
30
+ end
24
31
  end
25
32
 
26
33
  def title
@@ -28,19 +35,46 @@ module Feed2Email
28
35
  end
29
36
 
30
37
  def uri
31
- @data.url
38
+ @uri ||= begin
39
+ if @data.url[0] == '/'
40
+ @feed.uri.chomp('/') + @data.url
41
+ else
42
+ @data.url
43
+ end
44
+ end
32
45
  end
33
46
 
34
47
  private
35
48
 
49
+ def log(*args)
50
+ Feed2Email::Logger.instance.log(*args)
51
+ end
52
+
36
53
  def published_at
37
54
  @data.published
38
55
  end
39
56
 
40
- def to_be_sent?
41
- published_at &&
42
- published_at.past? && # respect entry future pubDate
43
- published_at > @feed.fetch_time
57
+ def send?
58
+ if published_at
59
+ log :debug, 'Entry has publication timestamp'
60
+
61
+ if published_at.past? # respect entries published in the future
62
+ log :debug, 'Entry published in the past'
63
+
64
+ if published_at > @feed.fetch_time
65
+ log :debug, 'Entry not seen before'
66
+ return true
67
+ else
68
+ log :debug, 'Entry seen before'
69
+ end
70
+ else
71
+ log :warn, "Entry #{uri} published in the future"
72
+ end
73
+ else
74
+ log :warn, "Entry #{uri} does not have publication timestamp"
75
+ end
76
+
77
+ false
44
78
  end
45
79
 
46
80
  def to_mail
@@ -3,6 +3,14 @@ module Feed2Email
3
3
  FEEDS_FILE = File.join(CONFIG_DIR, 'feeds.yml')
4
4
  STATE_FILE = File.join(CONFIG_DIR, 'state.yml')
5
5
 
6
+ def self.log(*args)
7
+ Feed2Email::Logger.instance.log(*args)
8
+ end
9
+
10
+ def self.pluralize(n, singular, plural)
11
+ "#{n} #{n == 1 ? singular : plural}"
12
+ end
13
+
6
14
  def self.process(uri)
7
15
  Feed.new(uri).process
8
16
  end
@@ -10,6 +18,7 @@ module Feed2Email
10
18
  def self.process_all
11
19
  Feed2Email::Config.instance.read!
12
20
 
21
+ log :debug, 'Loading feed subscriptions...'
13
22
  feed_uris = YAML.load(open(FEEDS_FILE)) rescue nil
14
23
 
15
24
  if !feed_uris.is_a? Array
@@ -17,19 +26,19 @@ module Feed2Email
17
26
  exit 4
18
27
  end
19
28
 
29
+ log :info, "Subscribed to #{pluralize(feed_uris.size, 'feed', 'feeds')}"
30
+
31
+ log :debug, 'Loading fetch times...'
20
32
  @@fetch_times = YAML.load(open(STATE_FILE)) rescue {}
21
33
 
22
- feed_uris.each do |uri|
23
- begin
24
- Feed.process(uri)
25
- rescue
26
- # TODO log failure
27
- end
28
- end
34
+ feed_uris.each {|uri| Feed.process(uri) }
29
35
 
36
+ log :debug, 'Writing fetch times...'
30
37
  open(STATE_FILE, 'w') {|f| f.write(@@fetch_times.to_yaml) }
31
38
  end
32
39
 
40
+ attr_reader :uri
41
+
33
42
  def initialize(uri)
34
43
  @uri = uri
35
44
  end
@@ -38,9 +47,41 @@ module Feed2Email
38
47
  @@fetch_times[@uri]
39
48
  end
40
49
 
50
+ def pluralize(*args)
51
+ Feed2Email::Feed.pluralize(*args) # delegate
52
+ end
53
+
41
54
  def process
42
- process_entries if seen_before? && fetched? && have_entries?
43
- sync_fetch_time if !seen_before? || fetched?
55
+ log :info, "Processing feed #{@uri} ..."
56
+
57
+ if seen_before?
58
+ log :debug, 'Feed seen before'
59
+
60
+ if fetched?
61
+ log :debug, 'Feed is fetched'
62
+
63
+ if have_entries?
64
+ log :info, "Processing #{pluralize(entries.size, 'entry', 'entries')}..."
65
+
66
+ begin
67
+ process_entries
68
+ rescue => e
69
+ log :error, "#{e.class}: #{e.message.strip}"
70
+ end
71
+ else
72
+ log :warn, 'Feed does not have entries'
73
+ end
74
+ else
75
+ log :error, 'Feed could not be fetched'
76
+ end
77
+ else
78
+ log :info, 'Feed not seen before; skipping...'
79
+ end
80
+
81
+ if e.nil? && (!seen_before? || fetched?)
82
+ log :debug, 'Syncing fetch time...'
83
+ sync_fetch_time
84
+ end
44
85
  end
45
86
 
46
87
  def title
@@ -51,6 +92,7 @@ module Feed2Email
51
92
 
52
93
  def data
53
94
  if @data.nil?
95
+ log :debug, 'Fetching and parsing feed...'
54
96
  @data = Feedzirra::Feed.fetch_and_parse(@uri,
55
97
  :user_agent => "feed2email/#{VERSION}",
56
98
  :compress => true
@@ -73,6 +115,10 @@ module Feed2Email
73
115
  entries.any?
74
116
  end
75
117
 
118
+ def log(*args)
119
+ Feed2Email::Feed.log(*args) # delegate
120
+ end
121
+
76
122
  def process_entries
77
123
  entries.each do |entry_data|
78
124
  Entry.process(entry_data, self)
@@ -0,0 +1,37 @@
1
+ module Feed2Email
2
+ class Logger
3
+ include Singleton
4
+
5
+ def log(severity, message)
6
+ logger.add(::Logger.const_get(severity.upcase), message) if log?
7
+ end
8
+
9
+ private
10
+
11
+ def config
12
+ Feed2Email::Config.instance.config
13
+ end
14
+
15
+ def log?
16
+ log_path != false
17
+ end
18
+
19
+ def log_path
20
+ config['log_path']
21
+ end
22
+
23
+ def log_to
24
+ if log_path.nil? || log_path == true
25
+ STDOUT
26
+ else
27
+ log_path
28
+ end
29
+ end
30
+
31
+ def logger
32
+ @logger ||= ::Logger.new(log_to)
33
+ @logger.level = ::Logger::INFO
34
+ @logger
35
+ end
36
+ end
37
+ end
@@ -50,7 +50,7 @@ module Feed2Email
50
50
 
51
51
  def from_address
52
52
  if @entry.author && @entry.author['@']
53
- @entry.author
53
+ @entry.author[/\S+@\S+/]
54
54
  elsif send_with_smtp?
55
55
  '%{user}@%{host}' % {
56
56
  :user => config['smtp_user'],
@@ -1,3 +1,3 @@
1
1
  module Feed2Email
2
- VERSION = '0.2.3'
2
+ VERSION = '0.3.0'
3
3
  end
metadata CHANGED
@@ -1,48 +1,43 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: feed2email
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.3
5
- prerelease:
4
+ version: 0.3.0
6
5
  platform: ruby
7
6
  authors:
8
7
  - Aggelos Orfanakos
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2013-08-21 00:00:00.000000000 Z
11
+ date: 2013-08-25 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: feedzirra
16
- type: :runtime
17
15
  requirement: !ruby/object:Gem::Requirement
18
- none: false
19
16
  requirements:
20
- - - ! '>='
17
+ - - '>='
21
18
  - !ruby/object:Gem::Version
22
19
  version: '0'
20
+ type: :runtime
21
+ prerelease: false
23
22
  version_requirements: !ruby/object:Gem::Requirement
24
- none: false
25
23
  requirements:
26
- - - ! '>='
24
+ - - '>='
27
25
  - !ruby/object:Gem::Version
28
26
  version: '0'
29
- prerelease: false
30
27
  - !ruby/object:Gem::Dependency
31
28
  name: mail
32
- type: :runtime
33
29
  requirement: !ruby/object:Gem::Requirement
34
- none: false
35
30
  requirements:
36
- - - ! '>='
31
+ - - '>='
37
32
  - !ruby/object:Gem::Version
38
33
  version: '0'
34
+ type: :runtime
35
+ prerelease: false
39
36
  version_requirements: !ruby/object:Gem::Requirement
40
- none: false
41
37
  requirements:
42
- - - ! '>='
38
+ - - '>='
43
39
  - !ruby/object:Gem::Version
44
40
  version: '0'
45
- prerelease: false
46
41
  description: RSS/Atom feed updates in your email
47
42
  email:
48
43
  - agorf@agorf.gr
@@ -60,42 +55,35 @@ files:
60
55
  - Rakefile
61
56
  - bin/feed2email
62
57
  - feed2email.gemspec
63
- - feeds.yml.sample
64
58
  - lib/feed2email.rb
65
59
  - lib/feed2email/config.rb
66
60
  - lib/feed2email/core_ext.rb
67
61
  - lib/feed2email/entry.rb
68
62
  - lib/feed2email/feed.rb
63
+ - lib/feed2email/logger.rb
69
64
  - lib/feed2email/mail.rb
70
65
  - lib/feed2email/version.rb
71
66
  homepage: http://github.com/agorf/feed2email
72
67
  licenses: []
68
+ metadata: {}
73
69
  post_install_message:
74
70
  rdoc_options: []
75
71
  require_paths:
76
72
  - lib
77
73
  required_ruby_version: !ruby/object:Gem::Requirement
78
- none: false
79
74
  requirements:
80
- - - ! '>='
75
+ - - '>='
81
76
  - !ruby/object:Gem::Version
82
77
  version: '0'
83
- segments:
84
- - 0
85
- hash: -4353394670092365916
86
78
  required_rubygems_version: !ruby/object:Gem::Requirement
87
- none: false
88
79
  requirements:
89
- - - ! '>='
80
+ - - '>='
90
81
  - !ruby/object:Gem::Version
91
82
  version: '0'
92
- segments:
93
- - 0
94
- hash: -4353394670092365916
95
83
  requirements: []
96
84
  rubyforge_project:
97
- rubygems_version: 1.8.23
85
+ rubygems_version: 2.0.3
98
86
  signing_key:
99
- specification_version: 3
87
+ specification_version: 4
100
88
  summary: RSS/Atom feed updates in your email
101
89
  test_files: []
data/feeds.yml.sample DELETED
@@ -1,3 +0,0 @@
1
- ---
2
- - http://feeds.feedburner.com/agorf
3
- - http://api.twitter.com/1/statuses/user_timeline.rss?screen_name=agorf