summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--client.rb3
-rw-r--r--helpers.rb35
-rw-r--r--server.rb47
3 files changed, 51 insertions, 34 deletions
diff --git a/client.rb b/client.rb
index efc2f6d..75464c1 100644
--- a/client.rb
+++ b/client.rb
@@ -140,6 +140,9 @@ end
get path, provides: 'html' do
protected!
@dir = path.sub('/', '')
+ # collection = DirI#
+ # collection = Dir[File.join(@dir, 'object','*', '*.json')].collect { |f| JSON.parse(File.read(f)) }
+
@collection = Dir[File.join(@dir, 'create', '*.json')].collect { |f| JSON.parse(File.read(f))['object'] }
@collection += Dir[File.join(@dir, 'announce', '*.json')].collect { |f| JSON.parse(File.read(f))['object'] }
@threads = []
diff --git a/helpers.rb b/helpers.rb
index 45c58df..0db6566 100644
--- a/helpers.rb
+++ b/helpers.rb
@@ -4,34 +4,36 @@ require 'English'
helpers do
# add date and id, save
- def complete_and_save(activity)
- box = activity['id'] ? INBOX : OUTBOX
+ def save_activity(activity, box)
date = Time.now.utc.iso8601
activity['published'] = date if box == OUTBOX
basename = "#{activity['published']}_#{mention(activity['actor'])}.json"
activity_rel_path = File.join(activity['type'].downcase, basename)
activity_path = File.join(box[:dir], activity_rel_path)
- activity['id'] = File.join(box[:url], activity_rel_path) if box == OUTBOX
-
- if activity['object'] && activity['object']['type'] && !activity['object']['id']
- # save object
- object = activity['object']
- object['@context'] = 'https://www.w3.org/ns/activitystreams'
- object_rel_path = File.join 'object', activity['object']['type'].downcase, basename
- if box == OUTBOX
- object['id'] = File.join box[:url], object_rel_path
- object['published'] = date
- end
- object_path = File.join box[:dir], object_rel_path
- FileUtils.mkdir_p File.dirname(object_path)
- File.open(object_path, 'w+') { |f| f.puts object.to_json }
+ if box == OUTBOX
+ activity['id'] = File.join(box[:url], activity_rel_path)
+ activity['object']['published'] = date
end
+ # save object
+ save_object activity['object'], box if activity['object'] && activity['object']['type'] && !activity['object']['id']
# save activity
FileUtils.mkdir_p File.dirname(activity_path)
File.open(activity_path, 'w+') { |f| f.puts activity.to_json }
activity
end
+ def save_object(object, box)
+ object = fetch(object) if object.is_a? String and object.match(/^http/)
+ object['@context'] = 'https://www.w3.org/ns/activitystreams'
+ basename = "#{object['published']}_#{mention(object['attributedTo'])}.json"
+ object_rel_path = File.join 'object', object['type'].downcase, basename
+ object['id'] = File.join box[:url], object_rel_path if box == OUTBOX
+ object_path = File.join box[:dir], object_rel_path
+ FileUtils.mkdir_p File.dirname(object_path)
+ File.open(object_path, 'w+') { |f| f.puts object.to_json }
+ object
+ end
+
def update_collection(path, objects, delete = false)
objects = [objects] unless objects.is_a? Array
File.open(path, 'r+') do |f|
@@ -61,7 +63,6 @@ helpers do
string = "(request-target): get #{uri.request_uri}\nhost: #{uri.host}\ndate: #{httpdate}"
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\",signature=\"#{signature}\""
-
response = curl(
"-H 'Accept: #{accept}' -H 'Host: #{uri.host}' -H 'Date: #{httpdate}' -H 'Signature: #{signed_header}' ", url
)
diff --git a/server.rb b/server.rb
index f7e9b82..4fdf1e8 100644
--- a/server.rb
+++ b/server.rb
@@ -13,9 +13,9 @@ post '/inbox' do
end
halt 501 if @activity['actor'] and @activity['type'] == 'Delete' # deleted actors return 403 => verification error
verify! # unless type == :accept # pixelfed sends unsigned accept activities???
- complete_and_save(@activity)
+ save_activity(@activity, INBOX)
type = @activity['type'].downcase.to_sym
- send(type) if %i[follow accept undo].include? type
+ send(type) if %i[create announce follow accept undo].include? type
halt 200
end
@@ -36,6 +36,19 @@ end
end
helpers do
+ def create
+ @object ||= @activity['object']
+ @object = save_object @object, INBOX
+ return unless @object['inReplyTo']
+
+ @object = @object['inReplyTo']
+ create
+ end
+
+ def announce
+ create
+ end
+
def follow
update_collection FOLLOWERS, @activity['actor']
outbox 'Accept', @activity, [@activity['actor']]
@@ -88,22 +101,8 @@ helpers do
end
def outbox(type, object, recipients)
- # add date and id, save
- activity = complete_and_save({
- '@context' => 'https://www.w3.org/ns/activitystreams',
- 'type' => type,
- 'actor' => ACTOR,
- 'object' => object,
- 'to' => recipients
- })
-
# send
- # https://github.com/mastodon/mastodon/blob/main/app/lib/request.rb
- keypair = OpenSSL::PKey::RSA.new(File.read('private.pem'))
- body = activity.to_json
- sha256 = OpenSSL::Digest.new('SHA256')
- digest = "SHA-256=#{sha256.base64digest(body)}"
-
+ ## https://github.com/mastodon/mastodon/blob/main/app/lib/request.rb
inboxes = []
recipients.uniq.each do |url|
next if [ACTOR, 'https://www.w3.org/ns/activitystreams#Public'].include? url
@@ -118,8 +117,22 @@ helpers do
end
end
+ # add date and id, save
+ activity = save_activity({
+ '@context' => 'https://www.w3.org/ns/activitystreams',
+ 'type' => type,
+ 'actor' => ACTOR,
+ 'object' => object,
+ 'to' => recipients
+ }, OUTBOX)
+ body = activity.to_json
+ sha256 = OpenSSL::Digest.new('SHA256')
+ digest = "SHA-256=#{sha256.base64digest(body)}"
+ keypair = OpenSSL::PKey::RSA.new(File.read('private.pem'))
+
inboxes.compact.uniq.each do |inbox|
uri = URI(inbox)
+ httpdate = Time.now.utc.httpdate
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}\""