Encode custom emojis as resolveable objects in ActivityPub (#5243)
* Encode custom emojis as resolveable objects in ActivityPub * Improve code style
This commit is contained in:
		
							parent
							
								
									057db0ecd0
								
							
						
					
					
						commit
						3a3475450e
					
				
					 17 changed files with 132 additions and 48 deletions
				
			
		| 
						 | 
				
			
			@ -26,7 +26,10 @@ class AccountsController < ApplicationController
 | 
			
		|||
      end
 | 
			
		||||
 | 
			
		||||
      format.json do
 | 
			
		||||
        render json: @account, serializer: ActivityPub::ActorSerializer, adapter: ActivityPub::Adapter, content_type: 'application/activity+json'
 | 
			
		||||
        render json: @account,
 | 
			
		||||
               serializer: ActivityPub::ActorSerializer,
 | 
			
		||||
               adapter: ActivityPub::Adapter,
 | 
			
		||||
               content_type: 'application/activity+json'
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										22
									
								
								app/controllers/emojis_controller.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								app/controllers/emojis_controller.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,22 @@
 | 
			
		|||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
class EmojisController < ApplicationController
 | 
			
		||||
  before_action :set_emoji
 | 
			
		||||
 | 
			
		||||
  def show
 | 
			
		||||
    respond_to do |format|
 | 
			
		||||
      format.json do
 | 
			
		||||
        render json: @emoji,
 | 
			
		||||
               serializer: ActivityPub::EmojiSerializer,
 | 
			
		||||
               adapter: ActivityPub::Adapter,
 | 
			
		||||
               content_type: 'application/activity+json'
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  private
 | 
			
		||||
 | 
			
		||||
  def set_emoji
 | 
			
		||||
    @emoji = CustomEmoji.local.find(params[:id])
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			@ -10,7 +10,10 @@ class FollowerAccountsController < ApplicationController
 | 
			
		|||
      format.html
 | 
			
		||||
 | 
			
		||||
      format.json do
 | 
			
		||||
        render json: collection_presenter, serializer: ActivityPub::CollectionSerializer, adapter: ActivityPub::Adapter, content_type: 'application/activity+json'
 | 
			
		||||
        render json: collection_presenter,
 | 
			
		||||
               serializer: ActivityPub::CollectionSerializer,
 | 
			
		||||
               adapter: ActivityPub::Adapter,
 | 
			
		||||
               content_type: 'application/activity+json'
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -10,7 +10,10 @@ class FollowingAccountsController < ApplicationController
 | 
			
		|||
      format.html
 | 
			
		||||
 | 
			
		||||
      format.json do
 | 
			
		||||
        render json: collection_presenter, serializer: ActivityPub::CollectionSerializer, adapter: ActivityPub::Adapter, content_type: 'application/activity+json'
 | 
			
		||||
        render json: collection_presenter,
 | 
			
		||||
               serializer: ActivityPub::CollectionSerializer,
 | 
			
		||||
               adapter: ActivityPub::Adapter,
 | 
			
		||||
               content_type: 'application/activity+json'
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -21,13 +21,19 @@ class StatusesController < ApplicationController
 | 
			
		|||
      end
 | 
			
		||||
 | 
			
		||||
      format.json do
 | 
			
		||||
        render json: @status, serializer: ActivityPub::NoteSerializer, adapter: ActivityPub::Adapter, content_type: 'application/activity+json'
 | 
			
		||||
        render json: @status,
 | 
			
		||||
               serializer: ActivityPub::NoteSerializer,
 | 
			
		||||
               adapter: ActivityPub::Adapter,
 | 
			
		||||
               content_type: 'application/activity+json'
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def activity
 | 
			
		||||
    render json: @status, serializer: ActivityPub::ActivitySerializer, adapter: ActivityPub::Adapter, content_type: 'application/activity+json'
 | 
			
		||||
    render json: @status,
 | 
			
		||||
           serializer: ActivityPub::ActivitySerializer,
 | 
			
		||||
           adapter: ActivityPub::Adapter,
 | 
			
		||||
           content_type: 'application/activity+json'
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def embed
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -12,7 +12,10 @@ class TagsController < ApplicationController
 | 
			
		|||
      format.html
 | 
			
		||||
 | 
			
		||||
      format.json do
 | 
			
		||||
        render json: collection_presenter, serializer: ActivityPub::CollectionSerializer, adapter: ActivityPub::Adapter, content_type: 'application/activity+json'
 | 
			
		||||
        render json: collection_presenter,
 | 
			
		||||
               serializer: ActivityPub::CollectionSerializer,
 | 
			
		||||
               adapter: ActivityPub::Adapter,
 | 
			
		||||
               content_type: 'application/activity+json'
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -86,15 +86,19 @@ class ActivityPub::Activity::Create < ActivityPub::Activity
 | 
			
		|||
  end
 | 
			
		||||
 | 
			
		||||
  def process_emoji(tag, _status)
 | 
			
		||||
    return if tag['name'].blank? || tag['href'].blank?
 | 
			
		||||
    return if skip_download?
 | 
			
		||||
    return if tag['name'].blank? || tag['icon'].blank? || tag['icon']['url'].blank?
 | 
			
		||||
 | 
			
		||||
    shortcode = tag['name'].delete(':')
 | 
			
		||||
    image_url = tag['icon']['url']
 | 
			
		||||
    uri       = tag['id']
 | 
			
		||||
    updated   = tag['updated']
 | 
			
		||||
    emoji     = CustomEmoji.find_by(shortcode: shortcode, domain: @account.domain)
 | 
			
		||||
 | 
			
		||||
    return if !emoji.nil? || skip_download?
 | 
			
		||||
    return unless emoji.nil? || emoji.updated_at >= updated
 | 
			
		||||
 | 
			
		||||
    emoji = CustomEmoji.new(domain: @account.domain, shortcode: shortcode)
 | 
			
		||||
    emoji.image_remote_url = tag['href']
 | 
			
		||||
    emoji ||= CustomEmoji.new(domain: @account.domain, shortcode: shortcode, uri: uri)
 | 
			
		||||
    emoji.image_remote_url = image_url
 | 
			
		||||
    emoji.save
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -33,6 +33,8 @@ class ActivityPub::TagManager
 | 
			
		|||
    when :note, :comment, :activity
 | 
			
		||||
      return activity_account_status_url(target.account, target) if target.reblog?
 | 
			
		||||
      account_status_url(target.account, target)
 | 
			
		||||
    when :emoji
 | 
			
		||||
      emoji_url(target)
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -13,6 +13,8 @@
 | 
			
		|||
#  created_at         :datetime         not null
 | 
			
		||||
#  updated_at         :datetime         not null
 | 
			
		||||
#  disabled           :boolean          default(FALSE), not null
 | 
			
		||||
#  uri                :string
 | 
			
		||||
#  image_remote_url   :string
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
class CustomEmoji < ApplicationRecord
 | 
			
		||||
| 
						 | 
				
			
			@ -37,6 +39,10 @@ class CustomEmoji < ApplicationRecord
 | 
			
		|||
    domain.nil?
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def object_type
 | 
			
		||||
    :emoji
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  class << self
 | 
			
		||||
    def from_text(text, domain)
 | 
			
		||||
      return [] if text.blank?
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -10,20 +10,6 @@ class ActivityPub::ActorSerializer < ActiveModel::Serializer
 | 
			
		|||
 | 
			
		||||
  has_one :public_key, serializer: ActivityPub::PublicKeySerializer
 | 
			
		||||
 | 
			
		||||
  class ImageSerializer < ActiveModel::Serializer
 | 
			
		||||
    include RoutingHelper
 | 
			
		||||
 | 
			
		||||
    attributes :type, :url
 | 
			
		||||
 | 
			
		||||
    def type
 | 
			
		||||
      'Image'
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def url
 | 
			
		||||
      full_asset_url(object.url(:original))
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  class EndpointsSerializer < ActiveModel::Serializer
 | 
			
		||||
    include RoutingHelper
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -36,8 +22,8 @@ class ActivityPub::ActorSerializer < ActiveModel::Serializer
 | 
			
		|||
 | 
			
		||||
  has_one :endpoints, serializer: EndpointsSerializer
 | 
			
		||||
 | 
			
		||||
  has_one :icon,  serializer: ImageSerializer, if: :avatar_exists?
 | 
			
		||||
  has_one :image, serializer: ImageSerializer, if: :header_exists?
 | 
			
		||||
  has_one :icon,  serializer: ActivityPub::ImageSerializer, if: :avatar_exists?
 | 
			
		||||
  has_one :image, serializer: ActivityPub::ImageSerializer, if: :header_exists?
 | 
			
		||||
 | 
			
		||||
  def id
 | 
			
		||||
    account_url(object)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										29
									
								
								app/serializers/activitypub/emoji_serializer.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								app/serializers/activitypub/emoji_serializer.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,29 @@
 | 
			
		|||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
class ActivityPub::EmojiSerializer < ActiveModel::Serializer
 | 
			
		||||
  include RoutingHelper
 | 
			
		||||
 | 
			
		||||
  attributes :id, :type, :name, :updated
 | 
			
		||||
 | 
			
		||||
  has_one :icon, serializer: ActivityPub::ImageSerializer
 | 
			
		||||
 | 
			
		||||
  def id
 | 
			
		||||
    ActivityPub::TagManager.instance.uri_for(object)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def type
 | 
			
		||||
    'Emoji'
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def icon
 | 
			
		||||
    object.image
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def updated
 | 
			
		||||
    object.updated_at.iso8601
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def name
 | 
			
		||||
    ":#{object.shortcode}:"
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										19
									
								
								app/serializers/activitypub/image_serializer.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								app/serializers/activitypub/image_serializer.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,19 @@
 | 
			
		|||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
class ActivityPub::ImageSerializer < ActiveModel::Serializer
 | 
			
		||||
  include RoutingHelper
 | 
			
		||||
 | 
			
		||||
  attributes :type, :media_type, :url
 | 
			
		||||
 | 
			
		||||
  def type
 | 
			
		||||
    'Image'
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def url
 | 
			
		||||
    full_asset_url(object.url(:original))
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def media_type
 | 
			
		||||
    object.content_type
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			@ -142,21 +142,6 @@ class ActivityPub::NoteSerializer < ActiveModel::Serializer
 | 
			
		|||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  class CustomEmojiSerializer < ActiveModel::Serializer
 | 
			
		||||
    include RoutingHelper
 | 
			
		||||
 | 
			
		||||
    attributes :type, :href, :name
 | 
			
		||||
 | 
			
		||||
    def type
 | 
			
		||||
      'Emoji'
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def href
 | 
			
		||||
      full_asset_url(object.image.url)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def name
 | 
			
		||||
      ":#{object.shortcode}:"
 | 
			
		||||
    end
 | 
			
		||||
  class CustomEmojiSerializer < ActivityPub::EmojiSerializer
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -96,8 +96,9 @@ Rails.application.routes.draw do
 | 
			
		|||
    resources :sessions, only: [:destroy]
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  resources :media, only: [:show]
 | 
			
		||||
  resources :tags,  only: [:show]
 | 
			
		||||
  resources :media,  only: [:show]
 | 
			
		||||
  resources :tags,   only: [:show]
 | 
			
		||||
  resources :emojis, only: [:show]
 | 
			
		||||
 | 
			
		||||
  get '/media_proxy/:id/(*any)', to: 'media_proxy#show', as: :media_proxy
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										6
									
								
								db/migrate/20171006142024_add_uri_to_custom_emojis.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								db/migrate/20171006142024_add_uri_to_custom_emojis.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,6 @@
 | 
			
		|||
class AddUriToCustomEmojis < ActiveRecord::Migration[5.1]
 | 
			
		||||
  def change
 | 
			
		||||
    add_column :custom_emojis, :uri, :string
 | 
			
		||||
    add_column :custom_emojis, :image_remote_url, :string
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			@ -10,7 +10,7 @@
 | 
			
		|||
#
 | 
			
		||||
# It's strongly recommended that you check this file into your version control system.
 | 
			
		||||
 | 
			
		||||
ActiveRecord::Schema.define(version: 20171005171936) do
 | 
			
		||||
ActiveRecord::Schema.define(version: 20171006142024) do
 | 
			
		||||
 | 
			
		||||
  # These are extensions that must be enabled in order to support this database
 | 
			
		||||
  enable_extension "plpgsql"
 | 
			
		||||
| 
						 | 
				
			
			@ -99,6 +99,8 @@ ActiveRecord::Schema.define(version: 20171005171936) do
 | 
			
		|||
    t.datetime "created_at", null: false
 | 
			
		||||
    t.datetime "updated_at", null: false
 | 
			
		||||
    t.boolean "disabled", default: false, null: false
 | 
			
		||||
    t.string "uri"
 | 
			
		||||
    t.string "image_remote_url"
 | 
			
		||||
    t.index ["shortcode", "domain"], name: "index_custom_emojis_on_shortcode_and_domain", unique: true
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -290,7 +290,9 @@ RSpec.describe ActivityPub::Activity::Create do
 | 
			
		|||
          tag: [
 | 
			
		||||
            {
 | 
			
		||||
              type: 'Emoji',
 | 
			
		||||
              href: 'http://example.com/emoji.png',
 | 
			
		||||
              icon: {
 | 
			
		||||
                url: 'http://example.com/emoji.png',
 | 
			
		||||
              },
 | 
			
		||||
              name: 'tinking',
 | 
			
		||||
            },
 | 
			
		||||
          ],
 | 
			
		||||
| 
						 | 
				
			
			@ -314,7 +316,9 @@ RSpec.describe ActivityPub::Activity::Create do
 | 
			
		|||
          tag: [
 | 
			
		||||
            {
 | 
			
		||||
              type: 'Emoji',
 | 
			
		||||
              href: 'http://example.com/emoji.png',
 | 
			
		||||
              icon: {
 | 
			
		||||
                url: 'http://example.com/emoji.png',
 | 
			
		||||
              },
 | 
			
		||||
            },
 | 
			
		||||
          ],
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			@ -326,7 +330,7 @@ RSpec.describe ActivityPub::Activity::Create do
 | 
			
		|||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    context 'with emojis missing href' do
 | 
			
		||||
    context 'with emojis missing icon' do
 | 
			
		||||
      let(:object_json) do
 | 
			
		||||
        {
 | 
			
		||||
          id: 'bar',
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		
		Reference in a new issue