pummel 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,3 @@
1
+ README.md
2
+ LICENSE
3
+ pummel.rb
@@ -0,0 +1,21 @@
1
+ ## MAC OS
2
+ .DS_Store
3
+
4
+ ## TEXTMATE
5
+ *.tmproj
6
+ tmtags
7
+
8
+ ## EMACS
9
+ *~
10
+ \#*
11
+ .\#*
12
+
13
+ ## VIM
14
+ *.swp
15
+
16
+ ## PROJECT::GENERAL
17
+ coverage
18
+ rdoc
19
+ pkg
20
+
21
+ ## PROJECT::SPECIFIC
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Colin Shea
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,70 @@
1
+ # pummel
2
+
3
+ Auto-tumble your RSS feed! (Default: my (Evaryont) pinboard.in links)
4
+
5
+ ## Dependencies
6
+
7
+ * Rack
8
+ * Sinatra
9
+ * Ruby-OEmbed (vendored under vendor/ruby-oembed)
10
+ * RSS (built-in in Ruby 1.8+)
11
+
12
+ ## Installation
13
+
14
+ $ git clone git://github.com/evaryont/pummel.git
15
+ $ cd pummel
16
+ $ edit pummel.rb
17
+ # Edit the file to point to your choice of RSS feed
18
+ $ rackup
19
+ # Open your browser to http://localhost:9292/
20
+
21
+ ## Demo (& Heroku)
22
+
23
+ This web application was designed for Heroku, and is immediately compatible.
24
+ You can see a demo (and my bookmarks!) at [Heroku][].
25
+
26
+ ## Inspiration
27
+
28
+ I was just browsing around on the web, aimlessly when I stumbled on the [OEmbed][]
29
+ project, and subsequently found [OohEmbed][]. The author created a small-ish
30
+ javascript application called [Dumble][], which is exactly what Pummel is, but
31
+ uses a user's del.icio.us bookmarks rather than Pinboard. As I don't really use
32
+ del.icio.us but instead of pinboard.in, I decided to create my own version.
33
+
34
+ Here it is.
35
+
36
+ ## Technical Overview
37
+
38
+ This is relatively geeky overview of how Pummel works, so if you want to skip it,
39
+ go right ahead.
40
+
41
+ At application initiation, an Iconv object is created, and the RSS feed is fetched
42
+ and parsed.
43
+
44
+ Every time the index page is requested, loop through each item in the feed, and
45
+ pull it's link. Check if the link is embeddable. If it is, determine the type and
46
+ use the correct HTML. (Note: This perhaps should be done by Ruby-OEmbed itself.)
47
+ If it can not be embedded, create a simple link. If there is an error when embedding,
48
+ show the error in a <pre> block, and create a simple link.
49
+
50
+ Every time the refresh page is requested (http://.../refresh) pull the feed again
51
+ and parse it. Then redirect the user to the index page.
52
+
53
+ ## Note on Patches/Pull Requests
54
+
55
+ 1. Fork the project.
56
+ 1. Make your feature addition or bug fix.
57
+ 1. Add tests for it. This is important so I don't break it in a
58
+ future version unintentionally.
59
+ 1. Commit, do not mess with Rakefile, version, or history.
60
+ (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
61
+ 1. Send me a pull request. Bonus points for topic branches.
62
+
63
+ ## Copyright
64
+
65
+ Copyright (C) 2010 Colin Shea. See LICENSE for details.
66
+
67
+ [OEmbed]: http://www.oembed.com/
68
+ [OohEmbed]: http://oohembed.com/
69
+ [Dumble]: http://oohembed.com/dumble/
70
+ [Heroku]: http://pummel-demo.heroku.com
@@ -0,0 +1,57 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "pummel"
8
+ gem.summary = %Q{Auto-tumble your RSS feed!}
9
+ gem.description = %Q{Given an RSS feed, make a tumblr-like site out of it. Uses Sinatra & Rack, inspired by Dumble.}
10
+ gem.email = "colin@evaryont.me"
11
+ gem.homepage = "http://github.com/evaryont/pummel"
12
+ gem.authors = ["Colin Shea"]
13
+ gem.add_dependency("sinatra")
14
+ gem.add_development_dependency "riot", ">= 0"
15
+ gem.add_development_dependency "yard", ">= 0"
16
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
17
+ end
18
+ Jeweler::GemcutterTasks.new
19
+ rescue LoadError
20
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
21
+ end
22
+
23
+ begin
24
+ require 'reek/adapters/rake_task'
25
+ Reek::RakeTask.new do |t|
26
+ t.fail_on_error = true
27
+ t.verbose = false
28
+ t.source_files = 'lib/**/*.rb'
29
+ end
30
+ rescue LoadError
31
+ task :reek do
32
+ abort "Reek is not available. In order to run reek, you must: sudo gem install reek"
33
+ end
34
+ end
35
+
36
+ begin
37
+ require 'roodi'
38
+ require 'roodi_task'
39
+ RoodiTask.new do |t|
40
+ t.verbose = false
41
+ end
42
+ rescue LoadError
43
+ task :roodi do
44
+ abort "Roodi is not available. In order to run roodi, you must: sudo gem install roodi"
45
+ end
46
+ end
47
+
48
+ task :default => :test
49
+
50
+ begin
51
+ require 'yard'
52
+ YARD::Rake::YardocTask.new
53
+ rescue LoadError
54
+ task :yardoc do
55
+ abort "YARD is not available. In order to run yardoc, you must: sudo gem install yard"
56
+ end
57
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.3.0
@@ -0,0 +1,17 @@
1
+ require 'rubygems'
2
+ require 'sinatra'
3
+ require 'pummel'
4
+
5
+ root_dir = ::File.dirname(__FILE__)
6
+
7
+ set :environment, :production
8
+ set :root, root_dir
9
+ set :app_file, ::File.join(root_dir, 'pummel.rb')
10
+ disable :run
11
+
12
+ #::FileUtils.mkdir_p 'log' unless ::File.exists?('log')
13
+ #log = ::File.new("log/sinatra.log", "a")
14
+ #$stdout.reopen(log)
15
+ #$stderr.reopen(log)
16
+
17
+ run Sinatra::Application
Binary file
Binary file
@@ -0,0 +1,34 @@
1
+ /* Body image stolen from Heroku's main page (v3) */
2
+ /* A beautiful gradient is beautiful regardless, thank you very much Heroku! */
3
+ body {
4
+ background: url("/body.png") repeat-x scroll 0 0 #212121;
5
+ padding: 0px;
6
+ margin: 0px;
7
+ text-align: center;
8
+ color: #333;
9
+ }
10
+
11
+ a {
12
+ color: #555;
13
+ }
14
+
15
+ hr {
16
+ background-color: #444;
17
+ width: 250px;
18
+ height: 1px;
19
+ border: 0px;
20
+ }
21
+
22
+ h2 {
23
+ margin-bottom: 0px;
24
+ }
25
+ h2 a {
26
+ color: #fff;
27
+ }
28
+ h2 + span {
29
+ color: #bbb;
30
+ }
31
+
32
+ #oembed_feed code {
33
+ display: block;
34
+ }
@@ -0,0 +1,75 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{pummel}
8
+ s.version = "0.3.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Colin Shea"]
12
+ s.date = %q{2010-02-16}
13
+ s.description = %q{Given an RSS feed, make a tumblr-like site out of it. Uses Sinatra & Rack, inspired by Dumble.}
14
+ s.email = %q{colin@evaryont.me}
15
+ s.extra_rdoc_files = [
16
+ "LICENSE",
17
+ "README.md"
18
+ ]
19
+ s.files = [
20
+ ".document",
21
+ ".gitignore",
22
+ "LICENSE",
23
+ "README.md",
24
+ "Rakefile",
25
+ "VERSION",
26
+ "config.ru",
27
+ "public/body.png",
28
+ "public/favicon.ico",
29
+ "public/style.css",
30
+ "pummel.gemspec",
31
+ "pummel.rb",
32
+ "templates/index.erb",
33
+ "vendor/ruby-oembed/idea.rb",
34
+ "vendor/ruby-oembed/lib/oembed.rb",
35
+ "vendor/ruby-oembed/lib/oembed/errors.rb",
36
+ "vendor/ruby-oembed/lib/oembed/formatters.rb",
37
+ "vendor/ruby-oembed/lib/oembed/provider.rb",
38
+ "vendor/ruby-oembed/lib/oembed/provider_discovery.rb",
39
+ "vendor/ruby-oembed/lib/oembed/providers.rb",
40
+ "vendor/ruby-oembed/lib/oembed/response.rb",
41
+ "vendor/ruby-oembed/lib/oembed/response/link.rb",
42
+ "vendor/ruby-oembed/lib/oembed/response/photo.rb",
43
+ "vendor/ruby-oembed/lib/oembed/response/rich.rb",
44
+ "vendor/ruby-oembed/lib/oembed/response/video.rb",
45
+ "vendor/ruby-oembed/spec/provider_spec.rb",
46
+ "vendor/ruby-oembed/spec/providers_spec.rb",
47
+ "vendor/ruby-oembed/spec/response_spec.rb",
48
+ "vendor/ruby-oembed/spec/spec_helper.rb"
49
+ ]
50
+ s.homepage = %q{http://github.com/evaryont/pummel}
51
+ s.rdoc_options = ["--charset=UTF-8"]
52
+ s.require_paths = ["lib"]
53
+ s.rubygems_version = %q{1.3.5}
54
+ s.summary = %q{Auto-tumble your RSS feed!}
55
+
56
+ if s.respond_to? :specification_version then
57
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
58
+ s.specification_version = 3
59
+
60
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
61
+ s.add_runtime_dependency(%q<sinatra>, [">= 0"])
62
+ s.add_development_dependency(%q<riot>, [">= 0"])
63
+ s.add_development_dependency(%q<yard>, [">= 0"])
64
+ else
65
+ s.add_dependency(%q<sinatra>, [">= 0"])
66
+ s.add_dependency(%q<riot>, [">= 0"])
67
+ s.add_dependency(%q<yard>, [">= 0"])
68
+ end
69
+ else
70
+ s.add_dependency(%q<sinatra>, [">= 0"])
71
+ s.add_dependency(%q<riot>, [">= 0"])
72
+ s.add_dependency(%q<yard>, [">= 0"])
73
+ end
74
+ end
75
+
@@ -0,0 +1,50 @@
1
+ require 'iconv'
2
+ require 'rss/1.0'
3
+ require 'rss/2.0'
4
+ require 'open-uri'
5
+ require 'sinatra'
6
+ $: << File.join(File.dirname(__FILE__), 'vendor', 'ruby-oembed', 'lib')
7
+ require 'oembed'
8
+
9
+ @@rss_url = "http://feeds.pinboard.in/rss/u:evaryont/"
10
+ @@ic = Iconv.new('UTF-8//IGNORE', 'UTF-8')
11
+ def refresh_rss
12
+ valid_string = @@ic.iconv(open(@@rss_url).read << ' ')[0..-2]
13
+ @@rss = RSS::Parser.parse valid_string, false
14
+ end
15
+ refresh_rss()
16
+
17
+ set :public, File.dirname(__FILE__) + '/public'
18
+ set :views, File.dirname(__FILE__) + '/templates'
19
+
20
+ # Access to the @@rss variable, used in the template
21
+ def rss
22
+ @@rss
23
+ end
24
+
25
+ # Return a string, the proper HTML for the OEmbed response
26
+ #
27
+ # Used in the template.
28
+ def generate_html(oembed_response)
29
+ case oembed_response.field('type')
30
+ when 'photo'
31
+ return "<img src='#{oembed_response.field("url")}' width='#{oembed_response.field("width")}' height='#{oembed_response.field("height")}' />"
32
+ when 'video'
33
+ return oembed_response.field('html')
34
+ when 'link'
35
+ return "<a href='#{oembed_response.url}'>#{oembed_response.field('html') || oembed_response.url}</a>"
36
+ when 'rich'
37
+ return oembed_response.field('html')
38
+ else
39
+ "<a href='#{oembed_response.url}'>#{oembed_response.field('html') || oembed_response.url}</a>"
40
+ end
41
+ end
42
+
43
+ get '/' do
44
+ erb :index
45
+ end
46
+
47
+ get '/refresh' do
48
+ refresh_rss()
49
+ redirect '/'
50
+ end
@@ -0,0 +1,22 @@
1
+ <html><head>
2
+ <title>Pummel - Auto tumble your pinboard.in links!</title>
3
+ <link href="/style.css" media="screen" rel="stylesheet" type="text/css" />
4
+ </head><body>
5
+ <p>
6
+ <h2><a href="<%= rss.channel.link %>"><%= rss.channel.title %></a></h2>
7
+ <span><%= rss.channel.description %></span> (<a href="/refresh">refresh</a>)
8
+ </p>
9
+ <div id="oembed_feed">
10
+ <% rss.items.each do |item| %>
11
+ <p><%
12
+ begin
13
+ oemb = OEmbed::Providers.get(item.link) %>
14
+ <%= generate_html(oemb) %>
15
+ <% rescue OEmbed::NotFound %>
16
+ <a href="<%= item.link %>"><%= item.title %></a>
17
+ <% rescue OEmbed::Error => error %>
18
+ <a href="<%= item.link %>"><%= item.title %></a><code>Error: <%= error.to_s %></code>
19
+ <% end %>
20
+ <hr /></p>
21
+ <% end %>
22
+ </div></body></html>
@@ -0,0 +1,37 @@
1
+ # Adding providers:
2
+ # The second argument defines the default format
3
+ flickr = OEmbed::Provider.new("http://www.flickr.com/services/oembed/", :xml)
4
+ flickr << "http://*.flickr.com/*"
5
+ # Optional settings:
6
+ flickr.name = "Flickr"
7
+ flickr.url = "http://flickr.com/"
8
+
9
+ # Another one:
10
+ # The default format is json
11
+ qik = OEmbed::Provider.new("http://qik.com/api/oembed.{format}")
12
+ qik << "http://qik.com/*"
13
+
14
+ # Get a raw XML-file from Flickr
15
+ flickr.raw("http://flickr.com/photos/my_user/1231231312")
16
+ # Get a raw JSON-file from Flickr
17
+ flickr.raw("http://flickr.com/photos/my_user/1231231312", :format => :json)
18
+
19
+ # Register both providers
20
+ OEmbed::Providers.register(flickr, qik)
21
+
22
+ # Get a raw XML-file from whichever provider matches
23
+ OEmbed::Providers.raw("http://qik.com/video/1", :format => :xml)
24
+
25
+ # Returns a OEmbed::Response using XmlSimple library to parse the response
26
+ res = flickr.get("http://flickr.com/photos/my_user/1231231312")
27
+ # Returns a OEmbed::Response using the JSON library to parse the response
28
+ res = flickr.get("http://flickr.com/photos/my_user/1231231312", :format => :json)
29
+
30
+ res.is_a?(OEmbed::Response) # => true
31
+ res.type # => "photo"
32
+ res.version # => "1.0"
33
+ res.html # => "<img src='http://farm1.static.flickr.com/2312/3123123_123123.jpg' />"
34
+ res.author_name # => "my_user"
35
+ res.author_url # => "http://flickr.com/photos/my_user"
36
+ res.provider.url # => "http://flickr.com/"
37
+ res.provider.name # => "Flickr"
@@ -0,0 +1,14 @@
1
+ $:.unshift File.dirname(__FILE__)
2
+
3
+ require 'net/http'
4
+
5
+ require 'oembed/errors'
6
+ require 'oembed/formatters'
7
+ require 'oembed/provider'
8
+ require 'oembed/provider_discovery'
9
+ require 'oembed/providers'
10
+ require 'oembed/response'
11
+ require 'oembed/response/photo'
12
+ require 'oembed/response/video'
13
+ require 'oembed/response/link'
14
+ require 'oembed/response/rich'
@@ -0,0 +1,28 @@
1
+ module OEmbed
2
+ class Error < StandardError
3
+ end
4
+
5
+ class NotFound < OEmbed::Error
6
+ def to_s
7
+ "No embeddable content at '#{super}'"
8
+ end
9
+ end
10
+
11
+ class UnknownFormat < OEmbed::Error
12
+ def to_s
13
+ "The provider doesn't support the '#{super}' format"
14
+ end
15
+ end
16
+
17
+ class FormatNotSupported < OEmbed::Error
18
+ def to_s
19
+ "This server doesn't have the correct libraries installed to support the '#{super}' format"
20
+ end
21
+ end
22
+
23
+ class UnknownResponse < OEmbed::Error
24
+ def to_s
25
+ "Got unknown response (#{super}) from server"
26
+ end
27
+ end
28
+ end