# COPYRIGHT: 2007 Brent Beardsley (brentbeardsley@gmail.com) # LICENSE: MIT module RssListHelper @@rss_list_cache = {} ['RSS_LIST_PARAMETERS', 'EBAY_CATEGORIES', 'DIGG_TOPICS'].each do |const_name| self.send(:remove_const, const_name.to_sym) if self.const_defined?(const_name) end RSS_LIST_PARAMETERS = [:count, :class, :cache, :ul, :li, :reverse, :separator, :links] EBAY_CATEGORIES = {"Toys & Hobbies"=>"220", "Computers & Networking"=>"58058", "Cell Phones & PDAs"=>"15032", "Baby"=>"2984", "Crafts"=>"14339", "Business & Industrial"=>"12576", "Jewelry & Watches"=>"281", "Consumer Electronics"=>"293", "Real Estate"=>"10542", "Art"=>"550", "Books"=>"267", "Travel"=>"3252", "Sporting Goods"=>"382", "Specialty Services"=>"316", "Pottery & Glass"=>"870", "Health & Beauty"=>"26395", "Home & Garden"=>"11700", "Gift Certificates"=>"31411", "Collectibles"=>"1", "Video Games"=>"1249", "Sports Mem, Cards & Fan Shop"=>"64482", "Entertainment Memorabilia"=>"45100", "Dolls & Bears"=>"237", "Clothing, Shoes & Accessories"=>"11450", "Tickets"=>"1305", "All Categories"=>"-1", "Stamps"=>"260", "Music"=>"11233", "eBay Motors"=>"6000", "Coins & Paper Money"=>"11116", "Antiques"=>"20081", "Everything Else"=>"99", "Musical Instruments"=>"619", "DVDs & Movies"=>"11232", "Cameras & Photo"=>"625"} DIGG_TOPICS = {"Xbox 360"=>"http://digg.com/rss/indexxbox_360.xml", "Television"=>"http://digg.com/rss/indextelevision.xml", "Political News"=>"http://digg.com/rss/indexpolitics.xml", "Business & Finance"=>"http://digg.com/rss/indexbusiness_finance.xml", "General Sciences"=>"http://digg.com/rss/indexgeneral_sciences.xml", "Tech Deals"=>"http://digg.com/rss/indextech_deals.xml", "Music Videos"=>"http://digg.com/rss/indexvideos_music.xml", "PlayStation 3"=>"http://digg.com/rss/indexplaystation_3.xml", "Nintendo Wii"=>"http://digg.com/rss/indexnintendo_wii.xml", "World News"=>"http://digg.com/rss/indexworld_news.xml", "Design"=>"http://digg.com/rss/indexdesign.xml", "Gaming Videos"=>"http://digg.com/rss/indexvideos_gaming.xml", "Comedy Videos"=>"http://digg.com/rss/indexvideos_comedy.xml", "Animation Videos"=>"http://digg.com/rss/indexvideos_animation.xml", "All Videos Topics"=>"http://digg.com/rss/containervideos.xml", "Soccer"=>"http://digg.com/rss/indexsoccer.xml", "Motorsport"=>"http://digg.com/rss/indexmotorsport.xml", "Golf"=>"http://digg.com/rss/indexgolf.xml", "All Technology Topics"=>"http://digg.com/rss/containertechnology.xml", "Gaming Industry News"=>"http://digg.com/rss/indexgaming_news.xml", "All Gaming Topics"=>"http://digg.com/rss/containergaming.xml", "Security"=>"http://digg.com/rss/indexsecurity.xml", "Tech Industry News"=>"http://digg.com/rss/indextech_news.xml", "Tennis"=>"http://digg.com/rss/indextennis.xml", "Extreme"=>"http://digg.com/rss/indexextreme_sports.xml", "Basketball"=>"http://digg.com/rss/indexbasketball.xml", "Mods"=>"http://digg.com/rss/indexmods.xml", "Sports Videos"=>"http://digg.com/rss/indexvideos_sports.xml", "Playable Web Games"=>"http://digg.com/rss/indexplayable_web_games.xml", "Movies"=>"http://digg.com/rss/indexmovies.xml", "Celebrity"=>"http://digg.com/rss/indexcelebrity.xml", "Hockey"=>"http://digg.com/rss/indexhockey.xml", "Offbeat News"=>"http://digg.com/rss/indexoffbeat_news.xml", "US Elections 2008"=>"http://digg.com/rss/index2008_us_elections.xml", "All World & Business Topics"=>"http://digg.com/rss/containerworld_business.xml", "Software"=>"http://digg.com/rss/indexsoftware.xml", "Programming"=>"http://digg.com/rss/indexprogramming.xml", "Microsoft"=>"http://digg.com/rss/indexmicrosoft.xml", "Linux/Unix"=>"http://digg.com/rss/indexlinux_unix.xml", "Gadgets"=>"http://digg.com/rss/indexgadgets.xml", "Other Sports"=>"http://digg.com/rss/indexother_sports.xml", "Environment"=>"http://digg.com/rss/indexenvironment.xml", "Hardware"=>"http://digg.com/rss/indexhardware.xml", "Apple"=>"http://digg.com/rss/indexapple.xml", "People Videos"=>"http://digg.com/rss/indexvideos_people.xml", "Educational Videos"=>"http://digg.com/rss/indexvideos_educational.xml", "PC Games"=>"http://digg.com/rss/indexpc_games.xml", "Music"=>"http://digg.com/rss/indexmusic.xml", "All Entertainment Topics"=>"http://digg.com/rss/containerentertainment.xml", "American & Canadian Football"=>"http://digg.com/rss/indexfootball.xml", "Baseball"=>"http://digg.com/rss/indexbaseball.xml", "Political Opinion"=>"http://digg.com/rss/indexpolitical_opinion.xml", "All Science Topics"=>"http://digg.com/rss/containerscience.xml", "All Sports Topics"=>"http://digg.com/rss/containersports.xml", "Health"=>"http://digg.com/rss/indexhealth.xml", "Space"=>"http://digg.com/rss/indexspace.xml"} # rss_list is a helper to create an unordered list of urls from a rss feed. # Options are: # :class => 'your css class' applied to the tags (defaults to 'rss_list') # :count => a number (defaults to 5) # :cache => true or false so that the feed won't be queried everytime the helper is called (defaults to true) # :ul => true or false so the ul tag will not be added (defaults to true) # :li => true or false so the li tag will not be added (defaults to true) # :reverse => true or false so the order of the items is reversed (defaults to false) # :separator => ' | ' put between the items (defaults to nil - useful when :ul and :li are false) # :links => true or false so titles are linked or not (defaults to true) def rss_list(rss_url, options = {}, &block) require 'open-uri' require 'digest/sha1' begin require 'hpricot' rescue LoadError return tag(:div, :class => 'rss_list_error') { "Hpricot needs to be installed (gem install hpricot) to use rss_list" } end options[:count] ||= 5 options[:class] = 'rss_list' unless options.has_key?(:class) options[:cache] = true unless options.has_key?(:cache) options[:ul] = true unless options.has_key?(:ul) options[:li] = true unless options.has_key?(:li) options[:links] = true unless options.has_key?(:links) cache_key = Digest::SHA1.hexdigest(rss_url + '|' + options.to_a.collect { |a| a.join('=') }.sort.flatten.join('|')).hex.to_s if @@rss_list_cache[cache_key] return @@rss_list_cache[cache_key] if options[:cache] end # print "getting rss feed: #{rss_url}\n" items = [] doc = Hpricot.XML(Kernel.open(rss_url)) (doc/:item).each do |item| the_title = (item/:title).inner_html; the_link = (item/:link).inner_html items << { :title => the_title, :link => the_link, :element => item } end (doc/:entry).each do |item| the_title = (item/:title).inner_html; the_link = nil (item/:link).each do |link_element| if link_element.attributes['rel'] == 'alternate' && link_element.attributes['type'] == 'text/html' the_link = link_element.attributes['href'] end end items << { :title => the_title, :link => the_link, :element => item } end items.reverse! if options[:reverse] output = ""; i = 0 items.each do |item| break if i >= options[:count] item[:title].gsub!(/(^$)/, '') item[:link].gsub!(/(^$)/, '') output << "#{options[:separator]}" if i != 0 && options[:separator] && !options[:ul] && !options[:li] link_output = "" if block_given? link_output = yield(item) else if options[:links] link_output << link(item[:title], item[:link]) else link_output << item[:title] end end if options[:li] || options[:ul] output << " " + tag(:li) { link_output } + "\n" else output << " " + link_output + "\n" end i += 1 end output = tag(:ul, :class => options[:class]) { "\n" + output} if options[:ul] @@rss_list_cache[cache_key] = output if options[:cache] output end # delicious_list is a helper to create an unordered list of urls from delicious. # what => one of :hot, :popular, :recent, :user, :subscriptions, or :network # Options are: # :tags => 'yourtag' is optional for :popular, :recent, and :user # :user => 'username' is required for :what => one of :user, :subscriptions, and :network # :class => 'your css class' applied to the tags (defaults to 'delicious') # :count => a number (defaults to 5) # :cache => true or false so that delicious won't be queried everytime the helper is called (defaults to true) # :ul => true or false so the ul tag will not be added (defaults to true) # :li => true or false so the li tag will not be added (defaults to true) # :reverse => true or false so the order of the items is reversed (defaults to false) # :separator => ' | ' put between the items (defaults to nil - useful when :ul and :li are false) # :links => true or false so titles are linked or not (defaults to true) def delicious_list(what = :hot, options = {}) if what.is_a?(Hash) options = what what = :hot end options[:class] = 'delicious' unless options.has_key?(:class) rss_url = case what when :popular then "http://del.icio.us/rss/popular/#{options[:tags]}" when :recent then "http://del.icio.us/rss/recent/#{options[:tags]}" when :user then "http://del.icio.us/rss/#{options[:user]}/#{options[:tags]}" when :subscriptions then "http://del.icio.us/rss/subscriptions/#{options[:user]}" when :network then "http://del.icio.us/rss/network/#{options[:user]}" else "http://del.icio.us/rss/" end rss_options = {} RSS_LIST_PARAMETERS.each do |key| rss_options[key] = options[key] if options.has_key?(key) end rss_list(rss_url, rss_options) end # flickr_list is a helper to create an unordered list of urls and images from flickr. # what => one of :public, :friends, :activity, :comments, :news, :forums, :group_discussion, :group_pool # See http://www.flickr.com/services/feeds/ for parameters for each # Options are: # :tags => 'yourtags' is optional for :public # :size => :s, :t, :m, '-', :b, :o # :class => 'your css class' applied to the tags (defaults to 'flickr') # :count => a number (defaults to 5) # :cache => true or false so that flickr won't be queried everytime the helper is called (defaults to true) # :ul => true or false so the ul tag will not be added (defaults to true) # :li => true or false so the li tag will not be added (defaults to true) # :reverse => true or false so the order of the items is reversed (defaults to false) # :separator => ' | ' put between the items (defaults to nil - useful when :ul and :li are false) # :links => true or false so titles are linked or not (defaults to true) def flickr_list(what = :public, options = {}) if what.is_a?(Hash) options = what what = :public end options[:class] = 'flickr' unless options.has_key?(:class) options[:format] = 'rss2' rss_url = case(what) when :friends then 'http://api.flickr.com/services/feeds/photos_friends.gne' when :activity then 'http://api.flickr.com/services/feeds/activity.gne' when :comments then 'http://api.flickr.com/services/feeds/photos_comments.gne' when :news then 'http://api.flickr.com/services/feeds/news.gne' when :group_discussion then 'http://api.flickr.com/services/feeds/groups_discuss.gne' when :group_pool then 'http://api.flickr.com/services/feeds/groups_pool.gne' when :forums then 'http://api.flickr.com/services/feeds/forums.gne' else 'http://api.flickr.com/services/feeds/photos_public.gne' end tag_added = false options.keys.each do |param| next if RSS_LIST_PARAMETERS.include?(param) || !options[param] rss_url << (tag_added ? '&' : '?') rss_url << "#{param}=#{options[param]}" tag_added = true end rss_options = {} RSS_LIST_PARAMETERS.each do |key| rss_options[key] = options[key] if options.has_key?(key) end img_size = options[:size].to_s.downcase[0,1] if options[:size] img_size = 't' unless %w(s t m - b o).include?(img_size) img_element_name = (img_size == 'o') ? 'media:content' : 'media:thumbnail' rss_list(rss_url, rss_options) { |list_item| title = list_item[:title] img_element = ((list_item[:element])/img_element_name).first if img_element img_url = img_element.attributes['url'].gsub(/\_.\./, "_#{img_size}.") title = tag(:img, :src => img_url, :alt => list_item[:title]) end link(title, list_item[:link]) } end def ebay_list(options = {}) options[:class] = 'ebay' unless options.has_key?(:class) siteid = options[:siteid] || 0 sacat = options[:sacat] || -1 sacat = EBAY_CATEGORIES[sacat] if EBAY_CATEGORIES.has_key?(sacat) search = options[:search] || '' language = options[:language] || 'en-US' rss_url = "http://rss.api.ebay.com/ws/rssapi?FeedName=SearchResults&siteId=#{siteid}&language=#{language}&output=RSS20&from=R10&satitle=#{search}&sacat=#{sacat}" rss_options = {} RSS_LIST_PARAMETERS.each do |key| rss_options[key] = options[key] if options.has_key?(key) end rss_list(rss_url, rss_options) { |list_item| title = list_item[:title] desc_element = ((list_item[:element])/:description).first if desc_element && options[:images] desc_html = desc_element.inner_html.gsub(/(^$)/, '') img_element = (Hpricot(desc_html)/:img).first if img_element img_url = img_element.attributes['src'] title = tag(:img, :src => img_url, :alt => list_item[:title]) end end link(title, list_item[:link]) } end def magnolia_list(what = :tagged, options = {}) if what.is_a?(Hash) options = what what = :tagged end options[:class] = 'magnolia' unless options.has_key?(:class) rss_url = case(what) when :recent then "http://ma.gnolia.com/rss/lite/bookmarks" when :popular then "http://ma.gnolia.com/atom/full/popular" else "http://ma.gnolia.com/rss/lite/tags/#{options[:tags]}" end rss_options = {} RSS_LIST_PARAMETERS.each do |key| rss_options[key] = options[key] if options.has_key?(key) end rss_list(rss_url, rss_options) end def twitter_list(what, options = {}) if what.is_a?(Hash) options = what what = :user_timeline end options[:class] = 'twitter' unless options.has_key?(:class) rss_url = case(what) when :friends_timeline then "http://twitter.com/statuses/friends_timeline/#{options[:user_id]}.rss" when :public_timeline then "http://twitter.com/statuses/public_timeline.rss" else #:user_timeline "http://twitter.com/statuses/user_timeline/#{options[:user_id]}.rss" end rss_options = {} RSS_LIST_PARAMETERS.each do |key| rss_options[key] = options[key] if options.has_key?(key) end rss_list(rss_url, rss_options) end def digg_list(options = {}) return tag(:div, :class => 'digg_list_error') { "digg_list not operational yet due to digg blocking the request" } options[:class] = 'digg' unless options.has_key?(:class) rss_url = "http://digg.com/rss_search?search=#{options[:search]}&area=all&type=both§ion=all" rss_url = DIGG_TOPICS[options[:topic]] if options[:topic] && DIGG_TOPICS.has_key?(options[:topic]) rss_options = {} RSS_LIST_PARAMETERS.each do |key| rss_options[key] = options[key] if options.has_key?(key) end rss_list(rss_url, rss_options) end # def get_ebay_categories # url = "http://search.ebay.com/search/search.dll?sofocus=bs&sbrftog=1&from=R10&satitle=apple&sacat=267%26catref%3DC6&sargn=-1%26saslc%3D2&sadis=200&fpos=ZIP%2FPostal&sabfmts=1&saobfmts=insif&ftrt=1&ftrv=1&saprclo=&saprchi=&fsop=1%26fsoo%3D1&coaction=compare&copagenum=1&coentrypage=search&fgtp=" # select_element = ((Hpricot(open(url)))/:select).first # opts = {} # (select_element/:option).each { |opt| # name = opt.inner_text # next if name =~ /^\-+$/ || name =~ /^>\s/ # value = opt.attributes['value'].gsub(/&.*$/, '') # opts[name] = value # } # opts # end # puts get_ebay_categories.inspect # def get_digg_topics # url = "http://digg.com/digg.opml" # topics = {} # ((Hpricot.XML(File.open('C:/temp/digg.opml')))/:outline).each do |outline| # next unless outline.attributes['type'] == 'link' # name = outline.attributes['text'] # value = outline.attributes['xmlURL'] # topics[name] = value # end # topics # end # puts get_digg_topics.inspect end