summaryrefslogtreecommitdiff
path: root/helpers.rb
diff options
context:
space:
mode:
Diffstat (limited to 'helpers.rb')
-rw-r--r--helpers.rb89
1 files changed, 61 insertions, 28 deletions
diff --git a/helpers.rb b/helpers.rb
index fdbd894..556f187 100644
--- a/helpers.rb
+++ b/helpers.rb
@@ -1,6 +1,7 @@
# frozen_string_literal: true
require 'English'
+
helpers do
def curl(ext, url)
p url
@@ -8,7 +9,6 @@ helpers do
$CHILD_STATUS.success? ? response : nil
end
- # def fetch(url, accept = 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"')
def fetch(url, accept = 'application/activity+json')
response = curl("-H 'Accept: #{accept}'", url)
response ? JSON.parse(response) : nil
@@ -16,36 +16,60 @@ helpers do
# https://github.com/mastodon/mastodon/blob/main/app/lib/request.rb
# , url
- def send_signed(object)
+ def outbox(type, object, recipients, add_recipients = false)
+ activity = {
+ '@context' => 'https://www.w3.org/ns/activitystreams',
+ 'type' => type,
+ 'actor' => ACTOR,
+ 'object' => object
+ }
+
+ now = Time.now
+ date = now.strftime('%Y-%m-%dT%H:%M:%S.%N')
+ httpdate = now.utc.httpdate
+ basename = "#{date}.json"
+ activity['id'] = File.join(OUTBOX_URL, basename)
+ activity['published'] = httpdate
+ if activity['object'] and activity['object']['type'] and !activity['object']['id']
+ rel_path = File.join activity['object']['type'].downcase, basename
+ activity['object']['published'] = httpdate
+ activity['object']['id'] = File.join(OUTBOX_URL, rel_path)
+ File.open(File.join(OUTBOX_DIR, rel_path), 'w+') { |f| f.puts activity.to_json }
+ end
+ File.open(File.join(OUTBOX_DIR, basename), 'w+') { |f| f.puts activity.to_json }
+
keypair = OpenSSL::PKey::RSA.new(File.read('private.pem'))
- date = Time.now.utc.httpdate
- body = object.to_json
+ body = activity.to_json
sha256 = OpenSSL::Digest.new('SHA256')
digest = "SHA-256=#{sha256.base64digest(body)}"
- recipients = [object['to'], object['cc'], object['bto'], object['bcc'], object['audience']].flatten.compact.uniq
- recipients.each do |url|
- next if url == 'https://www.w3.org/ns/activitystreams#Public'
-
- host = URI.parse(url).host
- inbox = fetch(url)['inbox']
- if inbox
- request_uri = URI(inbox).request_uri
-
- signed_string = "(request-target): post #{request_uri}\nhost: #{host}\ndate: #{date}\ndigest: #{digest}\ncontent-type: application/activity+json"
- signature = Base64.strict_encode64(keypair.sign(OpenSSL::Digest.new('SHA256'), signed_string))
- signed_header = "keyId=\"#{ACTOR}#main-key\",algorithm=\"rsa-sha256\",headers=\"(request-target) host date digest content-type\",signature=\"#{signature}\""
-
- curl(
- "-X POST -H 'Content-Type: application/activity+json' -H 'Host: #{host}' -H 'Date: #{date}' -H 'Digest: #{digest}' -H 'Signature: #{signed_header}' -d '#{body}'", inbox
- )
- else
- p "No inbox for #{url}"
- end
+
+ # assumes that recipient collections have been expanded by sender
+ # put all recipients into 'to', avoid 'cc' 'bto' 'bcc' 'audience' !!
+ activity['to'] = recipients if add_recipients
+ inboxes = if recipients.include? 'https://www.w3.org/ns/activitystreams#Public'
+ people.collect { |p| p[2] }.uniq # cached sharedInboxes
+ else
+ []
+ end
+ recipients.uniq.each do |url|
+ next if [ACTOR, 'https://www.w3.org/ns/activitystreams#Public'].include? url
+
+ actor = fetch url
+ next unless actor and actor['inbox']
+
+ inbox = actor['endpoints']['sharedInbox']
+ inboxes << (inbox || actor['inbox'])
end
- end
+ inboxes.compact.uniq.each do |inbox|
+ uri = URI(inbox)
+ string = "(request-target): post #{uri.request_uri}\nhost: #{uri.host}\ndate: #{httpdate}\ndigest: #{digest}\ncontent-type: application/activity+json"
+ signature = Base64.strict_encode64(keypair.sign(OpenSSL::Digest.new('SHA256'), string))
+ signed_header = "keyId=\"#{ACTOR}#main-key\",algorithm=\"rsa-sha256\",headers=\"(request-target) host date digest content-type\",signature=\"#{signature}\""
- def people
- File.read('cache/people.tsv').split("\n").collect { |l| l.chomp.split("\t") }
+ curl(
+ "-X POST -H 'Content-Type: application/activity+json' -H 'Host: #{uri.host}' -H 'Date: #{httpdate}' -H 'Digest: #{digest}' -H 'Signature: #{signed_header}' -d '#{body}'", inbox
+ )
+ end
end
def mention(actor)
@@ -55,7 +79,7 @@ helpers do
return nil unless a
mention = "#{a['preferredUsername']}@#{URI(actor).host}"
- File.open('cache/people.tsv', 'a') { |f| f.puts "#{mention}\t#{actor}" }
+ cache mention, actor, a
mention
else
person[0][0]
@@ -73,10 +97,19 @@ helpers do
actor = a['links'].select do |l|
l['rel'] == 'self'
end[0]['href']
- File.open('cache/people.tsv', 'a') { |f| f.puts "#{mention}\t#{actor}" }
+ cache mention, actor, a
actor
else
actors[0][1]
end
end
+
+ def people
+ File.read('cache/people.tsv').split("\n").collect { |l| l.chomp.split("\t") }
+ end
+
+ def cache(mention, actor, a)
+ sharedInbox = a['endpoints']['sharedInbox'] if a['endpoints'] and a['endpoints']['sharedInbox']
+ File.open('cache/people.tsv', 'a') { |f| f.puts "#{mention}\t#{actor}\t#{sharedInbox}" }
+ end
end