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 +7 -0
- data/CHANGELOG.md +7 -0
- data/Gemfile.lock +11 -12
- data/README.md +15 -3
- data/lib/feed2email.rb +3 -0
- data/lib/feed2email/entry.rb +40 -6
- data/lib/feed2email/feed.rb +55 -9
- data/lib/feed2email/logger.rb +37 -0
- data/lib/feed2email/mail.rb +1 -1
- data/lib/feed2email/version.rb +1 -1
- metadata +16 -28
- data/feeds.yml.sample +0 -3
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
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
feed2email (0.
|
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.
|
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.
|
26
|
-
json (1.
|
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.
|
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.
|
33
|
-
|
34
|
-
|
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.
|
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.
|
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
|
-
|
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
|
-
|
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'
|
data/lib/feed2email/entry.rb
CHANGED
@@ -20,7 +20,14 @@ module Feed2Email
|
|
20
20
|
end
|
21
21
|
|
22
22
|
def process
|
23
|
-
|
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
|
-
@
|
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
|
41
|
-
published_at
|
42
|
-
|
43
|
-
|
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
|
data/lib/feed2email/feed.rb
CHANGED
@@ -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
|
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
|
-
|
43
|
-
|
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
|
data/lib/feed2email/mail.rb
CHANGED
data/lib/feed2email/version.rb
CHANGED
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.
|
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-
|
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:
|
85
|
+
rubygems_version: 2.0.3
|
98
86
|
signing_key:
|
99
|
-
specification_version:
|
87
|
+
specification_version: 4
|
100
88
|
summary: RSS/Atom feed updates in your email
|
101
89
|
test_files: []
|
data/feeds.yml.sample
DELETED