diff --git a/app/mastodon_account.rb b/app/mastodon_account.rb index 8cc9cb4..7c1f176 100644 --- a/app/mastodon_account.rb +++ b/app/mastodon_account.rb @@ -4,7 +4,14 @@ require_relative 'mastodon_api' class MastodonAccount APP_NAME = "Tootify" CONFIG_FILE = File.expand_path(File.join(__dir__, '..', 'config', 'mastodon.yml')) - OAUTH_SCOPES = 'read:accounts read:statuses write:media write:statuses' + + OAUTH_SCOPES = [ + 'read:accounts', + 'read:statuses', + 'read:search', + 'write:media', + 'write:statuses' + ].join(' ') def initialize @config = File.exist?(CONFIG_FILE) ? YAML.load(File.read(CONFIG_FILE)) : {} @@ -52,10 +59,16 @@ class MastodonAccount api.register_oauth_app(APP_NAME, OAUTH_SCOPES) end - def post_status(text, media_ids = nil, parent_id = nil) + def instance_info + instance = @config['handle'].split('@').last + api = MastodonAPI.new(instance, @config['access_token']) + api.instance_info + end + + def post_status(text, media_ids: nil, parent_id: nil, quoted_status_id: nil) instance = @config['handle'].split('@').last api = MastodonAPI.new(instance, @config['access_token']) - api.post_status(text, media_ids, parent_id) + api.post_status(text, media_ids: media_ids, parent_id: parent_id, quoted_status_id: quoted_status_id) end def upload_media(data, filename, content_type, alt = nil) @@ -63,4 +76,10 @@ class MastodonAccount api = MastodonAPI.new(instance, @config['access_token']) api.upload_media(data, filename, content_type, alt) end + + def search_post_by_url(url) + instance = @config['handle'].split('@').last + api = MastodonAPI.new(instance, @config['access_token']) + api.search_post_by_url(url) + end end diff --git a/app/mastodon_api.rb b/app/mastodon_api.rb index 2cdafac..72f96cd 100644 --- a/app/mastodon_api.rb +++ b/app/mastodon_api.rb @@ -74,6 +74,10 @@ class MastodonAPI get_json("/accounts/verify_credentials") end + def instance_info + get_json("https://#{@host}/api/v2/instance") + end + def lookup_account(username) json = get_json("/accounts/lookup", { acct: username }) raise UnexpectedResponseError.new unless json.is_a?(Hash) && json['id'].is_a?(String) @@ -84,10 +88,11 @@ class MastodonAPI get_json("/accounts/#{user_id}/statuses", params) end - def post_status(text, media_ids = nil, parent_id = nil) + def post_status(text, media_ids: nil, parent_id: nil, quoted_status_id: nil) params = { status: text } params['media_ids[]'] = media_ids if media_ids params['in_reply_to_id'] = parent_id if parent_id + params['quoted_status_id'] = quoted_status_id if quoted_status_id post_json("/statuses", params) end @@ -129,6 +134,16 @@ class MastodonAPI get_json("/media/#{media_id}") end + def search_post_by_url(url) + json = get_json("https://#{@host}/api/v2/search", { + q: url, + type: 'statuses', + resolve: true + }) + + json['statuses'] && json['statuses'][0] + end + def get_json(path, params = {}) url = URI(path.start_with?('https://') ? path : @root + path) url.query = URI.encode_www_form(params) if params diff --git a/app/tootify.rb b/app/tootify.rb index 5efca25..54a762d 100644 --- a/app/tootify.rb +++ b/app/tootify.rb @@ -135,10 +135,25 @@ class Tootify if collection == 'app.bsky.feed.post' link_to_append = bsky_post_link(repo, rkey) + instance_info = @mastodon.instance_info - if @config['extract_link_from_quotes'] + if instance_info.dig('api_versions', 'mastodon').to_i >= 7 quoted_record = fetch_record_by_at_uri(quote_uri) + # TODO: we need to wait for Bridgy to add support for quote_authorizations + quoted_post_url = quoted_record['bridgyOriginalUrl'] #|| "https://bsky.brid.gy/convert/ap/#{quote_uri}" + + if quoted_post_url && (local_post = @mastodon.search_post_by_url(quoted_post_url)) + quote_policy = local_post.dig('quote_approval', 'current_user') + + if quote_policy == 'automatic' || quote_policy == 'manual' + quote_id = local_post['id'] + end + end + end + + if !quote_id && @config['extract_link_from_quotes'] + quoted_record ||= fetch_record_by_at_uri(quote_uri) quote_link = link_embed(quoted_record) if quote_link.nil? @@ -151,7 +166,7 @@ class Tootify end end - append_link(text, link_to_append) unless text.include?(link_to_append) + append_link(text, link_to_append) unless quote_id || text.include?(link_to_append) end end @@ -191,7 +206,7 @@ class Tootify text += "\n\n" + tags.map { |t| '#' + t.gsub(' ', '') }.join(' ') end - @mastodon.post_status(text, media_ids, mastodon_parent_id) + @mastodon.post_status(text, media_ids: media_ids, parent_id: mastodon_parent_id, quoted_status_id: quote_id) end def fetch_record_by_at_uri(quote_uri)