[Opda-develop] OPDA/app/controllers opml_feeds_controller.rb, 1.2, 1.3
Brought to you by:
digitalpodcast
|
From: Alex N. <dig...@us...> - 2006-07-24 04:13:28
|
Update of /cvsroot/opda/OPDA/app/controllers In directory sc8-pr-cvs3.sourceforge.net:/tmp/cvs-serv990/app/controllers Added Files: opml_feeds_controller.rb Log Message: Moved opml_feeds out of admin --- NEW FILE: opml_feeds_controller.rb --- require 'uri' require 'open-uri' require 'rexml/document' include REXML class OpmlFeedsController < ApplicationController layout "layouts/default" @logger = Logger.new($stdout, shift_age = 7, shift_size = 1048576) def index list render :action => 'list' end # TODO, the list should be user subscriptions. def list @opml_feed_pages, @opml_feeds = paginate :opml_feeds, :per_page => 10 end def show @opml_feed = OpmlFeed.find(params[:id]) end def new # @opml_feed = OpmlFeed.new end # # Create a new OPML Entry. # It is assumed that the form parameters is a # multipart submission. # # def create opml_feed = OpmlFeed.new src_filename = params[:file] opml_feed.title = params['opml']['title'] opml_feed.opml_url = params['opml']['url'] logger.info "received" + opml_feed.title logger.info "received" + opml_feed.opml_url parsefile = false if !opml_feed.opml_url.empty? begin uri = URI::parse(opml_feed.opml_url) rescue URI::InvalidURIError => error # We assume it's a file name. log_error(error) logger.info("Will parse OPML as file.") parsefile = true end else logger.info("Will parse OPML as file.") parsefile = true end # Parsing of a file is OK, when the the OPML_URL is not provided. # if parsefile if src_filename && !src_filename.original_filename.empty? # src_filename = sanitize(src_filename) hashed_name = Digest::SHA1.hexdigest(Time.now.to_s) filename = "#{RAILS_ROOT}/public/upload/" + hashed_name + "_" + src_filename.original_filename if File.open(filename, 'w'){ |f| f.write(src_filename.read) } end opml_feed.opml_url = filename end end opml_feed.save if parse(opml_feed, parsefile) flash[:notice] = 'OpmlFeed was successfully created.' redirect_to :action => 'list' else render :action => 'new' end end def edit @opml_feed = OpmlFeed.find(params[:id]) end def update @opml_feed = OpmlFeed.find(params[:id]) if @opml_feed.update_attributes(params[:opml_feed]) flash[:notice] = 'OpmlFeed was successfully updated.' redirect_to :action => 'show', :id => @opml_feed else render :action => 'edit' end end def destroy OpmlFeed.find(params[:id]).destroy redirect_to :action => 'list' end def destroy_all @opml_feeds = OpmlFeed.find_all @opml_feeds.each do |opml| opml.destroy end redirect_to :action => 'destroy_result' end def destroy_result end ########################################################################### # The parse action takes a link to an opml field and reads in the file # it then sets up the new opml link in the DB and establishes a # Subscription List for the opml list. Once this has been set up it calls # parse_opml() to do the actual parsing of the opml file ########################################################################### def parse(feed, mode) #Get OPML file file = nil if mode begin file = File.new(feed.opml_url) rescue => error logger.info "Error: The file can not be accessed" + feed.opml_url log_error(error) end else open(feed.opml_url) { |http| file = http.read } if !file end begin # Read it into the opml variable opml = REXML::Document.new(file) logger.info "XML parsing file successfull" rescue => error log_error(error) end # If the opml file is ok, set up a DB entry and establsh a # subscription list for the file to keep track of categories begin if opml @opmlEntry = OpmlFeed.new @opmlEntry.opml_url = feed.opml_url if (feed.link_url && feed.link_url != "") @opmlEntry.link_url = feed.link_url else # TODO: fix getting website address # FIXME doesn't work with file names! get this from the opml itself @opmlEntry.link_url = "http://" + feed.opml_url.gsub(/https?:\/\/(www.)?/, '').gsub(/\/(.*)/, '') end #FIXME, should be model validation instead testing the value here. if (feed.title && feed.title != "") @opmlEntry.title = feed.title else @opmlEntry.title = opml.elements['opml/head/title'].text end @opmlEntry.user_id = session[:user].id if session[:user] #Christophe TODO, why getting the entry if we created one already? # if !OpmlFeed.find_by_opml_url(feed.opml_url) if (@opmlEntry.save) @opmlEntry.reload logger.info "OPML: Entry creater" + @opmlEntry.title end else @opmlEntry = OpmlFeed.find_by_opml_url(feed.opml_url) end # CHRISTOPHE: The expression below uses condition, but special find mehotds exist. # @sublist = SubscriptionList.find(:all, :conditions => ["opml_feed_id=?", @opmlEntry.id]) # Fix a new generic subscription for this user. # If the subscription alread contains the opml_feed_id for this user # we skip this process. @user = User.find(session[:user].id) if session[:user] if !@user raise # We can tie in a OPML feed, if there is no user hence subscrition list. end @root = @user.subscription_lists.find(:first, :conditions => "parent_id = 0") # TODO Christophe why, select on OPML_Feed id?? # if !@sublist # @sublist = # end # if @root # @sublist = @rootlist.find_all_by_opml_feed_id_(@opmlEntry.id]) # if @sublist #TODO, Decide to implement a conditional check, could a validation section in model # rather!. # raise # We need to exit if this OPMLEntry is already defined for this user. # end parent_id = @root.id else parent_id = 0 end @sublist = SubscriptionList.new(:parent_id => parent_id) # TODO: fix title on subscription list to be equal to opml title @sublist.opml_feed_id = @opmlEntry.id @sublist.title = @opmlEntry.title @sublist.user_id = session[:user].id if session[:user] @sublist.reload if @sublist.save # send opml file to be parsed - sets root to opml/body, and passes in sublist.id # and opmlEntry.id as additional parameters to keep track of where # we are in the subscription list tree logger.info "Start parsing OPML tags" parse_opml(opml.elements["opml/body"], @sublist.id , @opmlEntry.id) end rescue => error log_error(error) end end #################################################################### # parse the opml file # takes the base to be parsed, the parent_id for this node in the subscription # list and the id of the original opml file to associate this link to ################################################################### def parse_opml(opml_node, parent_id, opml_id) begin # get the first outline entry in the opml and start to iterate through # the outline elements opml_node.elements.each('outline') { |el| # if the element contains sub elements this means we have a new category # so set up the subcategory in the subscription list and call the parser again # this is a recursive process to get all the categories into the subscription list # tree if (el.elements.size != 0) # TODO: what happens if there is already a subscription list and this is an update @sublist = SubscriptionList.new(:parent_id => parent_id) # TODO: fix title on subscription list to be equal to opml title @sublist.opml_feed_id = opml_id @sublist.user_id = session[:user].id if session[:user] @sublist.title = el.attributes["text"] @sublist.reload if @sublist.save parse_opml(el, @sublist.id, opml_id) # if there are no sub elements we must have a link to something # it might be in an attribute called url or xmlUrl # check for the link and set url to equal what we find elsif (el.attributes['url'] || el.attributes['xmlUrl']) url = el.attributes['url'] if (el.attributes['url']) url = el.attributes['xmlUrl'] if (el.attributes['xmlUrl']) title = el.attributes['text'] logger.info "Outline tag, url=" + url # then if the link matches an existing channel just add tags for # the opml category and push the channel onto the opml join and # subscription list joins if (Channel.find_by_feed_url_and_title(url, title)) @channel = Channel.find_by_feed_url(url) @channel.tag(@sublist.title, :separator => ',') @channel.opml_feeds << @opmlEntry @channel.subscription_lists << @sublist # if we don't match both the url and the title # add a new channel, add tags, and connect the join tables elsif (!Channel.find_by_feed_url(url) && !Channel.find_by_title(title)) @channel = Channel.new @channel.suspended = 1 @channel.feed_url = url @channel.title = title @channel.user_id = 1 # TODO: fix user id for new channel @channel.tag(@sublist.title, :separator => ',') @opmlEntry.channels << @channel @sublist.channels << @channel # and what do we do if we have a duplicate # of either the url but not the title, or of the title but not the # url else # TODO: flag as potential duplicate, but have some type of data error end end } rescue => error text = "parsing problem" end end end |