diff --git a/app/controllers/activitypub/inboxes_controller.rb b/app/controllers/activitypub/inboxes_controller.rb
index 8f5e1887ea..1501b914ec 100644
--- a/app/controllers/activitypub/inboxes_controller.rb
+++ b/app/controllers/activitypub/inboxes_controller.rb
@@ -2,11 +2,14 @@
class ActivityPub::InboxesController < Api::BaseController
include SignatureVerification
+ include JsonLdHelper
before_action :set_account
def create
- if signed_request_account
+ if unknown_deleted_account?
+ head 202
+ elsif signed_request_account
upgrade_account
process_payload
head 202
@@ -17,12 +20,19 @@ class ActivityPub::InboxesController < Api::BaseController
private
+ def unknown_deleted_account?
+ json = Oj.load(body, mode: :strict)
+ json['type'] == 'Delete' && json['actor'].present? && json['actor'] == value_or_id(json['object']) && !Account.where(uri: json['actor']).exists?
+ rescue Oj::ParseError
+ false
+ end
+
def set_account
@account = Account.find_local!(params[:account_username]) if params[:account_username]
end
def body
- @body ||= request.body.read
+ @body ||= request.body.read.force_encoding('UTF-8')
end
def upgrade_account
@@ -36,6 +46,6 @@ class ActivityPub::InboxesController < Api::BaseController
end
def process_payload
- ActivityPub::ProcessingWorker.perform_async(signed_request_account.id, body.force_encoding('UTF-8'), @account&.id)
+ ActivityPub::ProcessingWorker.perform_async(signed_request_account.id, body, @account&.id)
end
end
diff --git a/app/javascript/mastodon/actions/importer/normalizer.js b/app/javascript/mastodon/actions/importer/normalizer.js
index ea80c0efb3..5badb0c49e 100644
--- a/app/javascript/mastodon/actions/importer/normalizer.js
+++ b/app/javascript/mastodon/actions/importer/normalizer.js
@@ -71,9 +71,11 @@ export function normalizeStatus(status, normalOldStatus) {
export function normalizePoll(poll) {
const normalPoll = { ...poll };
+ const emojiMap = makeEmojiMap(normalPoll);
+
normalPoll.options = poll.options.map(option => ({
...option,
- title_emojified: emojify(escapeTextContentForBrowser(option.title)),
+ title_emojified: emojify(escapeTextContentForBrowser(option.title), emojiMap),
}));
return normalPoll;
diff --git a/app/javascript/mastodon/components/poll.js b/app/javascript/mastodon/components/poll.js
index a1b297ce75..56331cb290 100644
--- a/app/javascript/mastodon/components/poll.js
+++ b/app/javascript/mastodon/components/poll.js
@@ -44,6 +44,11 @@ const timeRemainingString = (intl, date, now) => {
return relativeTime;
};
+const makeEmojiMap = record => record.get('emojis').reduce((obj, emoji) => {
+ obj[`:${emoji.get('shortcode')}:`] = emoji.toJS();
+ return obj;
+}, {});
+
export default @injectIntl
class Poll extends ImmutablePureComponent {
@@ -99,6 +104,12 @@ class Poll extends ImmutablePureComponent {
const active = !!this.state.selected[`${optionIndex}`];
const showResults = poll.get('voted') || poll.get('expired');
+ let titleEmojified = option.get('title_emojified');
+ if (!titleEmojified) {
+ const emojiMap = makeEmojiMap(poll);
+ titleEmojified = emojify(escapeTextContentForBrowser(option.get('title')), emojiMap);
+ }
+
return (
{showResults && (
@@ -122,7 +133,7 @@ class Poll extends ImmutablePureComponent {
{!showResults && }
{showResults && {Math.round(percent)}%}
-
+
);
diff --git a/app/lib/formatter.rb b/app/lib/formatter.rb
index 464e1ee7e8..aadf03b2ac 100644
--- a/app/lib/formatter.rb
+++ b/app/lib/formatter.rb
@@ -71,6 +71,12 @@ class Formatter
html.html_safe # rubocop:disable Rails/OutputSafety
end
+ def format_poll_option(status, option, **options)
+ html = encode(option.title)
+ html = encode_custom_emojis(html, status.emojis, options[:autoplay])
+ html.html_safe # rubocop:disable Rails/OutputSafety
+ end
+
def format_display_name(account, **options)
html = encode(account.display_name.presence || account.username)
html = encode_custom_emojis(html, account.emojis, options[:autoplay]) if options[:custom_emojify]
diff --git a/app/models/poll.rb b/app/models/poll.rb
index 6df2303370..8f72c7b112 100644
--- a/app/models/poll.rb
+++ b/app/models/poll.rb
@@ -60,6 +60,10 @@ class Poll < ApplicationRecord
!local?
end
+ def emojis
+ @emojis ||= CustomEmoji.from_text(options.join(' '), account.domain)
+ end
+
class Option < ActiveModelSerializers::Model
attributes :id, :title, :votes_count, :poll
diff --git a/app/models/status.rb b/app/models/status.rb
index 95f3368205..c049401e89 100644
--- a/app/models/status.rb
+++ b/app/models/status.rb
@@ -218,7 +218,11 @@ class Status < ApplicationRecord
end
def emojis
- @emojis ||= CustomEmoji.from_text([spoiler_text, text].join(' '), account.domain)
+ return @emojis if defined?(@emojis)
+ fields = [spoiler_text, text]
+ fields += owned_poll.options unless owned_poll.nil?
+ @emojis = CustomEmoji.from_text(fields.join(' '), account.domain)
+ @emojis
end
def mark_for_mass_destruction!
diff --git a/app/serializers/rest/poll_serializer.rb b/app/serializers/rest/poll_serializer.rb
index 4dae1c09f4..356c45b838 100644
--- a/app/serializers/rest/poll_serializer.rb
+++ b/app/serializers/rest/poll_serializer.rb
@@ -5,6 +5,7 @@ class REST::PollSerializer < ActiveModel::Serializer
:multiple, :votes_count
has_many :loaded_options, key: :options
+ has_many :emojis, serializer: REST::CustomEmojiSerializer
attribute :voted, if: :current_user?
diff --git a/app/views/stream_entries/_detailed_status.html.haml b/app/views/stream_entries/_detailed_status.html.haml
index b19d2452ad..d18ecd37a4 100644
--- a/app/views/stream_entries/_detailed_status.html.haml
+++ b/app/views/stream_entries/_detailed_status.html.haml
@@ -24,7 +24,7 @@
- if status.poll
= react_component :poll, disabled: true, poll: ActiveModelSerializers::SerializableResource.new(status.poll, serializer: REST::PollSerializer, scope: current_user, scope_name: :current_user).as_json do
- = render partial: 'stream_entries/poll', locals: { poll: status.poll }
+ = render partial: 'stream_entries/poll', locals: { status: status, poll: status.poll, autoplay: autoplay }
- elsif !status.media_attachments.empty?
- if status.media_attachments.first.video?
- video = status.media_attachments.first
diff --git a/app/views/stream_entries/_poll.html.haml b/app/views/stream_entries/_poll.html.haml
index d6b2c0cd91..ba34890dfe 100644
--- a/app/views/stream_entries/_poll.html.haml
+++ b/app/views/stream_entries/_poll.html.haml
@@ -10,11 +10,11 @@
%label.poll__text><
%span.poll__number= percent.round
- = option.title
+ = Formatter.instance.format_poll_option(status, option, autoplay: autoplay)
- else
%label.poll__text><
%span.poll__input{ class: poll.multiple? ? 'checkbox' : nil}><
- = option.title
+ = Formatter.instance.format_poll_option(status, option, autoplay: autoplay)
.poll__footer
- unless show_results
%button.button.button-secondary{ disabled: true }
diff --git a/app/views/stream_entries/_simple_status.html.haml b/app/views/stream_entries/_simple_status.html.haml
index d3441ca904..1952128a09 100644
--- a/app/views/stream_entries/_simple_status.html.haml
+++ b/app/views/stream_entries/_simple_status.html.haml
@@ -29,7 +29,7 @@
- if status.poll
= react_component :poll, disabled: true, poll: ActiveModelSerializers::SerializableResource.new(status.poll, serializer: REST::PollSerializer, scope: current_user, scope_name: :current_user).as_json do
- = render partial: 'stream_entries/poll', locals: { poll: status.poll }
+ = render partial: 'stream_entries/poll', locals: { status: status, poll: status.poll, autoplay: autoplay }
- elsif !status.media_attachments.empty?
- if status.media_attachments.first.video?
- video = status.media_attachments.first
diff --git a/spec/controllers/activitypub/inboxes_controller_spec.rb b/spec/controllers/activitypub/inboxes_controller_spec.rb
index 4055d93424..eab4b8c3e6 100644
--- a/spec/controllers/activitypub/inboxes_controller_spec.rb
+++ b/spec/controllers/activitypub/inboxes_controller_spec.rb
@@ -10,7 +10,7 @@ RSpec.describe ActivityPub::InboxesController, type: :controller do
Fabricate(:account)
end
- post :create
+ post :create, body: '{}'
expect(response).to have_http_status(202)
end
end
@@ -21,7 +21,7 @@ RSpec.describe ActivityPub::InboxesController, type: :controller do
false
end
- post :create
+ post :create, body: '{}'
expect(response).to have_http_status(401)
end
end