From 3a3475450e46f670e8beaf4bf804b820ad39a5f9 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Sat, 7 Oct 2017 17:43:42 +0200 Subject: [PATCH] Encode custom emojis as resolveable objects in ActivityPub (#5243) * Encode custom emojis as resolveable objects in ActivityPub * Improve code style --- app/controllers/accounts_controller.rb | 5 +++- app/controllers/emojis_controller.rb | 22 ++++++++++++++ .../follower_accounts_controller.rb | 5 +++- .../following_accounts_controller.rb | 5 +++- app/controllers/statuses_controller.rb | 10 +++++-- app/controllers/tags_controller.rb | 5 +++- app/lib/activitypub/activity/create.rb | 12 +++++--- app/lib/activitypub/tag_manager.rb | 2 ++ app/models/custom_emoji.rb | 6 ++++ .../activitypub/actor_serializer.rb | 18 ++---------- .../activitypub/emoji_serializer.rb | 29 +++++++++++++++++++ .../activitypub/image_serializer.rb | 19 ++++++++++++ .../activitypub/note_serializer.rb | 17 +---------- config/routes.rb | 5 ++-- ...20171006142024_add_uri_to_custom_emojis.rb | 6 ++++ db/schema.rb | 4 ++- spec/lib/activitypub/activity/create_spec.rb | 10 +++++-- 17 files changed, 132 insertions(+), 48 deletions(-) create mode 100644 app/controllers/emojis_controller.rb create mode 100644 app/serializers/activitypub/emoji_serializer.rb create mode 100644 app/serializers/activitypub/image_serializer.rb create mode 100644 db/migrate/20171006142024_add_uri_to_custom_emojis.rb diff --git a/app/controllers/accounts_controller.rb b/app/controllers/accounts_controller.rb index 26ab6636b5..75915b3371 100644 --- a/app/controllers/accounts_controller.rb +++ b/app/controllers/accounts_controller.rb @@ -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 diff --git a/app/controllers/emojis_controller.rb b/app/controllers/emojis_controller.rb new file mode 100644 index 0000000000..a82b9340bf --- /dev/null +++ b/app/controllers/emojis_controller.rb @@ -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 diff --git a/app/controllers/follower_accounts_controller.rb b/app/controllers/follower_accounts_controller.rb index 8eb4d28225..399e79665e 100644 --- a/app/controllers/follower_accounts_controller.rb +++ b/app/controllers/follower_accounts_controller.rb @@ -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 diff --git a/app/controllers/following_accounts_controller.rb b/app/controllers/following_accounts_controller.rb index 1ca6f0fe7d..1e73d4bd40 100644 --- a/app/controllers/following_accounts_controller.rb +++ b/app/controllers/following_accounts_controller.rb @@ -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 diff --git a/app/controllers/statuses_controller.rb b/app/controllers/statuses_controller.rb index 65206ea969..e8a360fb57 100644 --- a/app/controllers/statuses_controller.rb +++ b/app/controllers/statuses_controller.rb @@ -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 diff --git a/app/controllers/tags_controller.rb b/app/controllers/tags_controller.rb index 3001b2ee31..240ef058af 100644 --- a/app/controllers/tags_controller.rb +++ b/app/controllers/tags_controller.rb @@ -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 diff --git a/app/lib/activitypub/activity/create.rb b/app/lib/activitypub/activity/create.rb index be656de481..9421a0aa7e 100644 --- a/app/lib/activitypub/activity/create.rb +++ b/app/lib/activitypub/activity/create.rb @@ -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 diff --git a/app/lib/activitypub/tag_manager.rb b/app/lib/activitypub/tag_manager.rb index 4ec3b8c56e..0708713e64 100644 --- a/app/lib/activitypub/tag_manager.rb +++ b/app/lib/activitypub/tag_manager.rb @@ -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 diff --git a/app/models/custom_emoji.rb b/app/models/custom_emoji.rb index 258b50c82f..65d9840d56 100644 --- a/app/models/custom_emoji.rb +++ b/app/models/custom_emoji.rb @@ -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? diff --git a/app/serializers/activitypub/actor_serializer.rb b/app/serializers/activitypub/actor_serializer.rb index a11178f5ba..896d67115a 100644 --- a/app/serializers/activitypub/actor_serializer.rb +++ b/app/serializers/activitypub/actor_serializer.rb @@ -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) diff --git a/app/serializers/activitypub/emoji_serializer.rb b/app/serializers/activitypub/emoji_serializer.rb new file mode 100644 index 0000000000..7b06b1e5db --- /dev/null +++ b/app/serializers/activitypub/emoji_serializer.rb @@ -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 diff --git a/app/serializers/activitypub/image_serializer.rb b/app/serializers/activitypub/image_serializer.rb new file mode 100644 index 0000000000..a015c6b1b6 --- /dev/null +++ b/app/serializers/activitypub/image_serializer.rb @@ -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 diff --git a/app/serializers/activitypub/note_serializer.rb b/app/serializers/activitypub/note_serializer.rb index 4dbf6a4444..24c39f3c96 100644 --- a/app/serializers/activitypub/note_serializer.rb +++ b/app/serializers/activitypub/note_serializer.rb @@ -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 diff --git a/config/routes.rb b/config/routes.rb index cc1f66e52a..bd7068b5c8 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -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 diff --git a/db/migrate/20171006142024_add_uri_to_custom_emojis.rb b/db/migrate/20171006142024_add_uri_to_custom_emojis.rb new file mode 100644 index 0000000000..04dfcf397c --- /dev/null +++ b/db/migrate/20171006142024_add_uri_to_custom_emojis.rb @@ -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 diff --git a/db/schema.rb b/db/schema.rb index 3358e29979..7180d35158 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -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 diff --git a/spec/lib/activitypub/activity/create_spec.rb b/spec/lib/activitypub/activity/create_spec.rb index cdd4991505..3c3991c13f 100644 --- a/spec/lib/activitypub/activity/create_spec.rb +++ b/spec/lib/activitypub/activity/create_spec.rb @@ -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',