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
parent ea82a96b47
commit 8dcf7b224c
No known key found for this signature in database
GPG key ID: EC22E476DC2D3D84
3 changed files with 58 additions and 13 deletions

View file

@ -176,4 +176,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}"}") Rails.logger.info("Rejected #{@json['type']} activity #{@json['id']} from #{@account.uri}#{@options[:relayed_through_actor] && "via #{@options[:relayed_through_actor].uri}"}")
nil nil
end 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 end

View file

@ -5,9 +5,16 @@ class ActivityPub::Activity::EmojiReact < ActivityPub::Activity
original_status = status_from_uri(object_uri) original_status = status_from_uri(object_uri)
name = @json['content'] name = @json['content']
return if original_status.nil? || return if original_status.nil? ||
!original_status.account.local? || !original_status.account.local? ||
delete_arrived_first?(@json['id']) || delete_arrived_first?(@json['id']) ||
@account.reacted?(original_status, name) @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) 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) original_status = status_from_uri(object_uri)
return if original_status.nil? || !original_status.account.local? || delete_arrived_first?(@json['id']) 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 return if maybe_process_misskey_reaction(original_status)
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 @account.favourited?(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') LocalNotificationWorker.perform_async(original_status.account_id, favourite.id, 'Favourite', 'favourite')
Trends.statuses.register(original_status) Trends.statuses.register(original_status)
end 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 end