Codice LunaRss 0_9

Vedi tutte le pagine e le modifiche recenti o scarica i sorgenti nella pagina


LunaRss v0.9 – modificato da Gabriele Renzi

La modifica precedente è stata Codice LunaRss 0_8, la prossima modifica sarà Codice LunaRss 1_0 congratulazioni :)

Piccolo refactoring di gabriele renzi:

Ho aggiunto un secondo piccolissimo TestCase, in quanto io vorrei integrare questo codice nel wiki.. il problema da risolvere è di facile soluzione, estrarre dalle pagine i metadati relativi ai feed, dovrebbe farsi con una istruzione. C’è un altro problema che sorge però: LunaRss gestisce davvero Rss? che Rss? Se la cava anche con Atom?

E poi, e per questo non c’è anora il TestCase, come facciamo ad aggiornare il feed globale inserendo solo i nuovi item? Sinceramente non ho idea di come fare ma forse si potrebbe usare la data di creazione. Si assuma di poter usare un backend ActiveRecord nel quale infilare gli oggetti che volete, con le api base:
require 'net/http'
require 'uri'

class Feed
  def initialize(url, opts = { })
    @uri = URI.parse(url)
  end
  def read
    @uri.read
  end
end

FeedData = Struct.new(
  :channel, 
  :titles, 
  :descriptions, 
  :links
  )

class RssParser
  CHANNEL_TITLE=%r{<channel(?!s).*?>.*?(?:<title>(?:<!\[CDATA\[)*(.*?)(?:\]\]>)*</title>.*?)?</channel>}m
  ITEM_TITLE=%r{<item(?!s).*?>.*?(?:<title>(?:<!\[CDATA\[)*(.*?)(?:\]\]>)*</title>.*?)?</item>}m 
  ITEM_LINKS=%r{<item(?!s).*?>.*?(?:<link>(?:<!\[CDATA\[)*(.*?)(?:\]\]>)*</link>.*?)?</item>}m
  ITEM_DESCRIPTION=%r{<item(?!s).*?>.*?(?:<description>(?:<!\[CDATA\[)*(.*?)(?:\]\]>)*</description>.*?)?</item>}m

  def initialize(feed)
    @feed = feed
  end 

  def parse
    FeedData.new( 
      extract( CHANNEL_TITLE    ),            
      extract( ITEM_TITLE       ),
      extract( ITEM_DESCRIPTION ),
      extract( ITEM_LINKS       )
      )  
  end

  private

  def rss_data
    @data ||= @feed.read
  end

  def extract pattern
    rss_data.scan pattern 
  end
end

class RssMaker
  def align text
    text.gsub(/^\s*\./m, '') 
  end
  private :align
  def header
    align <<-HTML
             .Content-type: text/html\r\n\r\n
             .<html>
             .<body>
             HTML
  end

  def footer
    align <<-HTML
             .</body>
             .</html>
             HTML
  end

  def channel name
    align <<-HTML
             .<h3>#{name}</h3>
             HTML
  end

  def entry titolo, descrizione, link
    align <<-HTML
             .<strong>
             .  <a href="#{link}"> #{titolo} </a>
             .</strong><br/>
             .
             .<font size="-1"> #{descrizione} </font>
             .<p/>
             HTML
  end

end

##############################

# Configurations

feeds=[
    'http://www.repubblica.it/rss/scienza_e_tecnologia/rss2.0.xml',
    'http://programmazione.it/rss.xml',
    'http://www.hwupgrade.it/rss_news.xml',
    'http://www.hwupgrade.it/rss_articoli.xml',
    'http://www.beppegrillo.it/index.xml'
]

NEED_PROXY = false #switch this if you have a proxy
proxy_url = "http://10.0.0.2:8080" #put here your proxy, if you have one

##############################

class LunaRss
  def get_feeds
    rss_make = RssMaker.new
    puts rss_make.header

    feeds.each do |feed|
      parser = RssParser.new feed 
      data = parser.parse
      puts rss_make.channel( data.channel )
      0.upto data.titles.length do|i|
        puts rss_make.entry( 
          data.titles[i], 
          data.descriptions[i], 
          data.links[i] 
          )
      end
    end

    puts rss_make.footer
  end
end

require 'test/unit'
require 'stringio'

class TestLunaRss < Test::Unit::TestCase
  TEST_DATA = <<-HTML
      <?xml version="1.0"?>
      <rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/">
        <channel>
          <title>Ruby Italia</title>
          <link>http://ruby-it.org/</link>
          <description>Tracking all versions for Ruby Italia</description>
          <language>it-it</language>
          <ttl>40</ttl>
          <item>
            <title>Chiaroscuro</title>
            <description>description too long</description>
            <pubDate>Mon, 08 May 2006 13:33:54 +0200</pubDate>
            <guid>http://ruby-it.org/pages/Chiaroscuro#936</guid>
            <link>http://ruby-it.org/pages/Chiaroscuro#936</link>
            <dc:creator>Chiaroscuro</dc:creator>
          </item>
        </channel>
      </rss>
    HTML

  def test_parser
    parser = RssParser.new(StringIO.new(TEST_DATA))
    data = parser.parse
    assert_equal "Ruby Italia".to_s, data.channel[0].to_s
    assert_equal "Chiaroscuro".to_s, data.titles[0].to_s
    assert_equal "description too long".to_s, data.descriptions[0].to_s
    assert_equal "http://ruby-it.org/pages/Chiaroscuro#936".to_s, data.links[0].to_s
  end  

end

class TestLunaRssStore < Test::Unit::TestCase
  Page=Struct.new :title, :body
  TestPages=[Page.new("Andrea",<<Andrea),Page.new("antonio", <<Antonio)]
bla bla 
feed: http://guragedev.blogspot.com/atom.xml
bla bla
Andrea

ble bn
ble 
aleklena
feed: http://www.antoniocangiano.com/xml/rss20/feed.xml
feed: http://www.antoniocangiano.com/xml/rss20/comments/feed.xml
Antonio

  def test_load_data
    RssStore.new(TestPages)
    uris=RssStore.load_feed_uris
    assert_equal 3, uris.size
  end
end
Updated on May 16, 2006 20:42 by Ruby Fan (81.208.83.225)