myredditnews 0.0.1
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/.gitignore +18 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +50 -0
- data/Rakefile +11 -0
- data/lib/myredditnews.rb +251 -0
- data/lib/myredditnews/version.rb +3 -0
- data/myredditnews.gemspec +31 -0
- data/test/lib/myredditnews/app_test.rb +39 -0
- data/test/lib/myredditnews/entry_test.rb +56 -0
- data/test/lib/myredditnews/formatter_test.rb +38 -0
- data/test/lib/myredditnews/history_test.rb +39 -0
- data/test/lib/myredditnews/source_test.rb +18 -0
- data/test/lib/myredditnews/version_test.rb +8 -0
- data/test/test_helper.rb +5 -0
- metadata +193 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 60567deb5739350f3193263d102447ea5451ddeb
|
4
|
+
data.tar.gz: 9fa9b5e8c56cfc0948653d36f83a09c65b1a6d49
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 2b89b52a72391b48ee1bbb645e42d91add14e1d43586df76fc0f1114316a93b071c0acd2053dc6f6218961b17424659805e67cc48255ea1e4256e1c299632990
|
7
|
+
data.tar.gz: 5b9534c59fdd68653ad289b6a1732904e9132da3e10ac9fd99f71bbd0075752dd5d64bcdd05c2b50b2be809af223b99f362090f3a7bc835385055523093b7748
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Rudi Grinberg
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
# Myredditnews
|
2
|
+
|
3
|
+
Want to get your reddit and rss feeds at the same place? Mirror your rss
|
4
|
+
feeds into a personal subreddit with this script.
|
5
|
+
|
6
|
+
## Installation
|
7
|
+
|
8
|
+
Add this line to your application's Gemfile:
|
9
|
+
|
10
|
+
gem 'myredditnews'
|
11
|
+
|
12
|
+
And then execute:
|
13
|
+
|
14
|
+
$ bundle
|
15
|
+
|
16
|
+
Or install it yourself as:
|
17
|
+
|
18
|
+
$ gem install myredditnews
|
19
|
+
|
20
|
+
## Usage
|
21
|
+
|
22
|
+
First configure which feeds you'd like to follow and which subreddit
|
23
|
+
you'd like them to be sent.
|
24
|
+
|
25
|
+
```
|
26
|
+
require 'myredditnews'
|
27
|
+
|
28
|
+
mrn = Myreddinews::App.new
|
29
|
+
username 'foobar'
|
30
|
+
password 'hunter2'
|
31
|
+
history '~/.mrn'
|
32
|
+
source 'http://feeds.bbci.co.uk/news/world/rss.xml'
|
33
|
+
source 'http://feeds.bbci.co.uk/news/rss.xml' do
|
34
|
+
name 'breaking news'
|
35
|
+
end
|
36
|
+
target_subreddit 'my_personal_news' # r/my_personal_news
|
37
|
+
end
|
38
|
+
|
39
|
+
mrn.sync
|
40
|
+
```
|
41
|
+
|
42
|
+
Then run the script above as with a cron job.
|
43
|
+
|
44
|
+
## Contributing
|
45
|
+
|
46
|
+
1. Fork it
|
47
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
48
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
49
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
50
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
data/lib/myredditnews.rb
ADDED
@@ -0,0 +1,251 @@
|
|
1
|
+
require 'myredditnews/version'
|
2
|
+
require 'snoo'
|
3
|
+
require 'set'
|
4
|
+
require 'json'
|
5
|
+
require 'doodle'
|
6
|
+
require 'logger'
|
7
|
+
require 'feedzirra'
|
8
|
+
require 'nokogiri'
|
9
|
+
require 'pstore'
|
10
|
+
|
11
|
+
$logger = Logger.new(STDOUT)
|
12
|
+
# TODO get rid of the global variables
|
13
|
+
$delay = 4.5
|
14
|
+
$dry = false
|
15
|
+
|
16
|
+
module Myredditnews
|
17
|
+
|
18
|
+
def self.delay; $delay; end
|
19
|
+
def self.delay=d; $delay=d; end
|
20
|
+
def self.dry; $dry; end
|
21
|
+
def self.dry=d; $dry=d; end
|
22
|
+
|
23
|
+
# TODO : remove the boiler plate below
|
24
|
+
def self.with_dry(set_to)
|
25
|
+
old = self.dry
|
26
|
+
self.dry = set_to
|
27
|
+
yield
|
28
|
+
self.dry = old
|
29
|
+
end
|
30
|
+
def self.with_delay(set_to)
|
31
|
+
old = self.delay
|
32
|
+
self.delay = set_to
|
33
|
+
yield
|
34
|
+
self.delay = old
|
35
|
+
end
|
36
|
+
class RedditError < StandardError; end
|
37
|
+
class Entry < Doodle
|
38
|
+
has :author , kind: String
|
39
|
+
has :content , kind: String
|
40
|
+
has :url , kind: String
|
41
|
+
has :title , kind: String
|
42
|
+
has :date , kind: String
|
43
|
+
has :summary , default: ''
|
44
|
+
has :self_post , default: true
|
45
|
+
def submit(reddit, subreddit)
|
46
|
+
opts = {}
|
47
|
+
if self_post?
|
48
|
+
opts[:kind] = 'self'
|
49
|
+
opts[:text] = @content
|
50
|
+
else
|
51
|
+
opts[:kind] = 'link'
|
52
|
+
opts[:url] = @url
|
53
|
+
end
|
54
|
+
$logger.info("Submitting #{opts[:kind]}: #{self}")
|
55
|
+
puts "Dryness: #{Myredditnews.dry}"
|
56
|
+
unless Myredditnews.dry
|
57
|
+
response = reddit.submit(@title, subreddit, opts)
|
58
|
+
$logger.info(response)
|
59
|
+
throw_if_error response
|
60
|
+
# TODO rate limiting should be smarter than this
|
61
|
+
puts "Sleeping for #{Myredditnews.delay}"
|
62
|
+
sleep Myredditnews.delay
|
63
|
+
end
|
64
|
+
end
|
65
|
+
def to_s
|
66
|
+
return "[#{truncate(@author, 10)}, #{truncate(@url, 20)}]"
|
67
|
+
end
|
68
|
+
def self_post?
|
69
|
+
self_post
|
70
|
+
end
|
71
|
+
def to_json(*a)
|
72
|
+
{
|
73
|
+
"author" => @author,
|
74
|
+
"content" => @content,
|
75
|
+
"url" => @url,
|
76
|
+
"date" => @date,
|
77
|
+
"summary" => @summary,
|
78
|
+
"title" => @title, }.to_json(*a)
|
79
|
+
end
|
80
|
+
private
|
81
|
+
def truncate str, width
|
82
|
+
str.size > width ? (str[0..width-1] + "...") : str
|
83
|
+
end
|
84
|
+
def throw_if_error response
|
85
|
+
unless response['json']['errors'].empty?
|
86
|
+
raise RedditError, response['json']['errors']
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
class Formatter < Doodle
|
92
|
+
# @format is the "format" of the title only
|
93
|
+
has :format, kind: String
|
94
|
+
def fmt(entry)
|
95
|
+
new_title = @format.gsub(/\{\{(.+?)\}\}/) { |match| entry.send($1) }
|
96
|
+
new_entry = entry.clone
|
97
|
+
new_entry.title = new_title
|
98
|
+
new_entry.content = format_content(new_entry)
|
99
|
+
if new_entry.content.empty?
|
100
|
+
new_entry.self_post = false
|
101
|
+
else
|
102
|
+
new_entry.content += "\n\n" + md_link('source', new_entry.url)
|
103
|
+
end
|
104
|
+
return new_entry
|
105
|
+
end
|
106
|
+
def self.default
|
107
|
+
self.new '{{title}} - {{author}}'
|
108
|
+
end
|
109
|
+
private
|
110
|
+
def md_link(text, url)
|
111
|
+
"[#{text}](#{url})"
|
112
|
+
end
|
113
|
+
def format_content entry
|
114
|
+
# maybe translate to markdown?
|
115
|
+
return filter_html(entry.content) if !entry.content.empty?
|
116
|
+
return filter_html(entry.summary) if !entry.summary.empty?
|
117
|
+
return ''
|
118
|
+
end
|
119
|
+
def filter_html html
|
120
|
+
Nokogiri::HTML(html).xpath("//text()").remove.to_s
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
class FeedFetchingError < StandardError
|
125
|
+
attr_reader :parent
|
126
|
+
def initialize parent
|
127
|
+
@parent = parent
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
class Source < Doodle
|
132
|
+
has :source, kind: String
|
133
|
+
has :name, default: nil
|
134
|
+
has :formatter, kind: Formatter, default: Formatter.default
|
135
|
+
def safe_get field
|
136
|
+
# not using sanitize because of some encoding bug.
|
137
|
+
# field.nil? ? "" : field.sanitize
|
138
|
+
field.nil? ? "" : field
|
139
|
+
end
|
140
|
+
def fetch
|
141
|
+
feed = Feedzirra::Feed.fetch_and_parse(@source)
|
142
|
+
s = self
|
143
|
+
feed.entries.map do |feed_entry|
|
144
|
+
Myredditnews::Entry.new do
|
145
|
+
author s.safe_get(feed_entry.author)
|
146
|
+
content s.safe_get(feed_entry.content)
|
147
|
+
title s.safe_get(feed_entry.title)
|
148
|
+
summary s.safe_get(feed_entry.summary)
|
149
|
+
url feed_entry.url
|
150
|
+
date feed_entry.published.to_s
|
151
|
+
end
|
152
|
+
end
|
153
|
+
rescue => e
|
154
|
+
raise FeedFetchingError, e
|
155
|
+
end
|
156
|
+
def format entry
|
157
|
+
formatter.fmt(entry)
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
class History
|
162
|
+
def initialize path
|
163
|
+
@path = path
|
164
|
+
@posted_queue = []
|
165
|
+
@db = PStore.new(File.expand_path @path)
|
166
|
+
end
|
167
|
+
def filter entries
|
168
|
+
@db.transaction do
|
169
|
+
entries.reject { |e| @db.root? e }
|
170
|
+
end
|
171
|
+
end
|
172
|
+
# TODO : the only reason this method was not removed is because it's
|
173
|
+
# used in some tests
|
174
|
+
def posted? entry
|
175
|
+
return true if @posted_queue.include? entry
|
176
|
+
@db.transaction do
|
177
|
+
@db.root? entry
|
178
|
+
end
|
179
|
+
end
|
180
|
+
def posted! entry
|
181
|
+
@posted_queue << entry
|
182
|
+
end
|
183
|
+
def append_entries!
|
184
|
+
return if Myredditnews.dry
|
185
|
+
@db.transaction do
|
186
|
+
@posted_queue.each do |e|
|
187
|
+
@db[e] = 0
|
188
|
+
end
|
189
|
+
end
|
190
|
+
end
|
191
|
+
def delete_all!
|
192
|
+
@db = nil
|
193
|
+
File.delete @path if File.exists? @path
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
class App < Doodle
|
198
|
+
has :username , kind: String
|
199
|
+
has :password , kind: String
|
200
|
+
has :useragent , default: "Myredditnews v#{Myredditnews::VERSION}"
|
201
|
+
has :history , kind: History do
|
202
|
+
from String do |path|
|
203
|
+
History.new(path)
|
204
|
+
end
|
205
|
+
end
|
206
|
+
has :target_subreddit , kind: String
|
207
|
+
has :sources, collect: Source
|
208
|
+
def sync
|
209
|
+
$logger.info("Mode: dry = #{Myredditnews.dry}")
|
210
|
+
reddit = Snoo::Client.new(useragent: useragent)
|
211
|
+
$logger.info("Logging in with #{@username}")
|
212
|
+
reddit.log_in @username, @password
|
213
|
+
total = 0
|
214
|
+
fetch_sources().each do |source, submissions|
|
215
|
+
only_new(submissions).each do |submission|
|
216
|
+
begin
|
217
|
+
source.format(submission).submit(reddit, @target_subreddit)
|
218
|
+
@history.posted! submission
|
219
|
+
total += 1
|
220
|
+
rescue RedditError => e
|
221
|
+
puts "Error submitting #{submission}"
|
222
|
+
puts "Reason: #{e.message}"
|
223
|
+
rescue => e
|
224
|
+
puts "Failed submitting #{submission}"
|
225
|
+
puts "Message: #{e.message}"
|
226
|
+
puts e.backtrace
|
227
|
+
end
|
228
|
+
end
|
229
|
+
end
|
230
|
+
$logger.info("Sent #{total} entries to r/#{@target_subreddit}")
|
231
|
+
reddit.log_out
|
232
|
+
history.append_entries!
|
233
|
+
end
|
234
|
+
def only_new submissions
|
235
|
+
@history.filter(submissions)
|
236
|
+
end
|
237
|
+
def fetch_sources
|
238
|
+
sources = {}
|
239
|
+
@sources.each do |source|
|
240
|
+
begin
|
241
|
+
sources[source] = source.fetch
|
242
|
+
rescue FeedFetchingError => e
|
243
|
+
$logger.info("Could not fetch feed #{source.source}. Reason:")
|
244
|
+
$logger.info("Exception: #{e.message}. Backtrace:")
|
245
|
+
$logger.info(e.parent.backtrace.drop(1).map {|s| "\t#{s}"}.join("\n"))
|
246
|
+
end
|
247
|
+
end
|
248
|
+
sources
|
249
|
+
end
|
250
|
+
end
|
251
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'myredditnews/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "myredditnews"
|
8
|
+
spec.version = Myredditnews::VERSION
|
9
|
+
spec.authors = ["Rudi Grinberg"]
|
10
|
+
spec.email = ["rudi.grinberg@gmail.com"]
|
11
|
+
spec.description = %q{Mirror your rss feeds into a subreddit}
|
12
|
+
spec.summary = %q{This gem is a standalone program designed to mirror
|
13
|
+
your RSS feeds into your subreddits of choice. Runs in the background }
|
14
|
+
spec.homepage = ""
|
15
|
+
spec.license = "MIT"
|
16
|
+
|
17
|
+
spec.files = `git ls-files`.split($/)
|
18
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
19
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
20
|
+
spec.require_paths = ["lib"]
|
21
|
+
|
22
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
23
|
+
spec.add_development_dependency "rake"
|
24
|
+
spec.add_development_dependency "pry"
|
25
|
+
spec.add_development_dependency "minitest"
|
26
|
+
spec.add_dependency "snoo"
|
27
|
+
spec.add_dependency "json"
|
28
|
+
spec.add_dependency "doodle"
|
29
|
+
spec.add_dependency "feedzirra"
|
30
|
+
spec.add_dependency "nokogiri"
|
31
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require_relative '../../test_helper'
|
2
|
+
|
3
|
+
describe Myredditnews::App do
|
4
|
+
|
5
|
+
it 'be configured' do
|
6
|
+
sample_format = '#{date} >> #{title} - #{author}'
|
7
|
+
user, pass = 'user', 'pass'
|
8
|
+
s1name = 'my special blog source'
|
9
|
+
s2url = 'http://another.com/one/two.rss'
|
10
|
+
|
11
|
+
mrn = Myredditnews::App.new do
|
12
|
+
username 'user'
|
13
|
+
password 'pass'
|
14
|
+
history '~/.mrn'
|
15
|
+
# Complex source
|
16
|
+
source 'http://hey.com/path/to.rss' do
|
17
|
+
formatter sample_format
|
18
|
+
name s1name
|
19
|
+
end
|
20
|
+
source s2url # simple source
|
21
|
+
target_subreddit 'testing'
|
22
|
+
end
|
23
|
+
|
24
|
+
mrn.username.must_equal user
|
25
|
+
mrn.password.must_equal pass
|
26
|
+
mrn.history.wont_be_nil
|
27
|
+
mrn.target_subreddit.wont_be_nil
|
28
|
+
|
29
|
+
refute_nil mrn.useragent
|
30
|
+
|
31
|
+
s1 = mrn.sources.first
|
32
|
+
s1.formatter.format.must_equal sample_format
|
33
|
+
|
34
|
+
s2 = mrn.sources.last
|
35
|
+
s2.source.must_equal s2url
|
36
|
+
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require_relative '../../test_helper'
|
2
|
+
|
3
|
+
describe Myredditnews::Entry do
|
4
|
+
before do
|
5
|
+
@entry = Myredditnews::Entry.new do
|
6
|
+
author "david"
|
7
|
+
content "lorem ipsum"
|
8
|
+
url "google.com"
|
9
|
+
date "tomorrow"
|
10
|
+
title "my title"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'can be serialized to json' do
|
15
|
+
js = JSON.parse(@entry.to_json)
|
16
|
+
js["author"].must_equal "david"
|
17
|
+
js["content"].must_equal "lorem ipsum"
|
18
|
+
js["date"].must_equal "tomorrow"
|
19
|
+
js["title"].must_equal "my title"
|
20
|
+
js["url"].must_equal "google.com"
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'can be parsed from json' do
|
24
|
+
json = <<END
|
25
|
+
{
|
26
|
+
"author" : "rudi",
|
27
|
+
"content" : "boring",
|
28
|
+
"date" : "yesterday",
|
29
|
+
"title" : "testing123",
|
30
|
+
"url" : "testing.com"
|
31
|
+
}
|
32
|
+
END
|
33
|
+
entry = Myredditnews::Entry(JSON.parse(json))
|
34
|
+
entry.author.must_equal "rudi"
|
35
|
+
entry.content.must_equal "boring"
|
36
|
+
entry.date.must_equal "yesterday"
|
37
|
+
entry.title.must_equal "testing123"
|
38
|
+
entry.url.must_equal "testing.com"
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'respects delay when submitting' do
|
42
|
+
reddit_mock = MiniTest::Mock.new
|
43
|
+
reddit_mock.expect(:submit,
|
44
|
+
{'json' => {'errors' => []}}, [String, String, Hash])
|
45
|
+
@new_delay = 0.05
|
46
|
+
@now = Time.now.to_f
|
47
|
+
Myredditnews.with_dry false do
|
48
|
+
Myredditnews.with_delay 0.05 do
|
49
|
+
@entry.submit(reddit_mock, 'my_subreddit')
|
50
|
+
refute_in_delta @now, Time.now.to_f, @new_delay
|
51
|
+
end
|
52
|
+
end
|
53
|
+
reddit_mock.verify
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require_relative '../../test_helper'
|
2
|
+
|
3
|
+
describe Myredditnews::Formatter do
|
4
|
+
before do
|
5
|
+
@sample_entry = Myredditnews::Entry.new do
|
6
|
+
author 'rudi'
|
7
|
+
content '<b>something</b>'
|
8
|
+
title 'testing'
|
9
|
+
url 'http://test.me/ok.rss'
|
10
|
+
title 'a title'
|
11
|
+
date 'never'
|
12
|
+
end
|
13
|
+
end
|
14
|
+
it 'must have a default formatting' do
|
15
|
+
formatter = Myredditnews::Formatter.default
|
16
|
+
refute_nil formatter.format
|
17
|
+
end
|
18
|
+
it 'default formatter must format title' do
|
19
|
+
formatted_entry = Myredditnews::Formatter.default.fmt(@sample_entry)
|
20
|
+
assert_includes formatted_entry.title, 'a title'
|
21
|
+
end
|
22
|
+
it 'custom formatting of title must work' do
|
23
|
+
formatter = Myredditnews::Formatter.new do
|
24
|
+
format '{{author}} {{author}}'
|
25
|
+
end
|
26
|
+
formatter.fmt(@sample_entry).title.must_equal 'rudi rudi'
|
27
|
+
end
|
28
|
+
it 'formatted posts must include links' do
|
29
|
+
f = Myredditnews::Formatter.default
|
30
|
+
assert_includes f.fmt(@sample_entry).content, "(#{@sample_entry.url})"
|
31
|
+
end
|
32
|
+
it 'formatted text must remove html' do
|
33
|
+
f = Myredditnews::Formatter.default
|
34
|
+
refute_includes f.fmt(@sample_entry).content, "<b>"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require_relative '../../test_helper'
|
2
|
+
|
3
|
+
describe Myredditnews::History do
|
4
|
+
before do
|
5
|
+
Myredditnews.dry = false
|
6
|
+
@entry = Myredditnews::Entry.new do
|
7
|
+
author "rudi"
|
8
|
+
content "someone"
|
9
|
+
title "foo"
|
10
|
+
date "bar"
|
11
|
+
url "gopnik"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
it 'can have entries' do
|
15
|
+
history = Myredditnews::History.new('testin.db')
|
16
|
+
history.posted?("testing").must_equal false
|
17
|
+
history.delete_all!
|
18
|
+
end
|
19
|
+
it 'can add entries' do
|
20
|
+
history = Myredditnews::History.new('testing.db')
|
21
|
+
history.posted! @entry
|
22
|
+
history.posted?(@entry).must_equal true
|
23
|
+
history.delete_all!
|
24
|
+
end
|
25
|
+
it 'can write posted' do
|
26
|
+
path = './scrub.txt'
|
27
|
+
File.exists?(path).must_equal false
|
28
|
+
history = Myredditnews::History.new(path)
|
29
|
+
history.posted! @entry
|
30
|
+
history.posted?(@entry).must_equal true
|
31
|
+
history.append_entries!
|
32
|
+
File.exists?(path).must_equal true
|
33
|
+
history.delete_all!
|
34
|
+
end
|
35
|
+
after do
|
36
|
+
Myredditnews.dry = true
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require_relative '../../test_helper'
|
2
|
+
|
3
|
+
rss_url = "http://rss.cbc.ca/lineup/topstories.xml"
|
4
|
+
|
5
|
+
describe Myredditnews::Source do
|
6
|
+
it 'can be created' do
|
7
|
+
source = Myredditnews::Source.new do
|
8
|
+
source rss_url
|
9
|
+
name 'cbc'
|
10
|
+
end
|
11
|
+
source.source.must_equal rss_url
|
12
|
+
source.name.must_equal "cbc"
|
13
|
+
end
|
14
|
+
it 'can fetch entries' do
|
15
|
+
entries = Myredditnews::Source.new(source: rss_url).fetch
|
16
|
+
(entries.size > 0).must_equal true
|
17
|
+
end
|
18
|
+
end
|
data/test/test_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,193 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: myredditnews
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Rudi Grinberg
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2013-05-26 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.3'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.3'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: pry
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: minitest
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - '>='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: snoo
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - '>='
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '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'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: json
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - '>='
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :runtime
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - '>='
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: doodle
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - '>='
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :runtime
|
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: feedzirra
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - '>='
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :runtime
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - '>='
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: nokogiri
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - '>='
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0'
|
132
|
+
type: :runtime
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - '>='
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0'
|
139
|
+
description: Mirror your rss feeds into a subreddit
|
140
|
+
email:
|
141
|
+
- rudi.grinberg@gmail.com
|
142
|
+
executables: []
|
143
|
+
extensions: []
|
144
|
+
extra_rdoc_files: []
|
145
|
+
files:
|
146
|
+
- .gitignore
|
147
|
+
- Gemfile
|
148
|
+
- LICENSE.txt
|
149
|
+
- README.md
|
150
|
+
- Rakefile
|
151
|
+
- lib/myredditnews.rb
|
152
|
+
- lib/myredditnews/version.rb
|
153
|
+
- myredditnews.gemspec
|
154
|
+
- test/lib/myredditnews/app_test.rb
|
155
|
+
- test/lib/myredditnews/entry_test.rb
|
156
|
+
- test/lib/myredditnews/formatter_test.rb
|
157
|
+
- test/lib/myredditnews/history_test.rb
|
158
|
+
- test/lib/myredditnews/source_test.rb
|
159
|
+
- test/lib/myredditnews/version_test.rb
|
160
|
+
- test/test_helper.rb
|
161
|
+
homepage: ''
|
162
|
+
licenses:
|
163
|
+
- MIT
|
164
|
+
metadata: {}
|
165
|
+
post_install_message:
|
166
|
+
rdoc_options: []
|
167
|
+
require_paths:
|
168
|
+
- lib
|
169
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
170
|
+
requirements:
|
171
|
+
- - '>='
|
172
|
+
- !ruby/object:Gem::Version
|
173
|
+
version: '0'
|
174
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
175
|
+
requirements:
|
176
|
+
- - '>='
|
177
|
+
- !ruby/object:Gem::Version
|
178
|
+
version: '0'
|
179
|
+
requirements: []
|
180
|
+
rubyforge_project:
|
181
|
+
rubygems_version: 2.0.3
|
182
|
+
signing_key:
|
183
|
+
specification_version: 4
|
184
|
+
summary: This gem is a standalone program designed to mirror your RSS feeds into your
|
185
|
+
subreddits of choice. Runs in the background
|
186
|
+
test_files:
|
187
|
+
- test/lib/myredditnews/app_test.rb
|
188
|
+
- test/lib/myredditnews/entry_test.rb
|
189
|
+
- test/lib/myredditnews/formatter_test.rb
|
190
|
+
- test/lib/myredditnews/history_test.rb
|
191
|
+
- test/lib/myredditnews/source_test.rb
|
192
|
+
- test/lib/myredditnews/version_test.rb
|
193
|
+
- test/test_helper.rb
|