From 0930e5fa23db0e8d065b5a44514c3396009a50b4 Mon Sep 17 00:00:00 2001 From: Marcin Kulik Date: Sun, 29 Mar 2015 18:19:18 +0000 Subject: [PATCH] Add oEmbed endpoint --- app/controllers/application_controller.rb | 6 +- app/controllers/oembed_controller.rb | 70 +++++++++++++++++++++++ app/uploaders/asciicast_uploader.rb | 6 +- app/views/oembed/show.html.erb | 1 + config/routes.rb | 2 + spec/api/oembed_spec.rb | 17 ++++++ 6 files changed, 97 insertions(+), 5 deletions(-) create mode 100644 app/controllers/oembed_controller.rb create mode 100644 app/views/oembed/show.html.erb create mode 100644 spec/api/oembed_spec.rb diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 4dc284f..d68f30e 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -81,6 +81,10 @@ class ApplicationController < ActionController::Base end end - helper_method :profile_path + def profile_url(user) + root_url[0..-2] + profile_path(user) + end + + helper_method :profile_path, :profile_url end diff --git a/app/controllers/oembed_controller.rb b/app/controllers/oembed_controller.rb new file mode 100644 index 0000000..1ef185c --- /dev/null +++ b/app/controllers/oembed_controller.rb @@ -0,0 +1,70 @@ +class OembedController < ApplicationController + + def show + url = URI.parse(params[:url]) + + if url.path =~ %r{^/a/(\d+)$} + id = $1 + asciicast = AsciicastDecorator.new(Asciicast.find(id)) + oembed = oembed_response(asciicast) + + respond_to do |format| + format.json do + render json: oembed + end + format.xml do + render xml: oembed.to_xml(root: 'oembed') + end + end + else + head :bad_request + end + end + + private + + def oembed_response(asciicast) + width, height = asciicast.image_width, asciicast.image_height + + if params[:maxwidth] + width, height = size_smaller_than(width, height, params[:maxwidth], params[:maxheight]) + end + + oembed = { + type: 'rich', + version: 1.0, + title: asciicast.title, + author_name: asciicast.user.display_name, + author_url: profile_url(asciicast.user), + provider_name: 'asciinema', + provider_url: root_url, + thumbnail_url: asciicast.image_url, + thumbnail_width: width, + thumbnail_height: height, + html: render_html(asciicast, width), + width: width, + height: height, + } + end + + def render_html(asciicast, width) + render_to_string( + template: 'oembed/show.html.erb', + layout: false, + locals: { asciicast: asciicast, width: width } + ).chomp + end + + def size_smaller_than(width, height, max_width, max_height) + fw = Rational(max_width, width) + fh = Rational(max_height, height) + + if fw > 1 && fh > 1 + [width, height] + else + f = [fw, fh].min + [(Rational(width) * f).to_i, (Rational(height) * f).to_i] + end + end + +end diff --git a/app/uploaders/asciicast_uploader.rb b/app/uploaders/asciicast_uploader.rb index 07cae1b..2670736 100644 --- a/app/uploaders/asciicast_uploader.rb +++ b/app/uploaders/asciicast_uploader.rb @@ -1,12 +1,10 @@ class AsciicastUploader < BaseUploader def url - url = super - - if url[0] == '/' + if CFG.carrierwave_storage == 'file' path else - url + super end end diff --git a/app/views/oembed/show.html.erb b/app/views/oembed/show.html.erb new file mode 100644 index 0000000..2357cb8 --- /dev/null +++ b/app/views/oembed/show.html.erb @@ -0,0 +1 @@ +<%= link_to image_tag(asciicast.image_url, width: width, alt: asciicast.title), asciicast_url(asciicast), target: '_blank' %> diff --git a/config/routes.rb b/config/routes.rb index ab71d24..faa3066 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -15,6 +15,8 @@ Rails.application.routes.draw do get "/u/:id" => "users#show", as: :unnamed_user get "/~:username" => "users#show", as: :public_profile + get "/oembed" => "oembed#show", as: :oembed + namespace :api do resources :asciicasts end diff --git a/spec/api/oembed_spec.rb b/spec/api/oembed_spec.rb new file mode 100644 index 0000000..fcf52e7 --- /dev/null +++ b/spec/api/oembed_spec.rb @@ -0,0 +1,17 @@ +require 'rails_helper' + +describe "oEmbed provider" do + + let(:asciicast) { create(:asciicast) } + + it "responds with status 200 for JSON" do + get "/oembed?url=http://localhost:3000/a/#{asciicast.id}&format=json" + expect(response.status).to eq(200) + end + + it "responds with status 200 for XML" do + get "/oembed?url=http://localhost:3000/a/#{asciicast.id}&format=xml" + expect(response.status).to eq(200) + end + +end