KeeperPat-feedupdater 0.2.6

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG ADDED
@@ -0,0 +1,21 @@
1
+ == FeedUpdater 0.2.6
2
+ * Updated for compatibility with RubyGems >= 1.0
3
+ == FeedUpdater 0.2.5
4
+ * fixed bug with redefinition of file searching system
5
+ == FeedUpdater 0.2.4
6
+ * added more code for detecting the location of the config file
7
+ == FeedUpdater 0.2.3
8
+ * added additional logging messages
9
+ == FeedUpdater 0.2.2
10
+ * better distribution of work across threads
11
+ * fixed major threading bug
12
+ * added configuration variable for sleep time
13
+ == FeedUpdater 0.2.1
14
+ * no longer attempts to update feeds that have been updated very recently
15
+ * fixed logging levels
16
+ * added on_begin block
17
+ == FeedUpdater 0.2.0
18
+ * multithreaded
19
+ * unchanged feeds will no longer call on_update
20
+ == FeedUpdater 0.1.0
21
+ * initial version
data/README ADDED
@@ -0,0 +1,34 @@
1
+ The FeedUpdater is a simple daemon for handling the automatic updating of
2
+ FeedTools feed objects.
3
+
4
+ USAGE: feed_updater <subcommand>
5
+
6
+ Subcommands:
7
+ start
8
+ stop
9
+ restart
10
+ install
11
+
12
+ The FeedUpdater daemon is very easy to use, especially if you're using it
13
+ with a Rails application. If you're going to be using it with a Rails app,
14
+ simply install the feedupdater gem, navigate to your Rails app, and run
15
+ the 'feed_updater install' command. This will install FeedUpdater. Then
16
+ edit the feed_updater.yml config file as necessary. You will probably need
17
+ to define a custom updater class, which should probably go in your lib
18
+ directory. It's recommended that you use the example/custom_updater.rb file
19
+ as a starting point. You should using the updater events to copy any
20
+ required fields to feed subscription tables or item tables as necessary so
21
+ that a full feed parse isn't required every time the feed is displayed.
22
+
23
+ The config file also has a start delay option. This should almost always be
24
+ set to true. You should only turn it off when you are debugging a custom
25
+ updater class, and it should probably never be turned off in production.
26
+ Keeping it on prevents FeedUpdater from hitting the CPU too hard immediately
27
+ after a server reboot, and also prevents hundreds of update processes from
28
+ kicking off simultaneously on a shared server.
29
+
30
+ If you chose to use FeedUpdater outside a Rails application, you should try
31
+ to use a similar directory structure to what would be found in a Rails
32
+ setup. FeedUpdater will usually look in the current directory if it cannot
33
+ find a file its looking for though, so if FeedUpdater can't find a file it
34
+ needs, changing directories will probably fix the problem.
data/bin/feed_updater ADDED
@@ -0,0 +1,317 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ #--
4
+ # Copyright (c) 2005 Robert Aman
5
+ #
6
+ # Permission is hereby granted, free of charge, to any person obtaining
7
+ # a copy of this software and associated documentation files (the
8
+ # "Software"), to deal in the Software without restriction, including
9
+ # without limitation the rights to use, copy, modify, merge, publish,
10
+ # distribute, sublicense, and/or sell copies of the Software, and to
11
+ # permit persons to whom the Software is furnished to do so, subject to
12
+ # the following conditions:
13
+ #
14
+ # The above copyright notice and this permission notice shall be
15
+ # included in all copies or substantial portions of the Software.
16
+ #
17
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24
+ #++
25
+
26
+ if RUBY_PLATFORM =~ /mswin/
27
+ puts "FeedUpdater is not supported on Windows due to a lack of fork()."
28
+ exit
29
+ end
30
+
31
+ # :stopdoc:
32
+ # ROFLCOPTERS?
33
+ # This mainly exists because of the approximately 1 billion different
34
+ # ways to deploy this script.
35
+ class FileStalker
36
+ def self.hunt(paths)
37
+ for path in paths
38
+ if File.exists?(File.expand_path(path))
39
+ return File.expand_path(path)
40
+ elsif File.exists?(File.expand_path(
41
+ File.dirname(__FILE__) + path))
42
+ return File.expand_path(File.dirname(__FILE__) + path)
43
+ elsif File.exists?(File.expand_path(
44
+ File.dirname(__FILE__) + "/" + path))
45
+ return File.expand_path(File.dirname(__FILE__) + "/" + path)
46
+ end
47
+ end
48
+ return nil
49
+ end
50
+ end
51
+ # :startdoc:
52
+
53
+ $:.unshift(FileStalker.hunt([
54
+ "/../vendor/feedupdater/lib",
55
+ "vendor/feedupdater/lib",
56
+ "../lib"]))
57
+ $:.uniq!
58
+
59
+ require 'yaml'
60
+ require 'feed_updater'
61
+
62
+ if ARGV[0].nil?
63
+ # Exit quickly if no command line arguments given.
64
+
65
+ feed_updater_version = FeedTools::FEED_UPDATER_VERSION::STRING
66
+ feed_tools_version = "<error: not loaded>"
67
+ if defined?(FeedTools::FEED_TOOLS_VERSION::STRING)
68
+ feed_tools_version = FeedTools::FEED_TOOLS_VERSION::STRING
69
+ elsif defined?(FEED_TOOLS_VERSION)
70
+ feed_tools_version = FEED_TOOLS_VERSION
71
+ end
72
+ puts ""
73
+ puts "FeedUpdater #{feed_updater_version} / FeedTools #{feed_tools_version}"
74
+ puts "USAGE: feed_updater <subcommand>"
75
+ puts ""
76
+ puts "Subcommands:"
77
+ puts " start"
78
+ puts " This will start the daemon if it hasn't already been started."
79
+ puts ""
80
+ puts " stop"
81
+ puts " This will stop the daemon if it's already running."
82
+ puts ""
83
+ puts " restart"
84
+ puts " This will restart the daemon."
85
+ puts ""
86
+ puts " install"
87
+ puts " If the current directory is a Rails installation, this will"
88
+ puts " install FeedUpdater into the vendor folder and add a new script"
89
+ puts " to the scripts/ directory for running FeedUpdater. Rerunning"
90
+ puts " the install subcommand will update the files against the latest"
91
+ puts " version of the FeedUpdater gem file you have installed. Rails"
92
+ puts " is NOT required to use FeedUpdater."
93
+ puts ""
94
+ exit
95
+ elsif ARGV[0] == "install"
96
+ rails_root = nil
97
+ install_vendor_directory = nil
98
+ install_config_directory = nil
99
+ install_script_directory = nil
100
+
101
+ current_directory = File.expand_path(".")
102
+ loop do
103
+ entries = Dir.entries(current_directory)
104
+ if entries.include?("vendor") &&
105
+ entries.include?("config") &&
106
+ entries.include?("script")
107
+ rails_root = current_directory
108
+ break
109
+ else
110
+ break if current_directory == "/"
111
+ current_directory = File.expand_path(current_directory + "/..")
112
+ end
113
+ end
114
+ if rails_root.nil?
115
+ puts "You must run the install command when the current directory is"
116
+ puts "a Rails application."
117
+ else
118
+ install_vendor_directory = File.expand_path(rails_root + "/vendor")
119
+ install_config_directory = File.expand_path(rails_root + "/config")
120
+ install_script_directory = File.expand_path(rails_root + "/script")
121
+
122
+ # Install FeedUpdater gem to application vendor directory
123
+ system("rm -rf #{install_vendor_directory}/feedupdater")
124
+ unpack_string = `gem unpack feedupdater`
125
+ feed_updater_version =
126
+ unpack_string.scan(/feedupdater\-(.*)\'/).flatten[0]
127
+ if feed_updater_version.nil? || feed_updater_version == ""
128
+ puts "You need to have the feedupdater gem installed for the install"
129
+ puts "subcommand to run correctly."
130
+ exit
131
+ end
132
+ puts "Installing FeedUpdater #{feed_updater_version} " +
133
+ "to vendor directory..."
134
+
135
+ system("cp -rp feedupdater-#{feed_updater_version} " +
136
+ "#{install_vendor_directory}")
137
+ system("rm -rf feedupdater-#{feed_updater_version}")
138
+ system("mv #{install_vendor_directory}/" +
139
+ "feedupdater-#{feed_updater_version} " +
140
+ "#{install_vendor_directory}/feedupdater")
141
+
142
+ # Install FeedTools gem to application vendor directory
143
+ system("rm -rf #{install_vendor_directory}/feedtools")
144
+ unpack_string = `gem unpack feedtools`
145
+ feed_tools_version =
146
+ unpack_string.scan(/feedtools\-(.*)\'/).flatten[0]
147
+ if feed_tools_version.nil? || feed_tools_version == ""
148
+ puts "You need to have the feedtools gem installed for the install"
149
+ puts "subcommand to run correctly."
150
+ exit
151
+ end
152
+ puts "Installing FeedTools #{feed_tools_version} to vendor directory..."
153
+
154
+ system("cp -rp feedtools-#{feed_tools_version} " +
155
+ "#{install_vendor_directory}")
156
+ system("rm -rf feedtools-#{feed_tools_version}")
157
+ system("mv #{install_vendor_directory}/" +
158
+ "feedtools-#{feed_tools_version} " +
159
+ "#{install_vendor_directory}/feedtools")
160
+
161
+ # Copying the default config file to the config directory
162
+ if !File.exists?(File.expand_path(install_config_directory +
163
+ "/feed_updater.yml"))
164
+ puts "Installing default config file..."
165
+ config_file =
166
+ File.expand_path(File.dirname(__FILE__) + '/../config/feed_updater.yml')
167
+ system("cp -p #{config_file} #{install_config_directory}")
168
+ else
169
+ puts "Config file already exists, skipping..."
170
+ end
171
+
172
+ # Copying this executable to the script directory
173
+ puts "Copying executable to script directory..."
174
+ system("rm -rf #{install_script_directory}/feed_updater")
175
+ system("cp -p #{__FILE__} #{install_script_directory}")
176
+ system("chmod +x #{install_script_directory}/feed_updater")
177
+
178
+ puts "Use script/feed_updater to run FeedUpdater."
179
+ end
180
+ exit
181
+ end
182
+
183
+ config_file = FileStalker.hunt([
184
+ "../config/feed_updater.yml",
185
+ "./feed_updater.yml"
186
+ ])
187
+ # Reportedly, in some cases, the example config is found instead.
188
+ if config_file =~ /example/
189
+ config_file = FileStalker.hunt([
190
+ "../../../config/feed_updater.yml",
191
+ "../config/feed_updater.yml",
192
+ "./feed_updater.yml"
193
+ ])
194
+ end
195
+ if config_file.nil?
196
+ puts "Could not locate feed_updater.yml config file."
197
+ exit
198
+ end
199
+
200
+ config_hash = YAML.load(File.open(config_file, "r").read)
201
+ load_script_path = config_hash["load_script"]
202
+ if !load_script_path.nil?
203
+ result = FileStalker.hunt([
204
+ load_script_path,
205
+ File.dirname(config_file) + "/" + load_script_path,
206
+ File.dirname(config_file) + load_script_path,
207
+ File.dirname(__FILE__) + "/../" + load_script_path,
208
+ File.dirname(__FILE__) + "/.." + load_script_path
209
+ ])
210
+ if result.nil?
211
+ puts "Could not locate #{load_script_path.inspect} file."
212
+ exit
213
+ else
214
+ load_script_path = result
215
+ end
216
+ end
217
+
218
+ pid_file_path = config_hash["pid_file_path"]
219
+ if !pid_file_path.nil?
220
+ result = FileStalker.hunt([
221
+ pid_file_path,
222
+ File.dirname(config_file) + "/" + pid_file_path,
223
+ File.dirname(config_file) + pid_file_path,
224
+ File.dirname(__FILE__) + "/../" + pid_file_path,
225
+ File.dirname(__FILE__) + "/.." + pid_file_path,
226
+ "../" + pid_file_path
227
+ ])
228
+ pid_file_path = result if !result.nil?
229
+ else
230
+ result = FileStalker.hunt([
231
+ File.dirname(__FILE__) + "/../config",
232
+ "./config",
233
+ File.dirname(__FILE__) + "/config"
234
+ ])
235
+ pid_file_path = result if !result.nil?
236
+ end
237
+
238
+ log_file_path = config_hash["log_file_path"]
239
+ if !log_file_path.nil?
240
+ result = FileStalker.hunt([
241
+ log_file_path,
242
+ File.dirname(config_file) + "/" + log_file_path,
243
+ File.dirname(config_file) + log_file_path,
244
+ File.dirname(__FILE__) + "/../" + log_file_path,
245
+ File.dirname(__FILE__) + "/.." + log_file_path,
246
+ "../" + log_file_path
247
+ ])
248
+ log_file_path = result if !result.nil?
249
+ else
250
+ result = FileStalker.hunt([
251
+ File.dirname(__FILE__) + "/../log",
252
+ "./log",
253
+ File.dirname(__FILE__) + "/log",
254
+ File.dirname(__FILE__) + "/../logs",
255
+ "./logs",
256
+ File.dirname(__FILE__) + "/logs"
257
+ ])
258
+ log_file_path = result if !result.nil?
259
+ end
260
+
261
+ script_class = nil
262
+ existing_subclasses = []
263
+ ObjectSpace.each_object do |instance|
264
+ if instance.class.name == "Class" &&
265
+ instance.ancestors.include?(FeedTools::FeedUpdater)
266
+ existing_subclasses << instance
267
+ end
268
+ end
269
+ load(load_script_path)
270
+ loaded_subclasses = []
271
+ ObjectSpace.each_object do |instance|
272
+ if instance.class.name == "Class" &&
273
+ instance.ancestors.include?(FeedTools::FeedUpdater)
274
+ loaded_subclasses << instance
275
+ end
276
+ end
277
+ script_classes = (loaded_subclasses - existing_subclasses)
278
+ if script_classes.size == 0
279
+ puts "There do not appear to be any subclasses of FeedTools::FeedUpdater."
280
+ exit
281
+ elsif script_classes.size > 1
282
+ puts "There appear to be multiple subclasses of FeedTools::FeedUpdater."
283
+ exit
284
+ else
285
+ script_class = script_classes[0]
286
+ end
287
+
288
+ updater = nil
289
+ if load_script_path.nil?
290
+ updater = FeedTools::FeedUpdater.new
291
+ FeedTools::FeedUpdater.on_update do |feed, seconds|
292
+ updater.logger.info("Loaded '#{feed.href}'.")
293
+ updater.logger.info("=> Updated (#{feed.title}) in #{seconds} seconds.")
294
+ end
295
+ FeedTools::FeedUpdater.on_error do |href, error|
296
+ updater.logger.info("Error updating '#{href}':")
297
+ updater.logger.info(error)
298
+ end
299
+ else
300
+ updater = script_class.new
301
+ end
302
+
303
+ for key in config_hash.keys
304
+ key_sym = key.to_s.to_sym
305
+ updater.updater_options[key_sym] = config_hash[key]
306
+ end
307
+ updater.pid_file_dir = pid_file_path
308
+ updater.log_file_dir = log_file_path
309
+
310
+ case ARGV[0]
311
+ when "start"
312
+ updater.start()
313
+ when "stop"
314
+ updater.stop()
315
+ when "restart"
316
+ updater.restart()
317
+ end
@@ -0,0 +1,22 @@
1
+ # This ensures that you don't break shared servers.
2
+ start_delay: false
3
+
4
+ # This is the path to the custom handler for updated feeds.
5
+ # See the documentation for details.
6
+ load_script: example/custom_updater.rb
7
+
8
+ # Keep this set to 1 unless you're certain you need to set it higher.
9
+ # Never set it higher than 1 if you're on a shared server.
10
+ threads: 5
11
+
12
+ # The amount of time to sleep between updates. Expressed in minutes.
13
+ sleep_time: 65
14
+
15
+ # This is the path to store the pid files.
16
+ pid_file_path: config
17
+
18
+ # This is the path to store the log files.
19
+ log_file_path: log
20
+
21
+ # Log level
22
+ log_level: 0
@@ -0,0 +1,24 @@
1
+ class CustomUpdater < FeedTools::FeedUpdater
2
+ on_begin do
3
+ # self.feed_href_list = [
4
+ # "http://www.gigaom.com/feed/rss2/",
5
+ # "http://feeds.feedburner.com/ManeuverMarketingCommunique",
6
+ # "http://www.afp.com/english/rss/stories.xml",
7
+ # "http://www.railheaddesign.com/rss/railhead.xml",
8
+ # "http://www.nateanddi.com/rssfeed.xml"
9
+ # ]
10
+ end
11
+
12
+ on_update do |feed, seconds|
13
+ self.logger.info("Loaded '#{feed.href}'.")
14
+ self.logger.info("=> Updated (#{feed.title}) in #{seconds} seconds.")
15
+ end
16
+
17
+ on_error do |href, error|
18
+ self.logger.info("Error updating '#{href}':")
19
+ self.logger.info(error)
20
+ end
21
+
22
+ on_complete do |updated_feed_hrefs|
23
+ end
24
+ end