#!/opt/local/bin/ruby # $Id$ # $URL$ # # Copyright (c) 2006 Ward Wouts # # Permission to use, copy, modify, and distribute this software for any # purpose with or without fee is hereby granted, provided that the above # copyright notice and this permission notice appear in all copies. # # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. # ######################################## # the configuration bit @podcasts = { # the podcast name "distortedview" => { # where's the rss file "rss" => 'http://www.distortedview.com/show/index.xml', # where should enclosures be saved "savedir" => '/Users/ward/Private/mp3/[books]/Distorted View', # rename magic, this is used on the file name with sub! "rename" => [ /_(\d\d\d\d)(\d\d)/, '\2\1' ], # directory to put symlinks to the new files "linkdir" => '/Users/ward/ipod_sync/[books]/Distorted View', }, "tagesschau" => { "rss" => 'http://www.tagesschau.de/export/podcast', "savedir" => '/Users/ward/ipod_sync/[books]/Tagesschau', # delete files that aren't in the rss anylonger "delete" => true, }, } ######################################## # code from here on require 'net/http' require 'uri' require 'rexml/document' def fetch(uri_str, limit = 10) # You should choose better exception. raise ArgumentError, 'HTTP redirect too deep' if limit == 0 response = Net::HTTP.get_response(URI.parse(uri_str)) case response when Net::HTTPSuccess then response when Net::HTTPRedirection then fetch(response['location'], limit - 1) else response.error! end end def deleteold(podcast) Dir.open(@podcasts[podcast]["savedir"]).each {|entry| if File.file?("#{@podcasts[podcast]["savedir"]}/#{entry}") && ! @filelist[entry] puts " deleting #{entry}" File.unlink("#{@podcasts[podcast]["savedir"]}/#{entry}") end } end def getenclosure(podcast, enclosure) if ! enclosure.attribute("url").nil? cast = enclosure.attribute("url").to_s.dup filename = cast.dup filename.sub!(/^.*\//, "") if @podcasts[podcast]["rename"] filename.sub!(@podcasts[podcast]["rename"][0], @podcasts[podcast]["rename"][1]) end @filelist[filename] = true if ! File.exists?("#{@podcasts[podcast]["savedir"]}/#{filename}") puts " getting #{@podcasts[podcast]["savedir"]}/#{filename}" response = fetch(cast) File.open("#{@podcasts[podcast]["savedir"]}/#{filename}", "w"){|f| f.print(response.body) } if @podcasts[podcast]["linkdir"] File.symlink("#{@podcasts[podcast]["savedir"]}/#{filename}", "#{@podcasts[podcast]["linkdir"]}/#{filename}") end end end end for podcast in @podcasts.keys.sort puts podcast res = fetch(@podcasts[podcast]["rss"]) @filelist = {} xmldoc = REXML::Document.new(res.body) xmldoc.elements.each("rss/channel/*/enclosure") {|enclosure| getenclosure(podcast, enclosure) } if @podcasts[podcast]["delete"] deleteold(podcast) end end