about summary refs log tree commit diff
path: root/app
diff options
context:
space:
mode:
authorThibG <thib@sitedethib.com>2020-12-17 06:51:49 +0100
committerGitHub <noreply@github.com>2020-12-17 06:51:49 +0100
commitb1feb47055c121c1b6949bd7ef6734bf56c847bd (patch)
tree7d73046847b67fc40a8d05cade4de98f6c180fb5 /app
parent2032748050b5ed1491473886107f622eea8e0c3f (diff)
Improve searching for private toots from URL (#14856)
* Improve searching for private toots from URL

Most of the time, when sharing toots, people use the toot URL rather than
the toot URI, which makes sense since it is the user-facing URL.

In Mastodon's case, the URL and URI are different, and Mastodon does not
have an index on URL, which means searching a private toot by URL is done
with a slow query that will only succeed for very recent toots.

This change gets rid of the slow query, and attempts to guess the URI from
URL instead, as Mastodon's are predictable.

* Add tests

* Only return status with guessed uri if url matches

Co-authored-by: Claire <claire.github-309c@sitedethib.com>
Diffstat (limited to 'app')
-rw-r--r--app/services/resolve_url_service.rb12
1 files changed, 11 insertions, 1 deletions
diff --git a/app/services/resolve_url_service.rb b/app/services/resolve_url_service.rb
index 78080d878..5981e4d98 100644
--- a/app/services/resolve_url_service.rb
+++ b/app/services/resolve_url_service.rb
@@ -34,7 +34,17 @@ class ResolveURLService < BaseService
 
     # It may happen that the resource is a private toot, and thus not fetchable,
     # but we can return the toot if we already know about it.
-    status = Status.find_by(uri: @url) || Status.find_by(url: @url)
+    scope = Status.where(uri: @url)
+
+    # We don't have an index on `url`, so try guessing the `uri` from `url`
+    parsed_url = Addressable::URI.parse(@url)
+    parsed_url.path.match(%r{/@(?<username>#{Account::USERNAME_RE})/(?<status_id>[0-9]+)\Z}) do |matched|
+      parsed_url.path = "/users/#{matched[:username]}/statuses/#{matched[:status_id]}"
+      scope = scope.or(Status.where(uri: parsed_url.to_s, url: @url))
+    end
+
+    status = scope.first
+
     authorize_with @on_behalf_of, status, :show? unless status.nil?
     status
   rescue Mastodon::NotPermittedError