From 6ff93845d55eb34fc8beceb0c2dde06860c1eb47 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Wed, 30 Nov 2016 23:01:03 +0100 Subject: [PATCH] Add basic OEmbed provider API, fix #247 --- app/controllers/api/oembed_controller.rb | 21 +++++++++++++++++++ app/helpers/api/oembed_helper.rb | 2 ++ app/views/api/oembed/show.json.rabl | 14 +++++++++++++ app/views/stream_entries/show.html.haml | 5 +++++ config/routes.rb | 3 +++ .../controllers/api/oembed_controller_spec.rb | 5 +++++ spec/helpers/api/oembed_helper_spec.rb | 15 +++++++++++++ 7 files changed, 65 insertions(+) create mode 100644 app/controllers/api/oembed_controller.rb create mode 100644 app/helpers/api/oembed_helper.rb create mode 100644 app/views/api/oembed/show.json.rabl create mode 100644 spec/controllers/api/oembed_controller_spec.rb create mode 100644 spec/helpers/api/oembed_helper_spec.rb diff --git a/app/controllers/api/oembed_controller.rb b/app/controllers/api/oembed_controller.rb new file mode 100644 index 00000000..4a591dc2 --- /dev/null +++ b/app/controllers/api/oembed_controller.rb @@ -0,0 +1,21 @@ +# frozen_string_literal: true + +class Api::OembedController < ApiController + respond_to :json + + def show + @stream_entry = stream_entry_from_url(params[:url]) + @width = [300, params[:maxwidth].to_i].min + @height = [200, params[:maxheight].to_i].min + end + + private + + def stream_entry_from_url(url) + params = Rails.application.routes.recognize_path(url) + + raise ActiveRecord::NotFound unless params[:controller] == 'stream_entries' && params[:action] == 'show' + + StreamEntry.find(params[:id]) + end +end diff --git a/app/helpers/api/oembed_helper.rb b/app/helpers/api/oembed_helper.rb new file mode 100644 index 00000000..05d5ca21 --- /dev/null +++ b/app/helpers/api/oembed_helper.rb @@ -0,0 +1,2 @@ +module Api::OembedHelper +end diff --git a/app/views/api/oembed/show.json.rabl b/app/views/api/oembed/show.json.rabl new file mode 100644 index 00000000..e035bc13 --- /dev/null +++ b/app/views/api/oembed/show.json.rabl @@ -0,0 +1,14 @@ +# frozen_string_literal: true +object @stream_entry + +node(:type) { 'rich' } +node(:version) { '1.0' } +node(:title, &:title) +node(:author_name) { |entry| entry.account.display_name.blank? ? entry.account.username : entry.account.display_name } +node(:author_url) { |entry| account_url(entry.account) } +node(:provider_name) { Rails.configuration.x.local_domain } +node(:provider_url) { root_url } +node(:cache_age) { 86_400 } +node(:html, &:content) +node(:width) { @width } +node(:height) { @height } diff --git a/app/views/stream_entries/show.html.haml b/app/views/stream_entries/show.html.haml index 2c6de32d..e628dd99 100644 --- a/app/views/stream_entries/show.html.haml +++ b/app/views/stream_entries/show.html.haml @@ -1,8 +1,13 @@ - content_for :header_tags do %link{ rel: 'alternate', type: 'application/atom+xml', href: account_stream_entry_url(@account, @stream_entry, format: 'atom') }/ + %link{ rel: 'alternate', type: 'application/json+oembed', href: api_oembed_url(url: account_stream_entry_url(@account, @stream_entry), format: 'json') }/ + %meta{ name: 'og:site_name', content: 'Mastodon' }/ %meta{ name: 'og:type', content: 'article' }/ + %meta{ name: 'og:title', content: "#{@account.username} on #{Rails.configuration.x.local_domain}" }/ %meta{ name: 'og:article:author', content: @account.username }/ + %meta{ name: 'og:description', content: @stream_entry.activity.content }/ + %meta{ name: 'og:image', content: @stream_entry.activity.is_a?(Status) && @stream_entry.activity.media_attachments.size > 0 ? full_asset_url(@stream_entry.activity.media_attachments.first.file.url(:preview)) : full_asset_url(@account.avatar.url(:large)) }/ .activity-stream.activity-stream-headless = render partial: @type, locals: { @type.to_sym => @stream_entry.activity, include_threads: true } diff --git a/config/routes.rb b/config/routes.rb index f956e99b..35e5c269 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -60,6 +60,9 @@ Rails.application.routes.draw do # Salmon post '/salmon/:id', to: 'salmon#update', as: :salmon + # OEmbed + get '/oembed', to: 'oembed#show', as: :oembed + # JSON / REST API namespace :v1 do resources :statuses, only: [:create, :show, :destroy] do diff --git a/spec/controllers/api/oembed_controller_spec.rb b/spec/controllers/api/oembed_controller_spec.rb new file mode 100644 index 00000000..758bfd1d --- /dev/null +++ b/spec/controllers/api/oembed_controller_spec.rb @@ -0,0 +1,5 @@ +require 'rails_helper' + +RSpec.describe Api::OembedController, type: :controller do + +end diff --git a/spec/helpers/api/oembed_helper_spec.rb b/spec/helpers/api/oembed_helper_spec.rb new file mode 100644 index 00000000..4f64cb84 --- /dev/null +++ b/spec/helpers/api/oembed_helper_spec.rb @@ -0,0 +1,15 @@ +require 'rails_helper' + +# Specs in this file have access to a helper object that includes +# the Api::OembedHelper. For example: +# +# describe Api::OembedHelper do +# describe "string concat" do +# it "concats two strings with spaces" do +# expect(helper.concat_strings("this","that")).to eq("this that") +# end +# end +# end +RSpec.describe Api::OembedHelper, type: :helper do + pending "add some examples to (or delete) #{__FILE__}" +end