feed2email 0.7.0 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +15 -1
- data/README.md +124 -59
- data/bin/f2e +9 -0
- data/bin/feed2email +4 -6
- data/bin/feed2email-migrate-feedlist +36 -0
- data/lib/feed2email.rb +16 -11
- data/lib/feed2email/cli.rb +158 -0
- data/lib/feed2email/config.rb +8 -3
- data/lib/feed2email/configurable.rb +7 -0
- data/lib/feed2email/feed.rb +87 -99
- data/lib/feed2email/feed_autodiscoverer.rb +55 -0
- data/lib/feed2email/feed_history.rb +63 -9
- data/lib/feed2email/feed_list.rb +147 -0
- data/lib/feed2email/lazy_smtp_connection.rb +6 -5
- data/lib/feed2email/loggable.rb +7 -0
- data/lib/feed2email/mail.rb +23 -39
- data/lib/feed2email/redirection_checker.rb +38 -0
- data/lib/feed2email/version.rb +1 -1
- metadata +61 -15
- data/TODO.md +0 -16
- data/lib/feed2email/feed_data_file.rb +0 -65
- data/lib/feed2email/feed_meta.rb +0 -28
- data/lib/feed2email/feeds.rb +0 -77
data/TODO.md
DELETED
@@ -1,16 +0,0 @@
|
|
1
|
-
# TODO
|
2
|
-
|
3
|
-
* Specs
|
4
|
-
* Do not mark entry as sent if email was not sent
|
5
|
-
* Implement a command-line interface to manage feeds.yml
|
6
|
-
* Detect entry URI changes (maybe by comparing body hashes?)
|
7
|
-
* Filters (e.g. skip entries matching a pattern)
|
8
|
-
* Support "dispatch interfaces" where email is one such interface (another could
|
9
|
-
be writing to the filesystem)
|
10
|
-
* Profiles (support many feed lists and recipients)
|
11
|
-
* Send email notifications to user (e.g. when a feed is not available anymore)
|
12
|
-
* Plugin architecture
|
13
|
-
* Integrate with Mail gem for email sending
|
14
|
-
* Do not consider fetched if there was an error
|
15
|
-
* begin ensure end
|
16
|
-
* Fix sleeping
|
@@ -1,65 +0,0 @@
|
|
1
|
-
require 'digest/md5'
|
2
|
-
require 'yaml'
|
3
|
-
|
4
|
-
module Feed2Email
|
5
|
-
class FeedDataFile
|
6
|
-
def initialize(uri)
|
7
|
-
@uri = uri
|
8
|
-
@dirty = false
|
9
|
-
end
|
10
|
-
|
11
|
-
def uri=(new_uri)
|
12
|
-
return if new_uri == uri
|
13
|
-
|
14
|
-
data # load data if not already loaded
|
15
|
-
remove_file
|
16
|
-
mark_dirty
|
17
|
-
@uri = new_uri
|
18
|
-
end
|
19
|
-
|
20
|
-
def sync
|
21
|
-
open(path, 'w') {|f| f.write(data.to_yaml) } if dirty
|
22
|
-
end
|
23
|
-
|
24
|
-
private
|
25
|
-
|
26
|
-
def load_data
|
27
|
-
begin
|
28
|
-
@data = YAML.load(open(path))
|
29
|
-
rescue Errno::ENOENT
|
30
|
-
@data = data_type.new
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
def path
|
35
|
-
File.join(CONFIG_DIR, filename)
|
36
|
-
end
|
37
|
-
|
38
|
-
def filename
|
39
|
-
"#{filename_prefix}-#{filename_suffix}.yml"
|
40
|
-
end
|
41
|
-
|
42
|
-
def filename_suffix
|
43
|
-
Digest::MD5.hexdigest(uri)
|
44
|
-
end
|
45
|
-
|
46
|
-
def data
|
47
|
-
@data ||= load_data
|
48
|
-
end
|
49
|
-
|
50
|
-
def mark_dirty
|
51
|
-
@dirty = true
|
52
|
-
end
|
53
|
-
|
54
|
-
def remove_file
|
55
|
-
begin
|
56
|
-
File.unlink(path)
|
57
|
-
rescue Errno::ENOENT
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
|
-
def dirty; @dirty end
|
62
|
-
|
63
|
-
def uri; @uri end
|
64
|
-
end
|
65
|
-
end
|
data/lib/feed2email/feed_meta.rb
DELETED
@@ -1,28 +0,0 @@
|
|
1
|
-
require 'feed2email/feed_data_file'
|
2
|
-
|
3
|
-
module Feed2Email
|
4
|
-
class FeedMeta < FeedDataFile
|
5
|
-
def [](key)
|
6
|
-
data[key]
|
7
|
-
end
|
8
|
-
|
9
|
-
def []=(key, value)
|
10
|
-
mark_dirty if data[key] != value
|
11
|
-
data[key] = value
|
12
|
-
end
|
13
|
-
|
14
|
-
def has_key?(key)
|
15
|
-
data.has_key?(key)
|
16
|
-
end
|
17
|
-
|
18
|
-
private
|
19
|
-
|
20
|
-
def data_type
|
21
|
-
Hash
|
22
|
-
end
|
23
|
-
|
24
|
-
def filename_prefix
|
25
|
-
'meta'
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
data/lib/feed2email/feeds.rb
DELETED
@@ -1,77 +0,0 @@
|
|
1
|
-
require 'forwardable'
|
2
|
-
require 'yaml'
|
3
|
-
|
4
|
-
module Feed2Email
|
5
|
-
class Feeds
|
6
|
-
extend Forwardable
|
7
|
-
|
8
|
-
class MissingFeedsError < StandardError; end
|
9
|
-
class InvalidFeedsSyntaxError < StandardError; end
|
10
|
-
class InvalidFeedsDataTypeError < StandardError; end
|
11
|
-
|
12
|
-
def initialize(path)
|
13
|
-
@path = path
|
14
|
-
@dirty = false
|
15
|
-
check
|
16
|
-
end
|
17
|
-
|
18
|
-
def_delegators :data, :size, :each_with_index
|
19
|
-
|
20
|
-
def []=(index, uri)
|
21
|
-
mark_dirty if data[index] != uri
|
22
|
-
data[index] = uri
|
23
|
-
end
|
24
|
-
|
25
|
-
def sync
|
26
|
-
open(path, 'w') {|f| f.write(data.to_yaml) } if dirty
|
27
|
-
end
|
28
|
-
|
29
|
-
private
|
30
|
-
|
31
|
-
def check
|
32
|
-
check_existence
|
33
|
-
check_syntax
|
34
|
-
check_data_type
|
35
|
-
end
|
36
|
-
|
37
|
-
def check_existence
|
38
|
-
if !File.exist?(path)
|
39
|
-
raise MissingFeedsError, "Missing feeds file #{path}"
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
def check_syntax
|
44
|
-
begin
|
45
|
-
load_yaml
|
46
|
-
rescue Psych::SyntaxError
|
47
|
-
raise InvalidFeedsSyntaxError,
|
48
|
-
"Invalid YAML syntax for feeds file #{path}"
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
def check_data_type
|
53
|
-
if !data.is_a?(Array)
|
54
|
-
raise InvalidFeedsDataTypeError,
|
55
|
-
"Invalid data type (not an Array) for feeds file #{path}"
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
def load_yaml
|
60
|
-
@data = YAML.load(read_file)
|
61
|
-
end
|
62
|
-
|
63
|
-
def read_file
|
64
|
-
File.read(path)
|
65
|
-
end
|
66
|
-
|
67
|
-
def mark_dirty
|
68
|
-
@dirty = true
|
69
|
-
end
|
70
|
-
|
71
|
-
def path; @path end
|
72
|
-
|
73
|
-
def data; @data end
|
74
|
-
|
75
|
-
def dirty; @dirty end
|
76
|
-
end
|
77
|
-
end
|