feedtools 0.2.8 → 0.2.9
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.
- data/CHANGELOG +6 -0
- data/lib/database_feed_cache.rb +145 -0
- data/lib/feed_tools.rb +91 -191
- data/rakefile +2 -1
- metadata +13 -2
data/CHANGELOG
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
== FeedTools 0.2.9
|
2
|
+
* changed ordering of elements checked for the item content
|
3
|
+
* added dependancy on uuidtools, uuids used in feed generation
|
4
|
+
* database feed cache implementation factored out into its own file
|
5
|
+
* http_fetch changed to use lambda
|
6
|
+
* fixed invalid rss 1.0/2.0 generation (missing some namespaces)
|
1
7
|
== FeedTools 0.2.8
|
2
8
|
* fixed bug with http headers being loaded from invalid YAML
|
3
9
|
* fixed uninitialized constant bug (you shouldn't have RUBYOPT set)
|
@@ -0,0 +1,145 @@
|
|
1
|
+
#= database_feed_cache.rb
|
2
|
+
#
|
3
|
+
# The <tt>DatabaseFeedCache</tt> is the default caching mechanism for
|
4
|
+
# FeedTools. This mechanism can be replaced easily by creating another
|
5
|
+
# class with the required set of methods and setting
|
6
|
+
# <tt>FeedTools#feed_cache</tt> to the new class.
|
7
|
+
module FeedTools
|
8
|
+
# The default caching mechanism for the FeedTools module
|
9
|
+
class DatabaseFeedCache < ActiveRecord::Base
|
10
|
+
# Overrides the default table name to use the "feeds" table.
|
11
|
+
def self.table_name() "feeds" end
|
12
|
+
|
13
|
+
# If ActiveRecord is not already connected, attempts to find a configuration file and use
|
14
|
+
# it to open a connection for ActiveRecord.
|
15
|
+
# This method is probably unnecessary for anything but testing and debugging purposes.
|
16
|
+
# In a Rails environment, the connection will already have been established
|
17
|
+
# and this method will simply do nothing.
|
18
|
+
#
|
19
|
+
# This method should not raise any exceptions because it's designed to be run only when
|
20
|
+
# the module is first loaded. If it fails, the user should get an exception when they
|
21
|
+
# try to perform some action that makes use of the caching functionality, and not until.
|
22
|
+
def DatabaseFeedCache.initialize_cache
|
23
|
+
# Establish a connection if we don't already have one
|
24
|
+
begin
|
25
|
+
ActiveRecord::Base.connection
|
26
|
+
rescue
|
27
|
+
begin
|
28
|
+
possible_config_files = [
|
29
|
+
"./config/database.yml",
|
30
|
+
"../config/database.yml",
|
31
|
+
"./database.yml",
|
32
|
+
"../database.yml"
|
33
|
+
]
|
34
|
+
database_config_file = nil
|
35
|
+
for file in possible_config_files
|
36
|
+
if File.exists? file
|
37
|
+
database_config_file = file
|
38
|
+
break
|
39
|
+
end
|
40
|
+
end
|
41
|
+
database_config_hash = File.open(database_config_file) do |file|
|
42
|
+
config_hash = YAML::load(file)
|
43
|
+
unless config_hash[FEED_TOOLS_ENV].nil?
|
44
|
+
config_hash = config_hash[FEED_TOOLS_ENV]
|
45
|
+
end
|
46
|
+
config_hash
|
47
|
+
end
|
48
|
+
ActiveRecord::Base.configurations = database_config_hash
|
49
|
+
ActiveRecord::Base.establish_connection(database_config_hash)
|
50
|
+
ActiveRecord::Base.connection
|
51
|
+
rescue
|
52
|
+
end
|
53
|
+
end
|
54
|
+
# Verify that the necessary database tables are in place
|
55
|
+
# and if they're missing, create them
|
56
|
+
unless DatabaseFeedCache.table_exists?
|
57
|
+
DatabaseFeedCache.create_table
|
58
|
+
end
|
59
|
+
return nil
|
60
|
+
end
|
61
|
+
|
62
|
+
# Returns true if a connection to the database has been established and the
|
63
|
+
# required table structure is in place.
|
64
|
+
def DatabaseFeedCache.connected?
|
65
|
+
begin
|
66
|
+
ActiveRecord::Base.connection
|
67
|
+
return false if ActiveRecord::Base.configurations.nil?
|
68
|
+
return false unless DatabaseFeedCache.table_exists?
|
69
|
+
rescue => error
|
70
|
+
return false
|
71
|
+
end
|
72
|
+
return true
|
73
|
+
end
|
74
|
+
|
75
|
+
# True if the appropriate database table already exists
|
76
|
+
def DatabaseFeedCache.table_exists?
|
77
|
+
begin
|
78
|
+
ActiveRecord::Base.connection.execute "select id, url, title, " +
|
79
|
+
"link, xml_data, http_headers, last_retrieved " +
|
80
|
+
"from #{self.table_name()} limit 1"
|
81
|
+
rescue ActiveRecord::StatementInvalid
|
82
|
+
return false
|
83
|
+
rescue
|
84
|
+
return false
|
85
|
+
end
|
86
|
+
return true
|
87
|
+
end
|
88
|
+
|
89
|
+
# Creates the appropriate database table
|
90
|
+
# Deprecated.
|
91
|
+
def DatabaseFeedCache.create_table
|
92
|
+
warn("The table creation methods will be removed in a future version " +
|
93
|
+
"and any reliance on this method should be removed.")
|
94
|
+
unless DatabaseFeedCache.table_exists?
|
95
|
+
feeds_mysql = <<-SQL_END
|
96
|
+
CREATE TABLE `#{self.table_name()}` (
|
97
|
+
`id` int(10) unsigned NOT NULL auto_increment,
|
98
|
+
`url` varchar(255) default NULL,
|
99
|
+
`title` varchar(255) default NULL,
|
100
|
+
`link` varchar(255) default NULL,
|
101
|
+
`xml_data` longtext default NULL,
|
102
|
+
`http_headers` text default NULL,
|
103
|
+
`last_retrieved` datetime default NULL,
|
104
|
+
PRIMARY KEY (`id`)
|
105
|
+
)
|
106
|
+
SQL_END
|
107
|
+
feeds_sqlite = <<-SQL_END
|
108
|
+
CREATE TABLE '#{self.table_name()}' (
|
109
|
+
'id' INTEGER PRIMARY KEY NOT NULL,
|
110
|
+
'url' VARCHAR(255) DEFAULT NULL,
|
111
|
+
'title' VARCHAR(255) DEFAULT NULL,
|
112
|
+
'link' VARCHAR(255) DEFAULT NULL,
|
113
|
+
'xml_data' TEXT DEFAULT NULL,
|
114
|
+
'http_headers' TEXT DEFAULT NULL,
|
115
|
+
'last_retrieved' DATETIME DEFAULT NULL
|
116
|
+
);
|
117
|
+
SQL_END
|
118
|
+
feeds_psql = <<-SQL_END
|
119
|
+
CREATE TABLE #{self.table_name()} (
|
120
|
+
id SERIAL PRIMARY KEY NOT NULL,
|
121
|
+
url varchar(255) default NULL,
|
122
|
+
title varchar(255) default NULL,
|
123
|
+
link varchar(255) default NULL,
|
124
|
+
xml_data text default NULL,
|
125
|
+
http_headers text default NULL,
|
126
|
+
last_retrieved timestamp default NULL
|
127
|
+
);
|
128
|
+
SQL_END
|
129
|
+
table_creation_sql = nil
|
130
|
+
if configurations["adapter"] == "mysql"
|
131
|
+
table_creation_sql = feeds_mysql
|
132
|
+
elsif configurations["adapter"] == "sqlite"
|
133
|
+
table_creation_sql = feeds_sqlite
|
134
|
+
elsif configurations["adapter"] == "postgresql"
|
135
|
+
table_creation_sql = feeds_psql
|
136
|
+
end
|
137
|
+
if table_creation_sql.nil?
|
138
|
+
raise "Could not build #{self.table_name()} table."
|
139
|
+
else
|
140
|
+
connection.execute table_creation_sql
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
data/lib/feed_tools.rb
CHANGED
@@ -22,19 +22,30 @@
|
|
22
22
|
#++
|
23
23
|
|
24
24
|
if Object.const_defined?(:FEED_TOOLS_ENV)
|
25
|
-
|
26
|
-
"by the presence of the RUBYOPT environment variable
|
25
|
+
warn("FeedTools may have been loaded improperly. This may be caused " +
|
26
|
+
"by the presence of the RUBYOPT environment variable or by using " +
|
27
|
+
"load instead of require. This can also be caused by missing " +
|
28
|
+
"the Iconv library, which is common on Windows.")
|
27
29
|
end
|
28
30
|
|
29
31
|
FEED_TOOLS_ENV = ENV['FEED_TOOLS_ENV'] ||
|
30
32
|
ENV['RAILS_ENV'] ||
|
31
33
|
'production' # :nodoc:
|
32
34
|
|
33
|
-
FEED_TOOLS_VERSION = "0.2.
|
35
|
+
FEED_TOOLS_VERSION = "0.2.9"
|
34
36
|
|
35
37
|
$:.unshift(File.dirname(__FILE__))
|
36
38
|
$:.unshift(File.dirname(__FILE__) + "/feed_tools/vendor")
|
37
|
-
|
39
|
+
|
40
|
+
begin
|
41
|
+
require 'iconv'
|
42
|
+
rescue LoadError
|
43
|
+
warn("The Iconv library does not appear to be installed properly. " +
|
44
|
+
"FeedTools cannot function properly without it.")
|
45
|
+
raise
|
46
|
+
end
|
47
|
+
|
48
|
+
require 'rubygems'
|
38
49
|
|
39
50
|
begin
|
40
51
|
require 'builder'
|
@@ -57,15 +68,16 @@ require 'net/ftp'
|
|
57
68
|
|
58
69
|
require 'rexml/document'
|
59
70
|
|
60
|
-
require 'iconv'
|
61
71
|
require 'uri'
|
62
72
|
require 'time'
|
63
73
|
require 'cgi'
|
64
74
|
require 'pp'
|
65
75
|
require 'yaml'
|
66
76
|
|
67
|
-
require 'rubygems'
|
68
77
|
require_gem('activerecord', '>= 1.10.1')
|
78
|
+
require_gem('uuidtools', '>= 0.1.1')
|
79
|
+
|
80
|
+
require 'database_feed_cache'
|
69
81
|
|
70
82
|
#= feed_tools.rb
|
71
83
|
#
|
@@ -84,141 +96,6 @@ require_gem('activerecord', '>= 1.10.1')
|
|
84
96
|
# => "43,37,28,23,11,3,1"
|
85
97
|
module FeedTools
|
86
98
|
|
87
|
-
# The default caching mechanism for the FeedTools module
|
88
|
-
class DatabaseFeedCache < ActiveRecord::Base
|
89
|
-
# Overrides the default table name to use the "feeds" table.
|
90
|
-
def self.table_name() "feeds" end
|
91
|
-
|
92
|
-
# If ActiveRecord is not already connected, attempts to find a configuration file and use
|
93
|
-
# it to open a connection for ActiveRecord.
|
94
|
-
# This method is probably unnecessary for anything but testing and debugging purposes.
|
95
|
-
# In a Rails environment, the connection will already have been established
|
96
|
-
# and this method will simply do nothing.
|
97
|
-
#
|
98
|
-
# This method should not raise any exceptions because it's designed to be run only when
|
99
|
-
# the module is first loaded. If it fails, the user should get an exception when they
|
100
|
-
# try to perform some action that makes use of the caching functionality, and not until.
|
101
|
-
def DatabaseFeedCache.initialize_cache
|
102
|
-
# Establish a connection if we don't already have one
|
103
|
-
begin
|
104
|
-
ActiveRecord::Base.connection
|
105
|
-
rescue
|
106
|
-
begin
|
107
|
-
possible_config_files = [
|
108
|
-
"./config/database.yml",
|
109
|
-
"../config/database.yml",
|
110
|
-
"./database.yml",
|
111
|
-
"../database.yml"
|
112
|
-
]
|
113
|
-
database_config_file = nil
|
114
|
-
for file in possible_config_files
|
115
|
-
if File.exists? file
|
116
|
-
database_config_file = file
|
117
|
-
break
|
118
|
-
end
|
119
|
-
end
|
120
|
-
database_config_hash = File.open(database_config_file) do |file|
|
121
|
-
config_hash = YAML::load(file)
|
122
|
-
unless config_hash[FEED_TOOLS_ENV].nil?
|
123
|
-
config_hash = config_hash[FEED_TOOLS_ENV]
|
124
|
-
end
|
125
|
-
config_hash
|
126
|
-
end
|
127
|
-
ActiveRecord::Base.configurations = database_config_hash
|
128
|
-
ActiveRecord::Base.establish_connection(database_config_hash)
|
129
|
-
ActiveRecord::Base.connection
|
130
|
-
rescue
|
131
|
-
end
|
132
|
-
end
|
133
|
-
# Verify that the necessary database tables are in place
|
134
|
-
# and if they're missing, create them
|
135
|
-
unless DatabaseFeedCache.table_exists?
|
136
|
-
DatabaseFeedCache.create_table
|
137
|
-
end
|
138
|
-
return nil
|
139
|
-
end
|
140
|
-
|
141
|
-
# Returns true if a connection to the database has been established and the
|
142
|
-
# required table structure is in place.
|
143
|
-
def DatabaseFeedCache.connected?
|
144
|
-
begin
|
145
|
-
ActiveRecord::Base.connection
|
146
|
-
return false if ActiveRecord::Base.configurations.nil?
|
147
|
-
return false unless DatabaseFeedCache.table_exists?
|
148
|
-
rescue => error
|
149
|
-
return false
|
150
|
-
end
|
151
|
-
return true
|
152
|
-
end
|
153
|
-
|
154
|
-
# True if the appropriate database table already exists
|
155
|
-
def DatabaseFeedCache.table_exists?
|
156
|
-
begin
|
157
|
-
ActiveRecord::Base.connection.execute "select id, url, title, " +
|
158
|
-
"link, xml_data, http_headers, last_retrieved " +
|
159
|
-
"from #{self.table_name()} limit 1"
|
160
|
-
rescue ActiveRecord::StatementInvalid
|
161
|
-
return false
|
162
|
-
rescue
|
163
|
-
return false
|
164
|
-
end
|
165
|
-
return true
|
166
|
-
end
|
167
|
-
|
168
|
-
# Creates the appropriate database table
|
169
|
-
def DatabaseFeedCache.create_table
|
170
|
-
unless DatabaseFeedCache.table_exists?
|
171
|
-
feeds_mysql = <<-SQL_END
|
172
|
-
CREATE TABLE `#{self.table_name()}` (
|
173
|
-
`id` int(10) unsigned NOT NULL auto_increment,
|
174
|
-
`url` varchar(255) default NULL,
|
175
|
-
`title` varchar(255) default NULL,
|
176
|
-
`link` varchar(255) default NULL,
|
177
|
-
`xml_data` longtext default NULL,
|
178
|
-
`http_headers` text default NULL,
|
179
|
-
`last_retrieved` datetime default NULL,
|
180
|
-
PRIMARY KEY (`id`)
|
181
|
-
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
|
182
|
-
SQL_END
|
183
|
-
feeds_sqlite = <<-SQL_END
|
184
|
-
CREATE TABLE '#{self.table_name()}' (
|
185
|
-
'id' INTEGER PRIMARY KEY NOT NULL,
|
186
|
-
'url' VARCHAR(255) DEFAULT NULL,
|
187
|
-
'title' VARCHAR(255) DEFAULT NULL,
|
188
|
-
'link' VARCHAR(255) DEFAULT NULL,
|
189
|
-
'xml_data' TEXT DEFAULT NULL,
|
190
|
-
'http_headers' TEXT DEFAULT NULL,
|
191
|
-
'last_retrieved' DATETIME DEFAULT NULL
|
192
|
-
);
|
193
|
-
SQL_END
|
194
|
-
feeds_psql = <<-SQL_END
|
195
|
-
CREATE TABLE #{self.table_name()} (
|
196
|
-
id SERIAL PRIMARY KEY NOT NULL,
|
197
|
-
url varchar(255) default NULL,
|
198
|
-
title varchar(255) default NULL,
|
199
|
-
link varchar(255) default NULL,
|
200
|
-
xml_data text default NULL,
|
201
|
-
http_headers text default NULL,
|
202
|
-
last_retrieved timestamp default NULL
|
203
|
-
);
|
204
|
-
SQL_END
|
205
|
-
table_creation_sql = nil
|
206
|
-
if configurations["adapter"] == "mysql"
|
207
|
-
table_creation_sql = feeds_mysql
|
208
|
-
elsif configurations["adapter"] == "sqlite"
|
209
|
-
table_creation_sql = feeds_sqlite
|
210
|
-
elsif configurations["adapter"] == "postgresql"
|
211
|
-
table_creation_sql = feeds_psql
|
212
|
-
end
|
213
|
-
if table_creation_sql.nil?
|
214
|
-
raise "Could not build #{self.table_name()} table."
|
215
|
-
else
|
216
|
-
connection.execute table_creation_sql
|
217
|
-
end
|
218
|
-
end
|
219
|
-
end
|
220
|
-
end
|
221
|
-
|
222
99
|
# Error raised when a feed cannot be retrieved
|
223
100
|
class FeedAccessError < StandardError
|
224
101
|
end
|
@@ -446,6 +323,8 @@ module FeedTools
|
|
446
323
|
'/usr/lib/tidy.so',
|
447
324
|
'C:\Program Files\Tidy\tidy.dll',
|
448
325
|
'C:\Tidy\tidy.dll',
|
326
|
+
'C:\Ruby\bin\tidy.dll',
|
327
|
+
'C:\Ruby\tidy.dll',
|
449
328
|
'/usr/local/lib',
|
450
329
|
'/opt/local/lib',
|
451
330
|
'/usr/lib'
|
@@ -558,6 +437,7 @@ module FeedTools
|
|
558
437
|
if (feed_uri.path =~ /^[\/]+/) == 0
|
559
438
|
feed_uri.path.gsub!(/^[\/]+/, "/")
|
560
439
|
end
|
440
|
+
feed_uri.host.downcase!
|
561
441
|
return feed_uri.to_s
|
562
442
|
rescue URI::InvalidURIError
|
563
443
|
return normalized_url
|
@@ -586,18 +466,14 @@ module FeedTools
|
|
586
466
|
end
|
587
467
|
|
588
468
|
# Converts a url into a urn:uuid: uri
|
589
|
-
|
590
|
-
|
591
|
-
|
592
|
-
|
593
|
-
|
594
|
-
|
595
|
-
|
596
|
-
|
597
|
-
# require 'uuidtools'
|
598
|
-
# tag_uri = UUID.sha1_create(normalized_url).to_uri_string
|
599
|
-
# return tag_uri
|
600
|
-
# end
|
469
|
+
def FeedTools.build_urn_uri(url)
|
470
|
+
unless url.kind_of? String
|
471
|
+
raise ArgumentError, "Expected String, got #{url.class.name}"
|
472
|
+
end
|
473
|
+
normalized_url = normalize_url(url)
|
474
|
+
require 'uuidtools'
|
475
|
+
return UUID.sha1_create(normalized_url).to_uri_string
|
476
|
+
end
|
601
477
|
|
602
478
|
# Returns true if the parameter appears to be a valid uri
|
603
479
|
def FeedTools.is_uri?(url)
|
@@ -896,10 +772,10 @@ module FeedTools
|
|
896
772
|
@http_headers = YAML.load(self.cache_object.http_headers)
|
897
773
|
@http_headers = {} unless @http_headers.kind_of? Hash
|
898
774
|
end
|
899
|
-
if
|
900
|
-
load_remote_feed!
|
901
|
-
else
|
775
|
+
if FeedTools.cache_only? || self.expired? == false
|
902
776
|
@live = false
|
777
|
+
else
|
778
|
+
load_remote_feed!
|
903
779
|
end
|
904
780
|
end
|
905
781
|
|
@@ -955,8 +831,8 @@ module FeedTools
|
|
955
831
|
FeedTools.user_agent unless FeedTools.user_agent.nil?
|
956
832
|
|
957
833
|
# The http feed access method
|
958
|
-
|
959
|
-
response_chain
|
834
|
+
http_fetch = lambda do |feed_url, http_headers, redirect_limit,
|
835
|
+
response_chain|
|
960
836
|
raise FeedAccessError, 'Redirect too deep' if redirect_limit == 0
|
961
837
|
feed_uri = nil
|
962
838
|
begin
|
@@ -995,7 +871,7 @@ module FeedTools
|
|
995
871
|
break
|
996
872
|
end
|
997
873
|
end
|
998
|
-
|
874
|
+
response
|
999
875
|
when Net::HTTPRedirection
|
1000
876
|
if response.code.to_i == 304
|
1001
877
|
response.error!
|
@@ -1012,7 +888,7 @@ module FeedTools
|
|
1012
888
|
# TODO: deal with stupid people using relative urls
|
1013
889
|
# in Location header
|
1014
890
|
# =================================================
|
1015
|
-
http_fetch(new_location, http_headers,
|
891
|
+
http_fetch.call(new_location, http_headers,
|
1016
892
|
redirect_limit - 1, response_chain)
|
1017
893
|
end
|
1018
894
|
else
|
@@ -1022,7 +898,7 @@ module FeedTools
|
|
1022
898
|
end
|
1023
899
|
|
1024
900
|
begin
|
1025
|
-
@http_response = http_fetch(self.url, headers)
|
901
|
+
@http_response = http_fetch.call(self.url, headers, 10, [])
|
1026
902
|
@http_headers = {}
|
1027
903
|
self.http_response.each_header do |header|
|
1028
904
|
self.http_headers[header.first.downcase] = header.last
|
@@ -1142,6 +1018,9 @@ module FeedTools
|
|
1142
1018
|
def xml
|
1143
1019
|
if @xml_doc.nil?
|
1144
1020
|
begin
|
1021
|
+
# TODO: :ignore_whitespace_nodes => :all
|
1022
|
+
# Add that?
|
1023
|
+
# ======================================
|
1145
1024
|
@xml_doc = Document.new(xml_data)
|
1146
1025
|
rescue
|
1147
1026
|
# Something failed, attempt to repair the xml with htree.
|
@@ -2446,9 +2325,17 @@ module FeedTools
|
|
2446
2325
|
elsif feed_type == "atom" && (version == nil || version == 0.0)
|
2447
2326
|
version = 0.3
|
2448
2327
|
end
|
2449
|
-
if feed_type == "rss" && (version == 0.9 || version == 1.0 ||
|
2328
|
+
if feed_type == "rss" && (version == 0.9 || version == 1.0 ||
|
2329
|
+
version == 1.1)
|
2450
2330
|
# RDF-based rss format
|
2451
|
-
return xml_builder.tag!("rdf:RDF"
|
2331
|
+
return xml_builder.tag!("rdf:RDF",
|
2332
|
+
"xmlns" => "http://purl.org/rss/1.0/",
|
2333
|
+
"xmlns:rdf" => "http://www.w3.org/1999/02/22-rdf-syntax-ns#",
|
2334
|
+
"xmlns:dc" => "http://purl.org/dc/elements/1.1/",
|
2335
|
+
"xmlns:syn" => "http://purl.org/rss/1.0/modules/syndication/",
|
2336
|
+
"xmlns:taxo" => "http://purl.org/rss/1.0/modules/taxonomy/",
|
2337
|
+
"xmlns:itunes" => "http://www.itunes.com/DTDs/Podcast-1.0.dtd",
|
2338
|
+
"xmlns:media" => "http://search.yahoo.com/mrss") do
|
2452
2339
|
channel_attributes = {}
|
2453
2340
|
unless self.link.nil?
|
2454
2341
|
channel_attributes["rdf:about"] = CGI.escapeHTML(self.link)
|
@@ -2530,22 +2417,32 @@ module FeedTools
|
|
2530
2417
|
end
|
2531
2418
|
elsif feed_type == "rss"
|
2532
2419
|
# normal rss format
|
2533
|
-
return xml_builder.rss("version" =>
|
2534
|
-
|
2535
|
-
|
2536
|
-
|
2537
|
-
|
2538
|
-
|
2539
|
-
|
2540
|
-
|
2541
|
-
|
2542
|
-
|
2543
|
-
|
2544
|
-
|
2545
|
-
|
2546
|
-
|
2547
|
-
|
2548
|
-
|
2420
|
+
return xml_builder.rss("version" => "2.0",
|
2421
|
+
"xmlns:rdf" => "http://www.w3.org/1999/02/22-rdf-syntax-ns#",
|
2422
|
+
"xmlns:dc" => "http://purl.org/dc/elements/1.1/",
|
2423
|
+
"xmlns:taxo" => "http://purl.org/rss/1.0/modules/taxonomy/",
|
2424
|
+
"xmlns:trackback" =>
|
2425
|
+
"http://madskills.com/public/xml/rss/module/trackback/",
|
2426
|
+
"xmlns:itunes" => "http://www.itunes.com/DTDs/Podcast-1.0.dtd",
|
2427
|
+
"xmlns:media" => "http://search.yahoo.com/mrss") do
|
2428
|
+
xml_builder.channel do
|
2429
|
+
unless title.nil? || title == ""
|
2430
|
+
xml_builder.title(title)
|
2431
|
+
end
|
2432
|
+
unless link.nil? || link == ""
|
2433
|
+
xml_builder.link(link)
|
2434
|
+
end
|
2435
|
+
unless description.nil? || description == ""
|
2436
|
+
xml_builder.description(description)
|
2437
|
+
end
|
2438
|
+
xml_builder.ttl((time_to_live / 1.minute).to_s)
|
2439
|
+
xml_builder.generator(
|
2440
|
+
"http://www.sporkmonger.com/projects/feedtools")
|
2441
|
+
build_xml_hook(feed_type, version, xml_builder)
|
2442
|
+
unless items.nil?
|
2443
|
+
for item in items
|
2444
|
+
item.build_xml(feed_type, version, xml_builder)
|
2445
|
+
end
|
2549
2446
|
end
|
2550
2447
|
end
|
2551
2448
|
end
|
@@ -2647,16 +2544,16 @@ module FeedTools
|
|
2647
2544
|
"http://www.sporkmonger.com/projects/feedtools")
|
2648
2545
|
if self.id != nil
|
2649
2546
|
unless FeedTools.is_uri? self.id
|
2650
|
-
|
2651
|
-
|
2652
|
-
|
2547
|
+
if self.link != nil
|
2548
|
+
xml_builder.id(FeedTools.build_urn_uri(self.link))
|
2549
|
+
else
|
2653
2550
|
raise "The unique id must be a valid URI."
|
2654
|
-
|
2551
|
+
end
|
2655
2552
|
else
|
2656
2553
|
xml_builder.id(self.id)
|
2657
2554
|
end
|
2658
|
-
|
2659
|
-
|
2555
|
+
elsif self.link != nil
|
2556
|
+
xml_builder.id(FeedTools.build_urn_uri(self.link))
|
2660
2557
|
else
|
2661
2558
|
raise "Cannot build feed, missing feed unique id."
|
2662
2559
|
end
|
@@ -2880,6 +2777,9 @@ module FeedTools
|
|
2880
2777
|
# Returns a REXML Document of the xml_data
|
2881
2778
|
def xml
|
2882
2779
|
if @xml_doc.nil?
|
2780
|
+
# TODO: :ignore_whitespace_nodes => :all
|
2781
|
+
# Add that?
|
2782
|
+
# ======================================
|
2883
2783
|
@xml_doc = Document.new(xml_data)
|
2884
2784
|
end
|
2885
2785
|
return @xml_doc
|
@@ -2984,10 +2884,7 @@ module FeedTools
|
|
2984
2884
|
if @description.nil?
|
2985
2885
|
unless root_node.nil?
|
2986
2886
|
repair_entities = false
|
2987
|
-
description_node = XPath.first(root_node, "
|
2988
|
-
if description_node.nil?
|
2989
|
-
description_node = XPath.first(root_node, "content:encoded")
|
2990
|
-
end
|
2887
|
+
description_node = XPath.first(root_node, "content:encoded")
|
2991
2888
|
if description_node.nil?
|
2992
2889
|
description_node = XPath.first(root_node, "content")
|
2993
2890
|
end
|
@@ -3000,6 +2897,9 @@ module FeedTools
|
|
3000
2897
|
if description_node.nil?
|
3001
2898
|
description_node = XPath.first(root_node, "body")
|
3002
2899
|
end
|
2900
|
+
if description_node.nil?
|
2901
|
+
description_node = XPath.first(root_node, "description")
|
2902
|
+
end
|
3003
2903
|
if description_node.nil?
|
3004
2904
|
description_node = XPath.first(root_node, "tagline")
|
3005
2905
|
end
|
@@ -4178,7 +4078,7 @@ module FeedTools
|
|
4178
4078
|
xml_builder.tag!("dc:date", time.iso8601)
|
4179
4079
|
end
|
4180
4080
|
unless tags.nil? || tags.size == 0
|
4181
|
-
xml_builder.tag!("
|
4081
|
+
xml_builder.tag!("taxo:topics") do
|
4182
4082
|
xml_builder.tag!("rdf:Bag") do
|
4183
4083
|
for tag in tags
|
4184
4084
|
xml_builder.tag!("rdf:li", tag)
|
@@ -4205,7 +4105,7 @@ module FeedTools
|
|
4205
4105
|
xml_builder.pubDate(time.rfc822)
|
4206
4106
|
end
|
4207
4107
|
unless tags.nil? || tags.size == 0
|
4208
|
-
xml_builder.tag!("
|
4108
|
+
xml_builder.tag!("taxo:topics") do
|
4209
4109
|
xml_builder.tag!("rdf:Bag") do
|
4210
4110
|
for tag in tags
|
4211
4111
|
xml_builder.tag!("rdf:li", tag)
|
data/rakefile
CHANGED
@@ -7,7 +7,7 @@ require 'rake/gempackagetask'
|
|
7
7
|
require 'rake/contrib/rubyforgepublisher'
|
8
8
|
|
9
9
|
PKG_NAME = 'feedtools'
|
10
|
-
PKG_VERSION = '0.2.
|
10
|
+
PKG_VERSION = '0.2.9'
|
11
11
|
PKG_FILE_NAME = "#{PKG_NAME}-#{PKG_VERSION}"
|
12
12
|
|
13
13
|
RELEASE_NAME = "REL #{PKG_VERSION}"
|
@@ -59,6 +59,7 @@ spec = Gem::Specification.new do |s|
|
|
59
59
|
end
|
60
60
|
|
61
61
|
s.add_dependency('activerecord', '>= 1.10.1')
|
62
|
+
s.add_dependency('uuidtools', '>= 0.1.1')
|
62
63
|
|
63
64
|
s.require_path = 'lib'
|
64
65
|
s.autorequire = 'feed_tools'
|
metadata
CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.8.11
|
|
3
3
|
specification_version: 1
|
4
4
|
name: feedtools
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 0.2.
|
7
|
-
date: 2005-09-
|
6
|
+
version: 0.2.9
|
7
|
+
date: 2005-09-25 00:00:00 -04:00
|
8
8
|
summary: "Parsing, generation, and caching system for xml news feeds."
|
9
9
|
require_paths:
|
10
10
|
- lib
|
@@ -33,6 +33,7 @@ files:
|
|
33
33
|
- install.rb
|
34
34
|
- README
|
35
35
|
- CHANGELOG
|
36
|
+
- lib/database_feed_cache.rb
|
36
37
|
- lib/feed_tools
|
37
38
|
- lib/feed_tools.rb
|
38
39
|
- lib/feed_tools/vendor
|
@@ -96,4 +97,14 @@ dependencies:
|
|
96
97
|
- ">="
|
97
98
|
- !ruby/object:Gem::Version
|
98
99
|
version: 1.10.1
|
100
|
+
version:
|
101
|
+
- !ruby/object:Gem::Dependency
|
102
|
+
name: uuidtools
|
103
|
+
version_requirement:
|
104
|
+
version_requirements: !ruby/object:Gem::Version::Requirement
|
105
|
+
requirements:
|
106
|
+
-
|
107
|
+
- ">="
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: 0.1.1
|
99
110
|
version:
|