about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEugen Rochko <eugen@zeonfederated.com>2017-10-07 17:43:42 +0200
committerGitHub <noreply@github.com>2017-10-07 17:43:42 +0200
commit3a3475450e46f670e8beaf4bf804b820ad39a5f9 (patch)
tree60600a840e74668818db64d5d55be2f4a0601fb3
parent057db0ecd0049c76c113cbe5412e098d686f0700 (diff)
Encode custom emojis as resolveable objects in ActivityPub (#5243)
* Encode custom emojis as resolveable objects in ActivityPub

* Improve code style
-rw-r--r--app/controllers/accounts_controller.rb5
-rw-r--r--app/controllers/emojis_controller.rb22
-rw-r--r--app/controllers/follower_accounts_controller.rb5
-rw-r--r--app/controllers/following_accounts_controller.rb5
-rw-r--r--app/controllers/statuses_controller.rb10
-rw-r--r--app/controllers/tags_controller.rb5
-rw-r--r--app/lib/activitypub/activity/create.rb12
-rw-r--r--app/lib/activitypub/tag_manager.rb2
-rw-r--r--app/models/custom_emoji.rb6
-rw-r--r--app/serializers/activitypub/actor_serializer.rb18
-rw-r--r--app/serializers/activitypub/emoji_serializer.rb29
-rw-r--r--app/serializers/activitypub/image_serializer.rb19
-rw-r--r--app/serializers/activitypub/note_serializer.rb17
-rw-r--r--config/routes.rb5
-rw-r--r--db/migrate/20171006142024_add_uri_to_custom_emojis.rb6
-rw-r--r--db/schema.rb4
-rw-r--r--spec/lib/activitypub/activity/create_spec.rb10
17 files changed, 132 insertions, 48 deletions
diff --git a/app/controllers/accounts_controller.rb b/app/controllers/accounts_controller.rb
index 26ab6636b..75915b337 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 000000000..a82b9340b
--- /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 8eb4d2822..399e79665 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 1ca6f0fe7..1e73d4bd4 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 65206ea96..e8a360fb5 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 3001b2ee3..240ef058a 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 be656de48..9421a0aa7 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 4ec3b8c56..0708713e6 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 258b50c82..65d9840d5 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 a11178f5b..896d67115 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 000000000..7b06b1e5d
--- /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 000000000..a015c6b1b
--- /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 4dbf6a444..24c39f3c9 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 cc1f66e52..bd7068b5c 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 000000000..04dfcf397
--- /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 3358e2997..7180d3515 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 cdd499150..3c3991c13 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',