commit: 3a3475450e46f670e8beaf4bf804b820ad39a5f9
parent: 057db0ecd0049c76c113cbe5412e098d686f0700
Author: Eugen Rochko <eugen@zeonfederated.com>
Date: Sat, 7 Oct 2017 17:43:42 +0200
Encode custom emojis as resolveable objects in ActivityPub (#5243)
* Encode custom emojis as resolveable objects in ActivityPub
* Improve code style
Diffstat:
17 files changed, 132 insertions(+), 48 deletions(-)
diff --git 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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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',