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:
		| @@ -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', | ||||
|   | ||||
		Reference in New Issue
	
	Block a user