mirror of
https://github.com/glitch-soc/mastodon.git
synced 2025-12-14 00:08:46 +00:00
Merge commit 'aedc5f692144aa36245fe47c277bb5ad4766a335' into glitch-soc/merge-upstream
This commit is contained in:
@@ -620,7 +620,7 @@ GEM
|
|||||||
psych (5.2.3)
|
psych (5.2.3)
|
||||||
date
|
date
|
||||||
stringio
|
stringio
|
||||||
public_suffix (6.0.1)
|
public_suffix (6.0.2)
|
||||||
puma (6.6.0)
|
puma (6.6.0)
|
||||||
nio4r (~> 2.0)
|
nio4r (~> 2.0)
|
||||||
pundit (2.5.0)
|
pundit (2.5.0)
|
||||||
@@ -743,7 +743,7 @@ GEM
|
|||||||
rspec-mocks (~> 3.0)
|
rspec-mocks (~> 3.0)
|
||||||
sidekiq (>= 5, < 9)
|
sidekiq (>= 5, < 9)
|
||||||
rspec-support (3.13.3)
|
rspec-support (3.13.3)
|
||||||
rubocop (1.75.4)
|
rubocop (1.75.5)
|
||||||
json (~> 2.3)
|
json (~> 2.3)
|
||||||
language_server-protocol (~> 3.17.0.2)
|
language_server-protocol (~> 3.17.0.2)
|
||||||
lint_roller (~> 1.1.0)
|
lint_roller (~> 1.1.0)
|
||||||
@@ -800,7 +800,7 @@ GEM
|
|||||||
activerecord (>= 4.0.0)
|
activerecord (>= 4.0.0)
|
||||||
railties (>= 4.0.0)
|
railties (>= 4.0.0)
|
||||||
securerandom (0.4.1)
|
securerandom (0.4.1)
|
||||||
selenium-webdriver (4.31.0)
|
selenium-webdriver (4.32.0)
|
||||||
base64 (~> 0.2)
|
base64 (~> 0.2)
|
||||||
logger (~> 1.4)
|
logger (~> 1.4)
|
||||||
rexml (~> 3.2, >= 3.2.5)
|
rexml (~> 3.2, >= 3.2.5)
|
||||||
|
|||||||
@@ -72,6 +72,18 @@ module JsonLdHelper
|
|||||||
!haystack.casecmp(needle).zero?
|
!haystack.casecmp(needle).zero?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def safe_prefetched_embed(account, object, context)
|
||||||
|
return unless object.is_a?(Hash)
|
||||||
|
|
||||||
|
# NOTE: Replacing the object's context by that of the parent activity is
|
||||||
|
# not sound, but it's consistent with the rest of the codebase
|
||||||
|
object = object.merge({ '@context' => context })
|
||||||
|
|
||||||
|
return if value_or_id(first_of_value(object['attributedTo'])) != account.uri || non_matching_uri_hosts?(account.uri, object['id'])
|
||||||
|
|
||||||
|
object
|
||||||
|
end
|
||||||
|
|
||||||
def canonicalize(json)
|
def canonicalize(json)
|
||||||
graph = RDF::Graph.new << JSON::LD::API.toRdf(json, documentLoader: method(:load_jsonld_context))
|
graph = RDF::Graph.new << JSON::LD::API.toRdf(json, documentLoader: method(:load_jsonld_context))
|
||||||
graph.dump(:normalize)
|
graph.dump(:normalize)
|
||||||
|
|||||||
@@ -19,14 +19,17 @@
|
|||||||
"account.block_domain": "Blokuoti serverį {domain}",
|
"account.block_domain": "Blokuoti serverį {domain}",
|
||||||
"account.block_short": "Blokuoti",
|
"account.block_short": "Blokuoti",
|
||||||
"account.blocked": "Užblokuota",
|
"account.blocked": "Užblokuota",
|
||||||
|
"account.blocking": "Blokavimas",
|
||||||
"account.cancel_follow_request": "Atšaukti sekimą",
|
"account.cancel_follow_request": "Atšaukti sekimą",
|
||||||
"account.copy": "Kopijuoti nuorodą į profilį",
|
"account.copy": "Kopijuoti nuorodą į profilį",
|
||||||
"account.direct": "Privačiai paminėti @{name}",
|
"account.direct": "Privačiai paminėti @{name}",
|
||||||
"account.disable_notifications": "Nustoti man pranešti, kai @{name} paskelbia",
|
"account.disable_notifications": "Nustoti man pranešti, kai @{name} paskelbia",
|
||||||
|
"account.domain_blocking": "Blokuoti domeną",
|
||||||
"account.edit_profile": "Redaguoti profilį",
|
"account.edit_profile": "Redaguoti profilį",
|
||||||
"account.enable_notifications": "Pranešti man, kai @{name} paskelbia",
|
"account.enable_notifications": "Pranešti man, kai @{name} paskelbia",
|
||||||
"account.endorse": "Rodyti profilyje",
|
"account.endorse": "Rodyti profilyje",
|
||||||
"account.featured": "Rodomi",
|
"account.featured": "Rodomi",
|
||||||
|
"account.featured.accounts": "Profiliai",
|
||||||
"account.featured.hashtags": "Saitažodžiai",
|
"account.featured.hashtags": "Saitažodžiai",
|
||||||
"account.featured.posts": "Įrašai",
|
"account.featured.posts": "Įrašai",
|
||||||
"account.featured_tags.last_status_at": "Paskutinis įrašas {date}",
|
"account.featured_tags.last_status_at": "Paskutinis įrašas {date}",
|
||||||
@@ -39,6 +42,7 @@
|
|||||||
"account.following": "Sekama",
|
"account.following": "Sekama",
|
||||||
"account.following_counter": "{count, plural, one {{counter} sekimas} few {{counter} sekimai} many {{counter} sekimo} other {{counter} sekimų}}",
|
"account.following_counter": "{count, plural, one {{counter} sekimas} few {{counter} sekimai} many {{counter} sekimo} other {{counter} sekimų}}",
|
||||||
"account.follows.empty": "Šis naudotojas dar nieko neseka.",
|
"account.follows.empty": "Šis naudotojas dar nieko neseka.",
|
||||||
|
"account.follows_you": "Seka tave",
|
||||||
"account.go_to_profile": "Eiti į profilį",
|
"account.go_to_profile": "Eiti į profilį",
|
||||||
"account.hide_reblogs": "Slėpti pasidalinimus iš @{name}",
|
"account.hide_reblogs": "Slėpti pasidalinimus iš @{name}",
|
||||||
"account.in_memoriam": "Atminimui.",
|
"account.in_memoriam": "Atminimui.",
|
||||||
@@ -53,6 +57,8 @@
|
|||||||
"account.mute_notifications_short": "Nutildyti pranešimus",
|
"account.mute_notifications_short": "Nutildyti pranešimus",
|
||||||
"account.mute_short": "Nutildyti",
|
"account.mute_short": "Nutildyti",
|
||||||
"account.muted": "Nutildytas",
|
"account.muted": "Nutildytas",
|
||||||
|
"account.muting": "Užtildymas",
|
||||||
|
"account.mutual": "Jūs sekate vienas kitą",
|
||||||
"account.no_bio": "Nėra pateikto aprašymo.",
|
"account.no_bio": "Nėra pateikto aprašymo.",
|
||||||
"account.open_original_page": "Atidaryti originalų puslapį",
|
"account.open_original_page": "Atidaryti originalų puslapį",
|
||||||
"account.posts": "Įrašai",
|
"account.posts": "Įrašai",
|
||||||
@@ -61,6 +67,7 @@
|
|||||||
"account.report": "Pranešti apie @{name}",
|
"account.report": "Pranešti apie @{name}",
|
||||||
"account.requested": "Laukiama patvirtinimo. Spustelėk, kad atšauktum sekimo prašymą",
|
"account.requested": "Laukiama patvirtinimo. Spustelėk, kad atšauktum sekimo prašymą",
|
||||||
"account.requested_follow": "{name} paprašė tave sekti",
|
"account.requested_follow": "{name} paprašė tave sekti",
|
||||||
|
"account.requests_to_follow_you": "Prašymai sekti jus",
|
||||||
"account.share": "Bendrinti @{name} profilį",
|
"account.share": "Bendrinti @{name} profilį",
|
||||||
"account.show_reblogs": "Rodyti pasidalinimus iš @{name}",
|
"account.show_reblogs": "Rodyti pasidalinimus iš @{name}",
|
||||||
"account.statuses_counter": "{count, plural, one {{counter} įrašas} few {{counter} įrašai} many {{counter} įrašo} other {{counter} įrašų}}",
|
"account.statuses_counter": "{count, plural, one {{counter} įrašas} few {{counter} įrašai} many {{counter} įrašo} other {{counter} įrašų}}",
|
||||||
@@ -255,6 +262,7 @@
|
|||||||
"disabled_account_banner.text": "Tavo paskyra {disabledAccount} šiuo metu išjungta.",
|
"disabled_account_banner.text": "Tavo paskyra {disabledAccount} šiuo metu išjungta.",
|
||||||
"dismissable_banner.community_timeline": "Tai – naujausi vieši įrašai iš žmonių, kurių paskyros talpinamos {domain}.",
|
"dismissable_banner.community_timeline": "Tai – naujausi vieši įrašai iš žmonių, kurių paskyros talpinamos {domain}.",
|
||||||
"dismissable_banner.dismiss": "Atmesti",
|
"dismissable_banner.dismiss": "Atmesti",
|
||||||
|
"dismissable_banner.explore_links": "Šiomis naujienų istorijomis šiandien \"Fediverse\" dalijamasi dažniausiai. Naujesnės istorijos, kurias paskelbė daugiau skirtingų žmonių, užima aukštesnę vietą.",
|
||||||
"domain_block_modal.block": "Blokuoti serverį",
|
"domain_block_modal.block": "Blokuoti serverį",
|
||||||
"domain_block_modal.block_account_instead": "Blokuoti @{name} vietoj to",
|
"domain_block_modal.block_account_instead": "Blokuoti @{name} vietoj to",
|
||||||
"domain_block_modal.they_can_interact_with_old_posts": "Žmonės iš šio serverio gali bendrauti su tavo senomis įrašomis.",
|
"domain_block_modal.they_can_interact_with_old_posts": "Žmonės iš šio serverio gali bendrauti su tavo senomis įrašomis.",
|
||||||
|
|||||||
@@ -26,6 +26,8 @@
|
|||||||
"account.edit_profile": "Upraviť profil",
|
"account.edit_profile": "Upraviť profil",
|
||||||
"account.enable_notifications": "Zapnúť upozornenia na príspevky od @{name}",
|
"account.enable_notifications": "Zapnúť upozornenia na príspevky od @{name}",
|
||||||
"account.endorse": "Zobraziť na vlastnom profile",
|
"account.endorse": "Zobraziť na vlastnom profile",
|
||||||
|
"account.featured.accounts": "Profily",
|
||||||
|
"account.featured.hashtags": "Hashtagy",
|
||||||
"account.featured.posts": "Príspevky",
|
"account.featured.posts": "Príspevky",
|
||||||
"account.featured_tags.last_status_at": "Posledný príspevok dňa {date}",
|
"account.featured_tags.last_status_at": "Posledný príspevok dňa {date}",
|
||||||
"account.featured_tags.last_status_never": "Žiadne príspevky",
|
"account.featured_tags.last_status_never": "Žiadne príspevky",
|
||||||
@@ -37,6 +39,7 @@
|
|||||||
"account.following": "Sledovaný účet",
|
"account.following": "Sledovaný účet",
|
||||||
"account.following_counter": "{count, plural, one {{counter} sledovaných} other {{counter} sledovaných}}",
|
"account.following_counter": "{count, plural, one {{counter} sledovaných} other {{counter} sledovaných}}",
|
||||||
"account.follows.empty": "Tento účet ešte nikoho nesleduje.",
|
"account.follows.empty": "Tento účet ešte nikoho nesleduje.",
|
||||||
|
"account.follows_you": "Nasleduje ťa",
|
||||||
"account.go_to_profile": "Prejsť na profil",
|
"account.go_to_profile": "Prejsť na profil",
|
||||||
"account.hide_reblogs": "Skryť zdieľania od @{name}",
|
"account.hide_reblogs": "Skryť zdieľania od @{name}",
|
||||||
"account.in_memoriam": "In memoriam.",
|
"account.in_memoriam": "In memoriam.",
|
||||||
@@ -208,6 +211,7 @@
|
|||||||
"confirmations.redraft.confirm": "Vymazať a prepísať",
|
"confirmations.redraft.confirm": "Vymazať a prepísať",
|
||||||
"confirmations.redraft.message": "Určite chcete tento príspevok vymazať a prepísať? Prídete o jeho zdieľania a ohviezdičkovania a odpovede na pôvodný príspevok budú odlúčené.",
|
"confirmations.redraft.message": "Určite chcete tento príspevok vymazať a prepísať? Prídete o jeho zdieľania a ohviezdičkovania a odpovede na pôvodný príspevok budú odlúčené.",
|
||||||
"confirmations.redraft.title": "Vymazať a prepísať príspevok?",
|
"confirmations.redraft.title": "Vymazať a prepísať príspevok?",
|
||||||
|
"confirmations.remove_from_followers.confirm": "Odstrániť nasledovateľa",
|
||||||
"confirmations.reply.confirm": "Odpovedať",
|
"confirmations.reply.confirm": "Odpovedať",
|
||||||
"confirmations.reply.message": "Odpovedaním akurát teraz prepíšeš správu, ktorú máš práve rozpísanú. Si si istý/á, že chceš pokračovať?",
|
"confirmations.reply.message": "Odpovedaním akurát teraz prepíšeš správu, ktorú máš práve rozpísanú. Si si istý/á, že chceš pokračovať?",
|
||||||
"confirmations.reply.title": "Prepísať príspevok?",
|
"confirmations.reply.title": "Prepísať príspevok?",
|
||||||
|
|||||||
@@ -204,7 +204,9 @@ class ActivityPub::Activity::Create < ActivityPub::Activity
|
|||||||
|
|
||||||
@quote.status = status
|
@quote.status = status
|
||||||
@quote.save
|
@quote.save
|
||||||
ActivityPub::VerifyQuoteService.new.call(@quote, fetchable_quoted_uri: @quote_uri, request_id: @options[:request_id])
|
|
||||||
|
embedded_quote = safe_prefetched_embed(@account, @status_parser.quoted_object, @json['context'])
|
||||||
|
ActivityPub::VerifyQuoteService.new.call(@quote, fetchable_quoted_uri: @quote_uri, prefetched_quoted_object: embedded_quote, request_id: @options[:request_id])
|
||||||
rescue Mastodon::UnexpectedResponseError, *Mastodon::HTTP_CONNECTION_ERRORS
|
rescue Mastodon::UnexpectedResponseError, *Mastodon::HTTP_CONNECTION_ERRORS
|
||||||
ActivityPub::RefetchAndVerifyQuoteWorker.perform_in(rand(30..600).seconds, @quote.id, @quote_uri, { 'request_id' => @options[:request_id] })
|
ActivityPub::RefetchAndVerifyQuoteWorker.perform_in(rand(30..600).seconds, @quote.id, @quote_uri, { 'request_id' => @options[:request_id] })
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -122,6 +122,11 @@ class ActivityPub::Parser::StatusParser
|
|||||||
end.first
|
end.first
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# The inlined quote; out of the attributes we support, only `https://w3id.org/fep/044f#quote` explicitly supports inlined objects
|
||||||
|
def quoted_object
|
||||||
|
as_array(@object['quote']).first
|
||||||
|
end
|
||||||
|
|
||||||
def quote_approval_uri
|
def quote_approval_uri
|
||||||
as_array(@object['quoteAuthorization']).first
|
as_array(@object['quoteAuthorization']).first
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -6,14 +6,13 @@
|
|||||||
class HttpSignatureDraft
|
class HttpSignatureDraft
|
||||||
REQUEST_TARGET = '(request-target)'
|
REQUEST_TARGET = '(request-target)'
|
||||||
|
|
||||||
def initialize(keypair, key_id, full_path: true)
|
def initialize(keypair, key_id)
|
||||||
@keypair = keypair
|
@keypair = keypair
|
||||||
@key_id = key_id
|
@key_id = key_id
|
||||||
@full_path = full_path
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def request_target(verb, url)
|
def request_target(verb, url)
|
||||||
if url.query.nil? || !@full_path
|
if url.query.nil?
|
||||||
"#{verb} #{url.path}"
|
"#{verb} #{url.path}"
|
||||||
else
|
else
|
||||||
"#{verb} #{url.path}?#{url.query}"
|
"#{verb} #{url.path}?#{url.query}"
|
||||||
|
|||||||
@@ -75,7 +75,6 @@ class Request
|
|||||||
@url = Addressable::URI.parse(url).normalize
|
@url = Addressable::URI.parse(url).normalize
|
||||||
@http_client = options.delete(:http_client)
|
@http_client = options.delete(:http_client)
|
||||||
@allow_local = options.delete(:allow_local)
|
@allow_local = options.delete(:allow_local)
|
||||||
@full_path = !options.delete(:omit_query_string)
|
|
||||||
@options = {
|
@options = {
|
||||||
follow: {
|
follow: {
|
||||||
max_hops: 3,
|
max_hops: 3,
|
||||||
@@ -102,7 +101,7 @@ class Request
|
|||||||
|
|
||||||
key_id = ActivityPub::TagManager.instance.key_uri_for(actor)
|
key_id = ActivityPub::TagManager.instance.key_uri_for(actor)
|
||||||
keypair = sign_with.present? ? OpenSSL::PKey::RSA.new(sign_with) : actor.keypair
|
keypair = sign_with.present? ? OpenSSL::PKey::RSA.new(sign_with) : actor.keypair
|
||||||
@signing = HttpSignatureDraft.new(keypair, key_id, full_path: @full_path)
|
@signing = HttpSignatureDraft.new(keypair, key_id)
|
||||||
|
|
||||||
self
|
self
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -57,20 +57,7 @@ class ActivityPub::FetchRepliesService < BaseService
|
|||||||
return unless @allow_synchronous_requests
|
return unless @allow_synchronous_requests
|
||||||
return if non_matching_uri_hosts?(@reference_uri, collection_or_uri)
|
return if non_matching_uri_hosts?(@reference_uri, collection_or_uri)
|
||||||
|
|
||||||
# NOTE: For backward compatibility reasons, Mastodon signs outgoing
|
fetch_resource_without_id_validation(collection_or_uri, nil, raise_on_error: :temporary)
|
||||||
# queries incorrectly by default.
|
|
||||||
#
|
|
||||||
# While this is relevant for all URLs with query strings, this is
|
|
||||||
# the only code path where this happens in practice.
|
|
||||||
#
|
|
||||||
# Therefore, retry with correct signatures if this fails.
|
|
||||||
begin
|
|
||||||
fetch_resource_without_id_validation(collection_or_uri, nil, raise_on_error: :temporary)
|
|
||||||
rescue Mastodon::UnexpectedResponseError => e
|
|
||||||
raise unless e.response && e.response.code == 401 && Addressable::URI.parse(collection_or_uri).query.present?
|
|
||||||
|
|
||||||
fetch_resource_without_id_validation(collection_or_uri, nil, raise_on_error: :temporary, request_options: { omit_query_string: false })
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def filter_replies(items)
|
def filter_replies(items)
|
||||||
|
|||||||
@@ -273,7 +273,6 @@ class ActivityPub::ProcessStatusUpdateService < BaseService
|
|||||||
def update_quote!
|
def update_quote!
|
||||||
return unless Mastodon::Feature.inbound_quotes_enabled?
|
return unless Mastodon::Feature.inbound_quotes_enabled?
|
||||||
|
|
||||||
quote = nil
|
|
||||||
quote_uri = @status_parser.quote_uri
|
quote_uri = @status_parser.quote_uri
|
||||||
|
|
||||||
if quote_uri.present?
|
if quote_uri.present?
|
||||||
@@ -294,21 +293,23 @@ class ActivityPub::ProcessStatusUpdateService < BaseService
|
|||||||
quote = Quote.create(status: @status, approval_uri: approval_uri)
|
quote = Quote.create(status: @status, approval_uri: approval_uri)
|
||||||
@quote_changed = true
|
@quote_changed = true
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
if quote.present?
|
quote.save
|
||||||
begin
|
|
||||||
quote.save
|
fetch_and_verify_quote!(quote, quote_uri)
|
||||||
ActivityPub::VerifyQuoteService.new.call(quote, fetchable_quoted_uri: quote_uri, request_id: @request_id)
|
|
||||||
rescue Mastodon::UnexpectedResponseError, *Mastodon::HTTP_CONNECTION_ERRORS
|
|
||||||
ActivityPub::RefetchAndVerifyQuoteWorker.perform_in(rand(30..600).seconds, quote.id, quote_uri, { 'request_id' => @request_id })
|
|
||||||
end
|
|
||||||
elsif @status.quote.present?
|
elsif @status.quote.present?
|
||||||
@status.quote.destroy!
|
@status.quote.destroy!
|
||||||
@quote_changed = true
|
@quote_changed = true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def fetch_and_verify_quote!(quote, quote_uri)
|
||||||
|
embedded_quote = safe_prefetched_embed(@account, @status_parser.quoted_object, @activity_json['context'])
|
||||||
|
ActivityPub::VerifyQuoteService.new.call(quote, fetchable_quoted_uri: quote_uri, prefetched_quoted_object: embedded_quote, request_id: @request_id)
|
||||||
|
rescue Mastodon::UnexpectedResponseError, *Mastodon::HTTP_CONNECTION_ERRORS
|
||||||
|
ActivityPub::RefetchAndVerifyQuoteWorker.perform_in(rand(30..600).seconds, quote.id, quote_uri, { 'request_id' => @request_id })
|
||||||
|
end
|
||||||
|
|
||||||
def update_counts!
|
def update_counts!
|
||||||
likes = @status_parser.favourites_count
|
likes = @status_parser.favourites_count
|
||||||
shares = @status_parser.reblogs_count
|
shares = @status_parser.reblogs_count
|
||||||
|
|||||||
@@ -4,15 +4,15 @@ class ActivityPub::VerifyQuoteService < BaseService
|
|||||||
include JsonLdHelper
|
include JsonLdHelper
|
||||||
|
|
||||||
# Optionally fetch quoted post, and verify the quote is authorized
|
# Optionally fetch quoted post, and verify the quote is authorized
|
||||||
def call(quote, fetchable_quoted_uri: nil, prefetched_body: nil, request_id: nil)
|
def call(quote, fetchable_quoted_uri: nil, prefetched_quoted_object: nil, prefetched_approval: nil, request_id: nil)
|
||||||
@request_id = request_id
|
@request_id = request_id
|
||||||
@quote = quote
|
@quote = quote
|
||||||
@fetching_error = nil
|
@fetching_error = nil
|
||||||
|
|
||||||
fetch_quoted_post_if_needed!(fetchable_quoted_uri)
|
fetch_quoted_post_if_needed!(fetchable_quoted_uri, prefetched_body: prefetched_quoted_object)
|
||||||
return if fast_track_approval! || quote.approval_uri.blank?
|
return if fast_track_approval! || quote.approval_uri.blank?
|
||||||
|
|
||||||
@json = fetch_approval_object(quote.approval_uri, prefetched_body:)
|
@json = fetch_approval_object(quote.approval_uri, prefetched_body: prefetched_approval)
|
||||||
return quote.reject! if @json.nil?
|
return quote.reject! if @json.nil?
|
||||||
|
|
||||||
return if non_matching_uri_hosts?(quote.approval_uri, value_or_id(@json['attributedTo']))
|
return if non_matching_uri_hosts?(quote.approval_uri, value_or_id(@json['attributedTo']))
|
||||||
@@ -68,11 +68,11 @@ class ActivityPub::VerifyQuoteService < BaseService
|
|||||||
ActivityPub::TagManager.instance.uri_for(@quote.status) == value_or_id(@json['interactingObject'])
|
ActivityPub::TagManager.instance.uri_for(@quote.status) == value_or_id(@json['interactingObject'])
|
||||||
end
|
end
|
||||||
|
|
||||||
def fetch_quoted_post_if_needed!(uri)
|
def fetch_quoted_post_if_needed!(uri, prefetched_body: nil)
|
||||||
return if uri.nil? || @quote.quoted_status.present?
|
return if uri.nil? || @quote.quoted_status.present?
|
||||||
|
|
||||||
status = ActivityPub::TagManager.instance.uri_to_resource(uri, Status)
|
status = ActivityPub::TagManager.instance.uri_to_resource(uri, Status)
|
||||||
status ||= ActivityPub::FetchRemoteStatusService.new.call(uri, on_behalf_of: @quote.account.followers.local.first, request_id: @request_id)
|
status ||= ActivityPub::FetchRemoteStatusService.new.call(uri, on_behalf_of: @quote.account.followers.local.first, prefetched_body:, request_id: @request_id)
|
||||||
|
|
||||||
@quote.update(quoted_status: status) if status.present?
|
@quote.update(quoted_status: status) if status.present?
|
||||||
rescue Mastodon::UnexpectedResponseError, *Mastodon::HTTP_CONNECTION_ERRORS => e
|
rescue Mastodon::UnexpectedResponseError, *Mastodon::HTTP_CONNECTION_ERRORS => e
|
||||||
|
|||||||
16
config/initializers/deprecations.rb
Normal file
16
config/initializers/deprecations.rb
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
if ENV['REDIS_NAMESPACE']
|
||||||
|
es_configured = ENV['ES_ENABLED'] == 'true' || ENV.fetch('ES_HOST', 'localhost') != 'localhost' || ENV.fetch('ES_PORT', '9200') != '9200' || ENV.fetch('ES_PASS', 'password') != 'password'
|
||||||
|
|
||||||
|
warn <<~MESSAGE
|
||||||
|
WARNING: the REDIS_NAMESPACE environment variable is deprecated and will be removed in Mastodon 4.4.0.
|
||||||
|
|
||||||
|
Please see documentation at https://github.com/mastodon/redis_namespace_migration
|
||||||
|
MESSAGE
|
||||||
|
|
||||||
|
warn <<~MESSAGE if es_configured && !ENV['ES_PREFIX']
|
||||||
|
|
||||||
|
In addition, as REDIS_NAMESPACE is being used as a prefix for Elasticsearch, please do not forget to set ES_PREFIX to "#{ENV.fetch('REDIS_NAMESPACE')}".
|
||||||
|
MESSAGE
|
||||||
|
end
|
||||||
@@ -36,6 +36,25 @@ nan:
|
|||||||
approved_msg: 成功審核 %{username} ê註冊申請ah
|
approved_msg: 成功審核 %{username} ê註冊申請ah
|
||||||
are_you_sure: Lí kám確定?
|
are_you_sure: Lí kám確定?
|
||||||
avatar: 標頭
|
avatar: 標頭
|
||||||
|
by_domain: 域名
|
||||||
|
change_email:
|
||||||
|
changed_msg: Email改成功ah!
|
||||||
|
current_email: 現在ê email
|
||||||
|
label: 改email
|
||||||
|
new_email: 新ê email
|
||||||
|
submit: 改email
|
||||||
|
title: 替 %{username} 改email
|
||||||
|
change_role:
|
||||||
|
changed_msg: 角色改成功ah!
|
||||||
|
edit_roles: 管理用者ê角色
|
||||||
|
label: 改角色
|
||||||
|
no_role: 無角色
|
||||||
|
title: 替 %{username} 改角色
|
||||||
|
confirm: 確認
|
||||||
|
confirmed: 確認ah
|
||||||
|
confirming: Teh確認
|
||||||
|
custom: 自訂
|
||||||
|
delete: Thâi資料
|
||||||
deleted: Thâi掉ah
|
deleted: Thâi掉ah
|
||||||
demote: 降級
|
demote: 降級
|
||||||
destroyed_msg: Teh-beh thâi掉 %{username} ê資料
|
destroyed_msg: Teh-beh thâi掉 %{username} ê資料
|
||||||
@@ -49,15 +68,61 @@ nan:
|
|||||||
email: 電子phue箱
|
email: 電子phue箱
|
||||||
email_status: 電子phue ê狀態
|
email_status: 電子phue ê狀態
|
||||||
enable: 取消冷凍
|
enable: 取消冷凍
|
||||||
|
enable_sign_in_token_auth: 啟用電子phue ê token認證
|
||||||
|
enabled: 啟用ah
|
||||||
|
enabled_msg: 成功kā %{username} ê口座退冰
|
||||||
|
followers: 跟tuè lí ê
|
||||||
|
follows: Lí跟tuè ê
|
||||||
|
header: 封面ê圖
|
||||||
|
inbox_url: 收件kheh-á ê URL
|
||||||
|
invite_request_text: 加入ê理由
|
||||||
|
invited_by: 邀請ê lâng
|
||||||
|
ip: IP
|
||||||
|
joined: 加入ê時
|
||||||
location:
|
location:
|
||||||
all: Kui ê
|
all: Kui ê
|
||||||
local: 本地
|
local: 本地
|
||||||
remote: 別ê站
|
remote: 別ê站
|
||||||
title: 位置
|
title: 位置
|
||||||
|
login_status: 登入ê狀態
|
||||||
|
media_attachments: 媒體ê附件
|
||||||
|
memorialize: 變做故人ê口座
|
||||||
|
memorialized: 變做故人ê口座ah
|
||||||
|
memorialized_msg: 成功kā %{username} 變做故人ê口座ah
|
||||||
|
moderation:
|
||||||
|
active: 活ê
|
||||||
|
all: 全部
|
||||||
|
disabled: 停止使用ah
|
||||||
|
pending: Teh審核
|
||||||
|
silenced: 受限制
|
||||||
|
suspended: 權限中止ah
|
||||||
|
title: 管理
|
||||||
|
moderation_notes: 管理ê註釋
|
||||||
|
most_recent_activity: 最近ê活動時間
|
||||||
|
most_recent_ip: 最近ê IP
|
||||||
|
no_account_selected: 因為無揀任何口座,所以lóng無改變
|
||||||
|
no_limits_imposed: 無受著限制
|
||||||
|
no_role_assigned: 無分著角色
|
||||||
|
not_subscribed: 無訂
|
||||||
|
pending: Teh等審核
|
||||||
|
perform_full_suspension: 中止權限
|
||||||
|
previous_strikes: Khah早ê處份
|
||||||
remove_avatar: Thâi掉標頭
|
remove_avatar: Thâi掉標頭
|
||||||
removed_avatar_msg: 成功thâi掉 %{username} ê 標頭影像
|
removed_avatar_msg: 成功thâi掉 %{username} ê 標頭影像
|
||||||
|
username: 用者ê名
|
||||||
|
view_domain: 看域名ê摘要
|
||||||
|
warn: 警告
|
||||||
|
web: 網頁
|
||||||
|
whitelisted: 允准佇聯邦傳資料
|
||||||
action_logs:
|
action_logs:
|
||||||
action_types:
|
action_types:
|
||||||
|
approve_appeal: 批准投訴
|
||||||
|
approve_user: 批准用者
|
||||||
|
assigned_to_self_report: 分配檢舉
|
||||||
|
change_email_user: 替用者改email
|
||||||
|
change_role_user: 改用者ê角色
|
||||||
|
confirm_user: 確認用者
|
||||||
|
create_account_warning: 建立警告
|
||||||
remove_avatar_user: Thâi掉標頭
|
remove_avatar_user: Thâi掉標頭
|
||||||
actions:
|
actions:
|
||||||
remove_avatar_user_html: "%{name} thâi掉 %{target} ê標頭"
|
remove_avatar_user_html: "%{name} thâi掉 %{target} ê標頭"
|
||||||
|
|||||||
@@ -89,6 +89,37 @@ RSpec.describe ActivityPub::VerifyQuoteService do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'with a valid activity for a post that cannot be fetched but is passed as fetched_quoted_object' do
|
||||||
|
let(:quoted_status) { nil }
|
||||||
|
|
||||||
|
let(:approval_interaction_target) { 'https://b.example.com/unknown-quoted' }
|
||||||
|
let(:prefetched_object) do
|
||||||
|
{
|
||||||
|
'@context': 'https://www.w3.org/ns/activitystreams',
|
||||||
|
type: 'Note',
|
||||||
|
id: 'https://b.example.com/unknown-quoted',
|
||||||
|
to: 'https://www.w3.org/ns/activitystreams#Public',
|
||||||
|
attributedTo: ActivityPub::TagManager.instance.uri_for(quoted_account),
|
||||||
|
content: 'previously unknown post',
|
||||||
|
}.with_indifferent_access
|
||||||
|
end
|
||||||
|
|
||||||
|
before do
|
||||||
|
stub_request(:get, 'https://b.example.com/unknown-quoted')
|
||||||
|
.to_return(status: 404)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'updates the status' do
|
||||||
|
expect { subject.call(quote, fetchable_quoted_uri: 'https://b.example.com/unknown-quoted', prefetched_quoted_object: prefetched_object) }
|
||||||
|
.to change(quote, :state).to('accepted')
|
||||||
|
|
||||||
|
expect(a_request(:get, approval_uri))
|
||||||
|
.to have_been_made.once
|
||||||
|
|
||||||
|
expect(quote.reload.quoted_status.content).to eq 'previously unknown post'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
context 'with a valid activity for a post that cannot be fetched but is inlined' do
|
context 'with a valid activity for a post that cannot be fetched but is inlined' do
|
||||||
let(:quoted_status) { nil }
|
let(:quoted_status) { nil }
|
||||||
|
|
||||||
@@ -148,7 +179,7 @@ RSpec.describe ActivityPub::VerifyQuoteService do
|
|||||||
|
|
||||||
context 'with a valid activity for already-fetched posts, with a pre-fetched approval' do
|
context 'with a valid activity for already-fetched posts, with a pre-fetched approval' do
|
||||||
it 'updates the status without fetching the activity' do
|
it 'updates the status without fetching the activity' do
|
||||||
expect { subject.call(quote, prefetched_body: Oj.dump(json)) }
|
expect { subject.call(quote, prefetched_approval: Oj.dump(json)) }
|
||||||
.to change(quote, :state).to('accepted')
|
.to change(quote, :state).to('accepted')
|
||||||
|
|
||||||
expect(a_request(:get, approval_uri))
|
expect(a_request(:get, approval_uri))
|
||||||
|
|||||||
12
yarn.lock
12
yarn.lock
@@ -5496,8 +5496,8 @@ __metadata:
|
|||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"babel-plugin-formatjs@npm:^10.5.37":
|
"babel-plugin-formatjs@npm:^10.5.37":
|
||||||
version: 10.5.37
|
version: 10.5.38
|
||||||
resolution: "babel-plugin-formatjs@npm:10.5.37"
|
resolution: "babel-plugin-formatjs@npm:10.5.38"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/core": "npm:^7.26.10"
|
"@babel/core": "npm:^7.26.10"
|
||||||
"@babel/helper-plugin-utils": "npm:^7.26.5"
|
"@babel/helper-plugin-utils": "npm:^7.26.5"
|
||||||
@@ -5510,7 +5510,7 @@ __metadata:
|
|||||||
"@types/babel__helper-plugin-utils": "npm:^7.10.3"
|
"@types/babel__helper-plugin-utils": "npm:^7.10.3"
|
||||||
"@types/babel__traverse": "npm:^7.20.6"
|
"@types/babel__traverse": "npm:^7.20.6"
|
||||||
tslib: "npm:^2.8.0"
|
tslib: "npm:^2.8.0"
|
||||||
checksum: 10c0/e206ff1a8ad3cbcb3db2d2735d8821701df9d54c8aeb5e8b2861c945af91d4662b9cd37b1ff9d7e17954cdd31aec81788a3d044a1cd9f3e7e8e4f93177097b83
|
checksum: 10c0/5aeb9839ee5be198b82c9ab6c85160e7edcc07f6184efe296560d229d1cc680d9c1e507bde47da74234d612a3e49c919b3e11c855b7fd4e6d256ec23f8b8b1e0
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
@@ -18961,8 +18961,8 @@ __metadata:
|
|||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"ws@npm:^8.11.0, ws@npm:^8.12.1, ws@npm:^8.18.0":
|
"ws@npm:^8.11.0, ws@npm:^8.12.1, ws@npm:^8.18.0":
|
||||||
version: 8.18.1
|
version: 8.18.2
|
||||||
resolution: "ws@npm:8.18.1"
|
resolution: "ws@npm:8.18.2"
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
bufferutil: ^4.0.1
|
bufferutil: ^4.0.1
|
||||||
utf-8-validate: ">=5.0.2"
|
utf-8-validate: ">=5.0.2"
|
||||||
@@ -18971,7 +18971,7 @@ __metadata:
|
|||||||
optional: true
|
optional: true
|
||||||
utf-8-validate:
|
utf-8-validate:
|
||||||
optional: true
|
optional: true
|
||||||
checksum: 10c0/e498965d6938c63058c4310ffb6967f07d4fa06789d3364829028af380d299fe05762961742971c764973dce3d1f6a2633fe8b2d9410c9b52e534b4b882a99fa
|
checksum: 10c0/4b50f67931b8c6943c893f59c524f0e4905bbd183016cfb0f2b8653aa7f28dad4e456b9d99d285bbb67cca4fedd9ce90dfdfaa82b898a11414ebd66ee99141e4
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user