download remote custom emojis from reactions

Emoji reactions containing custom emojis from
remote instances were assumed to already have
been downloaded and stored in the database.
This might obviously not be the case.
This commit is contained in:
fef 2022-12-02 17:02:06 +00:00 committed by neatchee
parent 613d247a0a
commit 751909d348
3 changed files with 58 additions and 13 deletions

View File

@ -178,4 +178,30 @@ class ActivityPub::Activity
Rails.logger.info("Rejected #{@json['type']} activity #{@json['id']} from #{@account.uri}#{@options[:relayed_through_actor] && "via #{@options[:relayed_through_actor].uri}"}")
nil
end
# Ensure all emojis declared in the activity's tags are
# present in the database and downloaded to the local cache.
def process_emoji_tags
as_array(@object['tag']).each do |tag|
process_single_emoji(tag) if tag['type'] == 'Emoji'
end
end
def process_single_emoji(tag)
parser = ActivityPub::Parser::CustomEmojiParser.new(tag)
return if parser.shortcode.blank? || parser.image_remote_url.blank?
emoji = CustomEmoji.find_by(shortcode: parser.shortcode, domain: @account.domain)
return unless emoji.nil? ||
parser.image_remote_url != emoji.image_remote_url ||
(parser.updated_at && parser.updated_at >= emoji.updated_at)
begin
emoji ||= CustomEmoji.new(domain: @account.domain, shortcode: parser.shortcode, uri: parser.uri)
emoji.image_remote_url = parser.image_remote_url
emoji.save
rescue Seahorse::Client::NetworkingError => e
Rails.logger.warn "Error fetching emoji: #{e}"
end
end
end

View File

@ -5,9 +5,16 @@ class ActivityPub::Activity::EmojiReact < ActivityPub::Activity
original_status = status_from_uri(object_uri)
name = @json['content']
return if original_status.nil? ||
!original_status.account.local? ||
delete_arrived_first?(@json['id']) ||
@account.reacted?(original_status, name)
!original_status.account.local? ||
delete_arrived_first?(@json['id']) ||
@account.reacted?(original_status, name)
if name =~ /^:.*:$/
process_emoji_tags
name.delete! ':'
return if CustomEmoji.find_by(shortcode: name, domain: @account.domain).nil?
end
reaction = original_status.status_reactions.create!(account: @account, name: name)

View File

@ -5,16 +5,7 @@ class ActivityPub::Activity::Like < ActivityPub::Activity
original_status = status_from_uri(object_uri)
return if original_status.nil? || !original_status.account.local? || delete_arrived_first?(@json['id'])
# misskey delivers reactions as likes and attaches the emoji in _misskey_reaction
mk_reaction = @json['_misskey_reaction']
unless mk_reaction.nil?
custom_emoji = CustomEmoji.find_by(shortcode: mk_reaction, domain: @account.domain)
return if @account.reacted?(original_status, mk_reaction, custom_emoji)
reaction = original_status.status_reactions.create!(account: @account, name: mk_reaction, custom_emoji: custom_emoji)
LocalNotificationWorker.perform_async(original_status.account_id, reaction.id, 'StatusReaction', 'reaction')
return
end
return if maybe_process_misskey_reaction(original_status)
return if @account.favourited?(original_status)
@ -23,4 +14,25 @@ class ActivityPub::Activity::Like < ActivityPub::Activity
LocalNotificationWorker.perform_async(original_status.account_id, favourite.id, 'Favourite', 'favourite')
Trends.statuses.register(original_status)
end
# Misskey delivers reactions as likes with the emoji in _misskey_reaction
# see https://misskey-hub.net/ns.html#misskey-reaction for details
def maybe_process_misskey_reaction(original_status)
name = @json['_misskey_reaction']
return false if name.nil?
custom_emoji = nil
if name =~ /^:.*:$/
process_emoji_tags
name.delete! ':'
custom_emoji = CustomEmoji.find_by(shortcode: name, domain: @account.domain)
return false if custom_emoji.nil? # invalid custom emoji, treat it as a regular like
end
return true if @account.reacted?(original_status, name, custom_emoji)
reaction = original_status.status_reactions.create!(account: @account, name: name, custom_emoji: custom_emoji)
LocalNotificationWorker.perform_async(original_status.account_id, reaction.id, 'StatusReaction', 'reaction')
return true
end
end