feed2email 0.8.0 → 0.9.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 +4 -4
- data/CHANGELOG.md +21 -10
- data/README.md +138 -86
- data/bin/f2e +6 -4
- data/bin/feed2email +6 -4
- data/bin/feed2email-migrate +23 -0
- data/lib/feed2email.rb +6 -9
- data/lib/feed2email/cli.rb +112 -75
- data/lib/feed2email/config.rb +72 -52
- data/lib/feed2email/core_ext.rb +10 -0
- data/lib/feed2email/database.rb +75 -0
- data/lib/feed2email/entry.rb +149 -15
- data/lib/feed2email/feed.rb +111 -130
- data/lib/feed2email/feed_autodiscoverer.rb +8 -10
- data/lib/feed2email/migrate/convert_feeds_migration.rb +29 -0
- data/lib/feed2email/migrate/feeds_import_migration.rb +42 -0
- data/lib/feed2email/migrate/history_import_migration.rb +42 -0
- data/lib/feed2email/migrate/migration.rb +42 -0
- data/lib/feed2email/migrate/split_history_migration.rb +32 -0
- data/lib/feed2email/open-uri.rb +7 -0
- data/lib/feed2email/opml_exporter.rb +109 -0
- data/lib/feed2email/opml_importer.rb +52 -0
- data/lib/feed2email/redirection_checker.rb +2 -2
- data/lib/feed2email/smtp_connection.rb +59 -0
- data/lib/feed2email/version.rb +1 -1
- metadata +55 -30
- data/bin/feed2email-migrate-feedlist +0 -36
- data/bin/feed2email-migrate-history +0 -29
- data/lib/feed2email/feed_history.rb +0 -82
- data/lib/feed2email/feed_list.rb +0 -147
- data/lib/feed2email/lazy_smtp_connection.rb +0 -35
- data/lib/feed2email/mail.rb +0 -84
data/lib/feed2email/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: feed2email
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.9.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Aggelos Orfanakos
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-01-
|
11
|
+
date: 2015-01-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: feedzirra
|
@@ -94,6 +94,34 @@ dependencies:
|
|
94
94
|
- - "~>"
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: 1.6.5
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: sequel
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: 4.18.0
|
104
|
+
type: :runtime
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: 4.18.0
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: sqlite3
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - "~>"
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: 1.3.10
|
118
|
+
type: :runtime
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - "~>"
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: 1.3.10
|
97
125
|
- !ruby/object:Gem::Dependency
|
98
126
|
name: rspec
|
99
127
|
requirement: !ruby/object:Gem::Requirement
|
@@ -168,8 +196,7 @@ description:
|
|
168
196
|
email: me@agorf.gr
|
169
197
|
executables:
|
170
198
|
- f2e
|
171
|
-
- feed2email-migrate
|
172
|
-
- feed2email-migrate-history
|
199
|
+
- feed2email-migrate
|
173
200
|
- feed2email
|
174
201
|
extensions: []
|
175
202
|
extra_rdoc_files: []
|
@@ -179,23 +206,28 @@ files:
|
|
179
206
|
- README.md
|
180
207
|
- bin/f2e
|
181
208
|
- bin/feed2email
|
182
|
-
- bin/feed2email-migrate
|
183
|
-
- bin/feed2email-migrate-history
|
209
|
+
- bin/feed2email-migrate
|
184
210
|
- lib/feed2email.rb
|
185
211
|
- lib/feed2email/cli.rb
|
186
212
|
- lib/feed2email/config.rb
|
187
213
|
- lib/feed2email/configurable.rb
|
188
214
|
- lib/feed2email/core_ext.rb
|
215
|
+
- lib/feed2email/database.rb
|
189
216
|
- lib/feed2email/entry.rb
|
190
217
|
- lib/feed2email/feed.rb
|
191
218
|
- lib/feed2email/feed_autodiscoverer.rb
|
192
|
-
- lib/feed2email/feed_history.rb
|
193
|
-
- lib/feed2email/feed_list.rb
|
194
|
-
- lib/feed2email/lazy_smtp_connection.rb
|
195
219
|
- lib/feed2email/loggable.rb
|
196
220
|
- lib/feed2email/logger.rb
|
197
|
-
- lib/feed2email/
|
221
|
+
- lib/feed2email/migrate/convert_feeds_migration.rb
|
222
|
+
- lib/feed2email/migrate/feeds_import_migration.rb
|
223
|
+
- lib/feed2email/migrate/history_import_migration.rb
|
224
|
+
- lib/feed2email/migrate/migration.rb
|
225
|
+
- lib/feed2email/migrate/split_history_migration.rb
|
226
|
+
- lib/feed2email/open-uri.rb
|
227
|
+
- lib/feed2email/opml_exporter.rb
|
228
|
+
- lib/feed2email/opml_importer.rb
|
198
229
|
- lib/feed2email/redirection_checker.rb
|
230
|
+
- lib/feed2email/smtp_connection.rb
|
199
231
|
- lib/feed2email/version.rb
|
200
232
|
homepage: https://github.com/agorf/feed2email
|
201
233
|
licenses:
|
@@ -203,31 +235,24 @@ licenses:
|
|
203
235
|
metadata: {}
|
204
236
|
post_install_message: |2+
|
205
237
|
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
to migrate your history before using feed2email: feed2email-migrate-history
|
210
|
-
If you don't, feed2email will think it is run for the first time and will
|
211
|
-
treat all entries as old (thus no email will be sent and you may miss some
|
212
|
-
entries).
|
213
|
-
|
214
|
-
* `sender` is a required config option. Please update your config file
|
215
|
-
(~/.feed2email/config.yml) to set it to an email address to send email from.
|
238
|
+
* Since version 0.9.0, the default send method is `file` which writes emails to
|
239
|
+
a file under `~/Mail/`. To change it, edit your config file (`feed2email
|
240
|
+
config`) and set `send_method` to `sendmail` or `smtp`.
|
216
241
|
|
217
|
-
|
242
|
+
* Since version 0.9.0, SQLite (instead of YAML) is used to store the feed list
|
243
|
+
and the entry history. Please issue `feed2email-migrate` to migrate your data
|
244
|
+
before running feed2email.
|
218
245
|
|
219
|
-
*
|
220
|
-
|
221
|
-
`feed2email
|
222
|
-
|
223
|
-
It is safe to remove any feed meta files: rm ~/.feed2email/meta-*.yml
|
224
|
-
|
225
|
-
* A command-line interface is available. Running feed2email without any options
|
226
|
-
will display some help text. To run it so that it processes your feed list,
|
227
|
-
issue: `feed2email process`
|
246
|
+
* Since version 0.8.0, a command-line interface is available. Running feed2email
|
247
|
+
without any arguments will display some help text. To have feed2email process
|
248
|
+
your feed list, issue `feed2email process`
|
228
249
|
|
229
250
|
Don't forget to update any cron jobs too!
|
230
251
|
|
252
|
+
* Since version 0.6.0, `sender` is a required config option. Please update your
|
253
|
+
config file (`feed2email config`) to set it to an email address to send email
|
254
|
+
from.
|
255
|
+
|
231
256
|
rdoc_options: []
|
232
257
|
require_paths:
|
233
258
|
- lib
|
@@ -1,36 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
require 'yaml'
|
4
|
-
|
5
|
-
CONFIG_DIR = File.expand_path('~/.feed2email')
|
6
|
-
FEEDS_FILE = File.join(CONFIG_DIR, 'feeds.yml')
|
7
|
-
|
8
|
-
if !File.exist?(FEEDS_FILE)
|
9
|
-
$stderr.puts "Missing feed list file #{FEEDS_FILE}"
|
10
|
-
exit 1
|
11
|
-
end
|
12
|
-
|
13
|
-
feeds_data = YAML.load(open(FEEDS_FILE))
|
14
|
-
|
15
|
-
unless feeds_data.is_a?(Array) && feeds_data.all? {|data| data.is_a?(String) }
|
16
|
-
$stderr.puts "Invalid data type for feed list file #{FEEDS_FILE}"
|
17
|
-
exit 2
|
18
|
-
end
|
19
|
-
|
20
|
-
File.rename(FEEDS_FILE, "#{FEEDS_FILE}.bak")
|
21
|
-
|
22
|
-
begin
|
23
|
-
open(FEEDS_FILE, 'w') do |f|
|
24
|
-
f.write(
|
25
|
-
feeds_data.map {|uri|
|
26
|
-
{ uri: uri, enabled: true }
|
27
|
-
}.to_yaml
|
28
|
-
)
|
29
|
-
end
|
30
|
-
|
31
|
-
puts "Migrated feed list file #{FEEDS_FILE}"
|
32
|
-
puts "Renamed #{FEEDS_FILE} to #{FEEDS_FILE}.bak"
|
33
|
-
rescue
|
34
|
-
File.rename("#{FEEDS_FILE}.bak", FEEDS_FILE)
|
35
|
-
raise
|
36
|
-
end
|
@@ -1,29 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
require 'digest/md5'
|
4
|
-
require 'yaml'
|
5
|
-
|
6
|
-
CONFIG_DIR = File.expand_path('~/.feed2email')
|
7
|
-
HISTORY_FILE = File.join(CONFIG_DIR, 'history.yml')
|
8
|
-
|
9
|
-
if !File.exist?(HISTORY_FILE)
|
10
|
-
$stderr.puts "Missing history file #{HISTORY_FILE}"
|
11
|
-
exit 1
|
12
|
-
end
|
13
|
-
|
14
|
-
history_data = YAML.load(open(HISTORY_FILE))
|
15
|
-
|
16
|
-
if !history_data.is_a?(Hash)
|
17
|
-
$stderr.puts "Invalid data type for history file #{HISTORY_FILE}"
|
18
|
-
exit 2
|
19
|
-
end
|
20
|
-
|
21
|
-
history_data.each do |feed_uri, entries|
|
22
|
-
hist_filename = "history-#{Digest::MD5.hexdigest(feed_uri)}.yml"
|
23
|
-
hist_path = File.join(CONFIG_DIR, hist_filename)
|
24
|
-
open(hist_path, 'w') {|f| f.write(entries.to_yaml) }
|
25
|
-
puts "Extracted history of #{feed_uri} to #{hist_filename}"
|
26
|
-
end
|
27
|
-
|
28
|
-
File.rename(HISTORY_FILE, "#{HISTORY_FILE}.bak")
|
29
|
-
puts "Renamed #{HISTORY_FILE} to #{HISTORY_FILE}.bak"
|
@@ -1,82 +0,0 @@
|
|
1
|
-
require 'digest/md5'
|
2
|
-
require 'yaml'
|
3
|
-
|
4
|
-
module Feed2Email
|
5
|
-
class FeedHistory
|
6
|
-
def initialize(uri)
|
7
|
-
@uri = uri
|
8
|
-
@dirty = false
|
9
|
-
end
|
10
|
-
|
11
|
-
def any?
|
12
|
-
@old_feed ||= File.exist?(path)
|
13
|
-
end
|
14
|
-
|
15
|
-
def path
|
16
|
-
File.join(CONFIG_DIR, filename)
|
17
|
-
end
|
18
|
-
|
19
|
-
def include?(entry_uri)
|
20
|
-
data.include?(entry_uri) # delegate
|
21
|
-
end
|
22
|
-
|
23
|
-
def sync
|
24
|
-
open(path, 'w') {|f| f.write(to_yaml) } if dirty
|
25
|
-
end
|
26
|
-
|
27
|
-
def uri=(new_uri)
|
28
|
-
return if new_uri == uri
|
29
|
-
|
30
|
-
data # load data if not already loaded
|
31
|
-
remove_file
|
32
|
-
mark_dirty
|
33
|
-
@uri = new_uri
|
34
|
-
end
|
35
|
-
|
36
|
-
def <<(entry_uri)
|
37
|
-
mark_dirty
|
38
|
-
data << entry_uri
|
39
|
-
end
|
40
|
-
|
41
|
-
private
|
42
|
-
|
43
|
-
def data
|
44
|
-
@data ||= load_data
|
45
|
-
end
|
46
|
-
|
47
|
-
def dirty; @dirty end
|
48
|
-
|
49
|
-
def filename
|
50
|
-
"history-#{filename_suffix}.yml"
|
51
|
-
end
|
52
|
-
|
53
|
-
def filename_suffix
|
54
|
-
Digest::MD5.hexdigest(uri)
|
55
|
-
end
|
56
|
-
|
57
|
-
def load_data
|
58
|
-
begin
|
59
|
-
@data = YAML.load(open(path))
|
60
|
-
rescue Errno::ENOENT
|
61
|
-
@data = []
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
def mark_dirty
|
66
|
-
@dirty = true
|
67
|
-
end
|
68
|
-
|
69
|
-
def remove_file
|
70
|
-
begin
|
71
|
-
File.unlink(path)
|
72
|
-
rescue Errno::ENOENT
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
76
|
-
def to_yaml
|
77
|
-
data.to_yaml # delegate
|
78
|
-
end
|
79
|
-
|
80
|
-
def uri; @uri end
|
81
|
-
end
|
82
|
-
end
|
data/lib/feed2email/feed_list.rb
DELETED
@@ -1,147 +0,0 @@
|
|
1
|
-
require 'forwardable'
|
2
|
-
require 'thor'
|
3
|
-
require 'yaml'
|
4
|
-
|
5
|
-
module Feed2Email
|
6
|
-
class FeedList
|
7
|
-
class DuplicateFeedError < StandardError; end
|
8
|
-
|
9
|
-
extend Forwardable
|
10
|
-
|
11
|
-
def initialize(path)
|
12
|
-
@path = path
|
13
|
-
@dirty = false
|
14
|
-
end
|
15
|
-
|
16
|
-
def_delegators :data, :size, :each, :each_with_index, :empty?, :[]
|
17
|
-
|
18
|
-
def <<(uri)
|
19
|
-
if index = find_feed_by_uri(uri)
|
20
|
-
raise DuplicateFeedError, "Feed #{uri} already exists at index #{index}"
|
21
|
-
end
|
22
|
-
|
23
|
-
mark_dirty
|
24
|
-
data << { uri: uri, enabled: true }
|
25
|
-
end
|
26
|
-
|
27
|
-
def clear_fetch_cache(index)
|
28
|
-
mark_dirty
|
29
|
-
data[index].delete(:last_modified)
|
30
|
-
data[index].delete(:etag)
|
31
|
-
end
|
32
|
-
|
33
|
-
def delete_at(index)
|
34
|
-
if deleted = data.delete_at(index)
|
35
|
-
mark_dirty
|
36
|
-
deleted
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
def include?(uri)
|
41
|
-
!find_feed_by_uri(uri).nil?
|
42
|
-
end
|
43
|
-
|
44
|
-
def process
|
45
|
-
require 'feed2email/feed'
|
46
|
-
|
47
|
-
begin
|
48
|
-
each do |meta|
|
49
|
-
next unless meta[:enabled]
|
50
|
-
|
51
|
-
feed = Feed.new(meta)
|
52
|
-
processed = feed.process
|
53
|
-
sync_feed_meta(feed.meta, meta, processed)
|
54
|
-
end
|
55
|
-
ensure
|
56
|
-
smtp_connection.finalize
|
57
|
-
end
|
58
|
-
|
59
|
-
sync
|
60
|
-
end
|
61
|
-
|
62
|
-
def sync
|
63
|
-
if dirty?
|
64
|
-
open(path, 'w') {|f| f.write(to_yaml) } > 0
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
def to_s
|
69
|
-
return 'Empty feed list' if empty?
|
70
|
-
|
71
|
-
justify = size.to_s.size
|
72
|
-
disabled = Thor::Shell::Color.new.set_color('DISABLED', :red)
|
73
|
-
|
74
|
-
each_with_index.map do |feed, i|
|
75
|
-
'%{index}: %{disabled}%{uri}' % {
|
76
|
-
index: i.to_s.rjust(justify),
|
77
|
-
disabled: feed[:enabled] ? '' : "#{disabled} ",
|
78
|
-
uri: feed[:uri]
|
79
|
-
}
|
80
|
-
end.join("\n")
|
81
|
-
end
|
82
|
-
|
83
|
-
def toggle(index)
|
84
|
-
if data[index]
|
85
|
-
mark_dirty
|
86
|
-
data[index][:enabled] = !data[index][:enabled]
|
87
|
-
true
|
88
|
-
end
|
89
|
-
end
|
90
|
-
|
91
|
-
private
|
92
|
-
|
93
|
-
def data
|
94
|
-
return @data if @data
|
95
|
-
|
96
|
-
if File.exist?(path)
|
97
|
-
@data = YAML.load(read_file)
|
98
|
-
else
|
99
|
-
@data = []
|
100
|
-
end
|
101
|
-
end
|
102
|
-
|
103
|
-
def dirty?; @dirty end
|
104
|
-
|
105
|
-
def find_feed_by_uri(uri)
|
106
|
-
data.index {|feed| feed[:uri] == uri }
|
107
|
-
end
|
108
|
-
|
109
|
-
def mark_dirty
|
110
|
-
@dirty = true
|
111
|
-
end
|
112
|
-
|
113
|
-
def path; @path end
|
114
|
-
|
115
|
-
def read_file
|
116
|
-
File.read(path)
|
117
|
-
end
|
118
|
-
|
119
|
-
def smtp_connection
|
120
|
-
Feed2Email.smtp_connection # delegate
|
121
|
-
end
|
122
|
-
|
123
|
-
def sync_feed_meta(src, dest, processed)
|
124
|
-
if processed
|
125
|
-
if src[:last_modified]
|
126
|
-
mark_dirty
|
127
|
-
dest[:last_modified] = src[:last_modified]
|
128
|
-
end
|
129
|
-
|
130
|
-
if src[:etag]
|
131
|
-
mark_dirty
|
132
|
-
dest[:etag] = src[:etag]
|
133
|
-
end
|
134
|
-
end
|
135
|
-
|
136
|
-
# Check for permanent redirection and persist
|
137
|
-
if dest[:uri] != src[:uri]
|
138
|
-
mark_dirty
|
139
|
-
dest[:uri] = src[:uri]
|
140
|
-
end
|
141
|
-
end
|
142
|
-
|
143
|
-
def to_yaml
|
144
|
-
data.to_yaml # delegate
|
145
|
-
end
|
146
|
-
end
|
147
|
-
end
|
@@ -1,35 +0,0 @@
|
|
1
|
-
require 'net/smtp'
|
2
|
-
require 'feed2email/configurable'
|
3
|
-
|
4
|
-
module Feed2Email
|
5
|
-
class LazySMTPConnection
|
6
|
-
include Configurable
|
7
|
-
|
8
|
-
def connect
|
9
|
-
smtp.start('localhost', config['smtp_user'], config['smtp_pass'],
|
10
|
-
config['smtp_auth'].to_sym)
|
11
|
-
end
|
12
|
-
|
13
|
-
def connected?
|
14
|
-
smtp.started?
|
15
|
-
end
|
16
|
-
|
17
|
-
def finalize
|
18
|
-
smtp.finish if connected?
|
19
|
-
end
|
20
|
-
|
21
|
-
def sendmail(*args, &block)
|
22
|
-
connect unless connected?
|
23
|
-
smtp.sendmail(*args, &block) # delegate
|
24
|
-
end
|
25
|
-
|
26
|
-
private
|
27
|
-
|
28
|
-
def smtp
|
29
|
-
return @smtp if @smtp
|
30
|
-
@smtp = Net::SMTP.new(config['smtp_host'], config['smtp_port'])
|
31
|
-
@smtp.enable_starttls if config['smtp_starttls']
|
32
|
-
@smtp
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|