Change multiple mentions with same username to render with domain (#15718)
Fix #15506
This commit is contained in:
		
							parent
							
								
									b3e9094e14
								
							
						
					
					
						commit
						7183d9a113
					
				@ -85,7 +85,7 @@ class Formatter
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def format_field(account, str, **options)
 | 
			
		||||
    html = account.local? ? encode_and_link_urls(str, me: true) : reformat(str)
 | 
			
		||||
    html = account.local? ? encode_and_link_urls(str, me: true, with_domain: true) : reformat(str)
 | 
			
		||||
    html = encode_custom_emojis(html, account.emojis, options[:autoplay]) if options[:custom_emojify]
 | 
			
		||||
    html.html_safe # rubocop:disable Rails/OutputSafety
 | 
			
		||||
  end
 | 
			
		||||
@ -122,7 +122,7 @@ class Formatter
 | 
			
		||||
      elsif entity[:hashtag]
 | 
			
		||||
        link_to_hashtag(entity)
 | 
			
		||||
      elsif entity[:screen_name]
 | 
			
		||||
        link_to_mention(entity, accounts)
 | 
			
		||||
        link_to_mention(entity, accounts, options)
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
@ -264,22 +264,37 @@ class Formatter
 | 
			
		||||
    encode(entity[:url])
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def link_to_mention(entity, linkable_accounts)
 | 
			
		||||
  def link_to_mention(entity, linkable_accounts, options = {})
 | 
			
		||||
    acct = entity[:screen_name]
 | 
			
		||||
 | 
			
		||||
    return link_to_account(acct) unless linkable_accounts
 | 
			
		||||
    return link_to_account(acct, options) unless linkable_accounts
 | 
			
		||||
 | 
			
		||||
    account = linkable_accounts.find { |item| TagManager.instance.same_acct?(item.acct, acct) }
 | 
			
		||||
    account ? mention_html(account) : "@#{encode(acct)}"
 | 
			
		||||
    same_username_hits = 0
 | 
			
		||||
    account = nil
 | 
			
		||||
    username, domain = acct.split('@')
 | 
			
		||||
    domain = nil if TagManager.instance.local_domain?(domain)
 | 
			
		||||
 | 
			
		||||
    linkable_accounts.each do |item|
 | 
			
		||||
      same_username = item.username.casecmp(username).zero?
 | 
			
		||||
      same_domain   = item.domain.nil? ? domain.nil? : item.domain.casecmp(domain).zero?
 | 
			
		||||
 | 
			
		||||
      if same_username && !same_domain
 | 
			
		||||
        same_username_hits += 1
 | 
			
		||||
      elsif same_username && same_domain
 | 
			
		||||
        account = item
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    account ? mention_html(account, with_domain: same_username_hits.positive? || options[:with_domain]) : "@#{encode(acct)}"
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def link_to_account(acct)
 | 
			
		||||
  def link_to_account(acct, options = {})
 | 
			
		||||
    username, domain = acct.split('@')
 | 
			
		||||
 | 
			
		||||
    domain  = nil if TagManager.instance.local_domain?(domain)
 | 
			
		||||
    account = EntityCache.instance.mention(username, domain)
 | 
			
		||||
 | 
			
		||||
    account ? mention_html(account) : "@#{encode(acct)}"
 | 
			
		||||
    account ? mention_html(account, with_domain: options[:with_domain]) : "@#{encode(acct)}"
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def link_to_hashtag(entity)
 | 
			
		||||
@ -300,7 +315,7 @@ class Formatter
 | 
			
		||||
    "<a href=\"#{encode(tag_url(tag))}\" class=\"mention hashtag\" rel=\"tag\">#<span>#{encode(tag)}</span></a>"
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def mention_html(account)
 | 
			
		||||
    "<span class=\"h-card\"><a href=\"#{encode(ActivityPub::TagManager.instance.url_for(account))}\" class=\"u-url mention\">@<span>#{encode(account.username)}</span></a></span>"
 | 
			
		||||
  def mention_html(account, with_domain: false)
 | 
			
		||||
    "<span class=\"h-card\"><a href=\"#{encode(ActivityPub::TagManager.instance.url_for(account))}\" class=\"u-url mention\">@<span>#{encode(with_domain ? account.pretty_acct : account.username)}</span></a></span>"
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
@ -22,14 +22,6 @@ class TagManager
 | 
			
		||||
    uri.normalized_host
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def same_acct?(canonical, needle)
 | 
			
		||||
    return true if canonical.casecmp(needle).zero?
 | 
			
		||||
 | 
			
		||||
    username, domain = needle.split('@')
 | 
			
		||||
 | 
			
		||||
    local_domain?(domain) && canonical.casecmp(username).zero?
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def local_url?(url)
 | 
			
		||||
    uri    = Addressable::URI.parse(url).normalize
 | 
			
		||||
    domain = uri.host + (uri.port ? ":#{uri.port}" : '')
 | 
			
		||||
 | 
			
		||||
@ -83,40 +83,4 @@ RSpec.describe TagManager do
 | 
			
		||||
      expect(TagManager.instance.local_url?('https://domainn.test/')).to eq false
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  describe '#same_acct?' do
 | 
			
		||||
    # The following comparisons MUST be case-insensitive.
 | 
			
		||||
 | 
			
		||||
    it 'returns true if the needle has a correct username and domain for remote user' do
 | 
			
		||||
      expect(TagManager.instance.same_acct?('username@domain.test', 'UsErNaMe@DoMaIn.Test')).to eq true
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it 'returns false if the needle is missing a domain for remote user' do
 | 
			
		||||
      expect(TagManager.instance.same_acct?('username@domain.test', 'UsErNaMe')).to eq false
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it 'returns false if the needle has an incorrect domain for remote user' do
 | 
			
		||||
      expect(TagManager.instance.same_acct?('username@domain.test', 'UsErNaMe@incorrect.test')).to eq false
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it 'returns false if the needle has an incorrect username for remote user' do
 | 
			
		||||
      expect(TagManager.instance.same_acct?('username@domain.test', 'incorrect@DoMaIn.test')).to eq false
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it 'returns true if the needle has a correct username and domain for local user' do
 | 
			
		||||
      expect(TagManager.instance.same_acct?('username', 'UsErNaMe@Cb6E6126.nGrOk.Io')).to eq true
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it 'returns true if the needle is missing a domain for local user' do
 | 
			
		||||
      expect(TagManager.instance.same_acct?('username', 'UsErNaMe')).to eq true
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it 'returns false if the needle has an incorrect username for local user' do
 | 
			
		||||
      expect(TagManager.instance.same_acct?('username', 'UsErNaM@Cb6E6126.nGrOk.Io')).to eq false
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it 'returns false if the needle has an incorrect domain for local user' do
 | 
			
		||||
      expect(TagManager.instance.same_acct?('username', 'incorrect@Cb6E6126.nGrOk.Io')).to eq false
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user