Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Merge pull request #1 from cz8s/master

RSS/Atom and status.net plugins
  • Loading branch information...
commit 603591f42df3db60b243dd2a62aa08e425012f46 2 parents 06cb67e + 528faf6
Christian Hellsten authored

Showing 2 changed files with 176 additions and 0 deletions. Show diff stats Hide diff stats

  1. +27 0 README.textile
  2. +149 0 rssfeed.rb
27 README.textile
Source Rendered
@@ -29,3 +29,30 @@ h4. Parameters
29 29 h2. Author
30 30
31 31 "Christian Hellsten":http://christianhellsten.com ("Aktagon Ltd.":http://aktagon.com)
  32 +
  33 +h2. rssfeed
  34 +
  35 +This Jekyll plugin is used for fetching and rendering rss and atom feeds
  36 +
  37 +h3. Usage
  38 +
  39 +This will fetch the last 15 dents and cache them for 3600 seconds:
  40 +
  41 +<pre><code>
  42 + {% rssfeed url:https://github.com/cz8s.atom count:15 ttl:3600 %}
  43 + {{ item.link }}
  44 + {{ item.day }}
  45 + {{ item.description }}
  46 + {% endstatusnet %}
  47 +</code></pre>
  48 +
  49 +h4. Parameters
  50 +
  51 +|Name|Description|Example|
  52 +|url|where the feed is |https://github.com/cz8s.atom|
  53 +|count|Number of Posts to show |15|
  54 +|ttl|The number of seconds the feed is cached 3600 caches the feed for one hour. Leave empty to always fetch feed.|3600|
  55 +
  56 +h2. Author
  57 +
  58 +"Christoph":http://www.kluenter.de
149 rssfeed.rb
... ... @@ -0,0 +1,149 @@
  1 +require 'open-uri'
  2 +require 'pp'
  3 +require 'ostruct'
  4 +require 'yaml'
  5 +require 'jekyll'
  6 +require 'date'
  7 +require 'digest/md5'
  8 +require 'action_view'
  9 +require 'net/http'
  10 +require 'net/https'
  11 +require 'feedparser'
  12 +require 'uri'
  13 +
  14 +include ActionView::Helpers::DateHelper
  15 +
  16 +# From http://api.rubyonrails.org/classes/ActiveSupport/CoreExtensions/Hash/Keys.html
  17 +class Hash
  18 + def stringify_keys!
  19 + keys.each do |key|
  20 + self[key.to_s] = delete(key)
  21 + end
  22 + self
  23 + end
  24 +end
  25 +
  26 +
  27 +
  28 +
  29 +#
  30 +# Parses a rss/atom feed and returns items as an array.
  31 +#
  32 +class RSSFeed
  33 + DEFAULT_TTL = 600
  34 + class << self
  35 + def tag(url, count = 15, ttl=DEFAULT_TTL)
  36 + links = []
  37 + url = "#{url}"
  38 + uri=URI.parse(url)
  39 + http = Net::HTTP.new(uri.host, uri.port)
  40 + if uri.scheme == "https"
  41 + http.use_ssl = true
  42 + http.verify_mode = OpenSSL::SSL::VERIFY_NONE
  43 + end
  44 + request = Net::HTTP::Get.new(uri.request_uri)
  45 + response = http.request(request)
  46 + f = FeedParser::Feed::new(response.body)
  47 + f.items.take(count.to_i).each do |i|
  48 + item = OpenStruct.new
  49 + item.title = i.title
  50 + item.link = i.link
  51 + item.date = i.date
  52 + item.day = time_ago_in_words(i.date)
  53 + item.description = i.content
  54 + links << item
  55 + end
  56 + links
  57 + end
  58 + end
  59 +end
  60 +
  61 +#
  62 +# Cached version of the RSSFeed Jekyll tag.
  63 +#
  64 +class CachedRSSFeed < RSSFeed
  65 + DEFAULT_TTL = 600
  66 + CACHE_DIR = '_rssfeed_cache'
  67 + class << self
  68 + def tag(url, count = 15, ttl = DEFAULT_TTL)
  69 + ttl = DEFAULT_TTL if ttl.nil?
  70 + cache_key = "#{url}_#{count}"
  71 + cache_file = File.join(CACHE_DIR, Digest::MD5.hexdigest(cache_key) + '.yml')
  72 + FileUtils.mkdir_p(CACHE_DIR) if !File.directory?(CACHE_DIR)
  73 + age_in_seconds = Time.now - File.stat(cache_file).mtime if File.exist?(cache_file)
  74 + if age_in_seconds.nil? || age_in_seconds > ttl
  75 + result = super(url, count)
  76 + File.open(cache_file, 'w') { |out| YAML.dump(result, out) }
  77 + else
  78 + result = YAML::load_file(cache_file)
  79 + end
  80 + result
  81 + end
  82 + end
  83 +end
  84 +
  85 +module Jekyll
  86 + class RSSFeedTag < Liquid::Block
  87 +
  88 + include Liquid::StandardFilters
  89 + Syntax = /(#{Liquid::QuotedFragment}+)?/
  90 +
  91 + def initialize(tag_name, markup, tokens)
  92 + @variable_name = 'item'
  93 + @attributes = {}
  94 +
  95 + # Parse parameters
  96 + if markup =~ Syntax
  97 + markup.scan(Liquid::TagAttributes) do |key, value|
  98 + #p key + ":" + value
  99 + @attributes[key] = value
  100 + end
  101 + else
  102 + raise SyntaxError.new("Syntax Error in 'rssfeed' - Valid syntax: rssfeed uid:x count:x]")
  103 + end
  104 +
  105 + @ttl = @attributes.has_key?('ttl') ? @attributes['ttl'].to_i : nil
  106 + @url = @attributes['url']
  107 + @count = @attributes['count']
  108 + @name = 'item'
  109 +
  110 + super
  111 + end
  112 +
  113 + def render(context)
  114 + context.registers[:rssfeed] ||= Hash.new(0)
  115 +
  116 + if @ttl
  117 + collection = CachedRSSFeed.tag(@url, @count, @ttl)
  118 + else
  119 + collection = RSSFeed.tag(@url, @count)
  120 + end
  121 +
  122 + length = collection.length
  123 + result = []
  124 +
  125 + # loop through found items and render results
  126 + context.stack do
  127 + collection.each_with_index do |item, index|
  128 + attrs = item.send('table')
  129 + context[@variable_name] = attrs.stringify_keys! if attrs.size > 0
  130 + context['forloop'] = {
  131 + 'name' => @name,
  132 + 'length' => length,
  133 + 'index' => index + 1,
  134 + 'index0' => index,
  135 + 'rindex' => length - index,
  136 + 'rindex0' => length - index -1,
  137 + 'first' => (index == 0),
  138 + 'last' => (index == length - 1) }
  139 +
  140 + result << render_all(@nodelist, context)
  141 + end
  142 + end
  143 + result
  144 + end
  145 + end
  146 +end
  147 +
  148 +Liquid::Template.register_tag('rssfeed', Jekyll::RSSFeedTag)
  149 +

0 comments on commit 603591f

Please sign in to comment.
Something went wrong with that request. Please try again.