summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--application.rb10
-rwxr-xr-xclean-inbox3
-rw-r--r--client.rb23
-rw-r--r--create.rb2
-rw-r--r--helpers.rb9
-rw-r--r--server.rb71
-rwxr-xr-xupdate3
-rwxr-xr-xwatch3
8 files changed, 71 insertions, 53 deletions
diff --git a/application.rb b/application.rb
index a03d98c..5236685 100644
--- a/application.rb
+++ b/application.rb
@@ -1,10 +1,8 @@
-# frozen_string_literal: true
-
require 'uri'
require 'base64'
require 'digest/sha2'
+require 'time'
require 'rack/protection'
-# require 'rack/contrib'
require 'sinatra'
SOCIAL_DIR = '/srv/social/'
@@ -25,15 +23,13 @@ INBOX = { dir: File.join(SOCIAL_DIR, 'inbox') }
OUTBOX = { dir: File.join(SOCIAL_DIR, 'outbox'), url: File.join(SOCIAL_URL, 'outbox') }
TAGS = { dir: File.join(PUBLIC_DIR, 'tags'), url: File.join(SOCIAL_URL, 'tags') }
FOLLOWERS_URL = 'https://social.pdp8.info/followers'
+VISITED = File.join(INBOX[:dir], 'visited')
+ACTIVITIES = %i[create announce follow accept undo delete like update move]
CONTENT_TYPE = 'application/activity+json'
# CONTENT_TYPE = 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"'
use Rack::Protection
-# use Rack::MailExceptions do |mail|
-# mail.to 'info@pdp8.info'
-# mail.smtp false
-# end
enable :sessions
set :environment, :production
diff --git a/clean-inbox b/clean-inbox
new file mode 100755
index 0000000..b623890
--- /dev/null
+++ b/clean-inbox
@@ -0,0 +1,3 @@
+#!/usr/bin/env nu
+[create announce undo delete like update move] | each { |a| glob $'/srv/social/inbox/($a)/*.json' | each {|f| rm $f } }
+
diff --git a/client.rb b/client.rb
index 61d1ac3..ca5a338 100644
--- a/client.rb
+++ b/client.rb
@@ -10,27 +10,8 @@ post '/delete' do
protected!
params['id'].each do |id|
file = find_file id
- halt 404 unless file
- # if file.match(%r{outbox/}) # find/delete activity
-
- %w[inbox outbox].each do |box|
- Dir[File.join box, 'announce', '*.json'].each do |announce_file|
- announce = JSON.load_file(announce_file)
- next unless announce['object']['id'] == id
-
- outbox 'Undo', announce, announce['to']
- FileUtils.rm(announce_file)
- end
- Dir[File.join box, 'create', '*.json'].each do |create_file|
- create = JSON.load_file(create_file)
- next unless create['object']['id'] == id
-
- object = JSON.load_file(file)
- outbox 'Delete', object, object['to']
- FileUtils.rm(create_file)
- end
- end
- FileUtils.rm(file) if File.exist? file
+ halt 404 unless file and File.exist?(file)
+ FileUtils.rm(file)
end
200
end
diff --git a/create.rb b/create.rb
index 59ef726..12d9a27 100644
--- a/create.rb
+++ b/create.rb
@@ -87,7 +87,7 @@ post '/create' do # TODO
p 'outbox'
jj object
- outbox 'Create', object, to
+ # outbox 'Create', object, to
200
end
diff --git a/helpers.rb b/helpers.rb
index 41dcc33..75221f8 100644
--- a/helpers.rb
+++ b/helpers.rb
@@ -1,5 +1,10 @@
require 'English'
helpers do
+ def save_item(item, path)
+ FileUtils.mkdir_p File.dirname(path)
+ File.open(path, 'w+') { |f| f.puts item.to_json }
+ end
+
# add date and id, save
def save_activity(activity, box)
date = Time.now.utc.iso8601
@@ -24,9 +29,7 @@ helpers do
def save_object(object, box)
object = fetch(object) if object.is_a? String and object.match(/^http/)
return unless object and object['type'] != 'Person'
- # File.open(File.join(INBOX[:dir]), 'visited', 'w+').open { |f| f.puts object['id'] }
- return if box == INBOX and object['id'] and File.readlines(File.join(INBOX[:dir], 'visited'),
- chomp: true).include? object['id']
+ return if box == INBOX and object['id'] and File.readlines(VISITED, chomp: true).include? object['id']
object['@context'] = 'https://www.w3.org/ns/activitystreams'
if object['attributedTo']
diff --git a/server.rb b/server.rb
index 7319efa..68c51e1 100644
--- a/server.rb
+++ b/server.rb
@@ -2,24 +2,16 @@
post '/inbox' do
request.body.rewind # in case someone already read it
@body = request.body.read
- halt 400 if @body.empty?
begin
@activity = JSON.parse @body
- rescue StandardError
+ rescue StandardError => e
p @body
halt 400
end
# deleted actors return 403 => verification error
halt 200 if @activity['type'] == 'Delete' and @activity['actor'] == @activity['object']
# verify! # pixelfed sends unsigned activities???
- type = @activity['type'].downcase.to_sym
- save_activity(@activity, INBOX) # unless %i[create announce].include? type
- if %i[create announce follow accept undo delete like update move].include? type
- send(type)
- else
- p "Unknown activity #{type}:"
- jj @activity
- end
+ handle_activity
200
end
@@ -66,12 +58,7 @@ helpers do
def create
@count ||= 0
@object ||= @activity['object']
-
- @object = if @object['type'] == 'Like' # lemmy likes
- save_object @object['object'], INBOX
- else
- save_object @object, INBOX
- end
+ save_inbox_object
return unless @object and @object['inReplyTo'] and @count < 5
# recursive thread download
@@ -81,11 +68,14 @@ helpers do
end
def announce
+ @object ||= @activity['object']
+ @object = fetch(@object) if @object.is_a? String and @object.match(/^http/)
+ @object['announce'] = @activity['actor'] if @object
create
end
def like
- create
+ announce
end
def follow
@@ -94,8 +84,13 @@ helpers do
end
def accept
- halt 501 unless @activity['object']['type'] == 'Follow'
- update_collection FOLLOWING, @activity['object']['object']
+ if @activity['object']['type'] == 'Follow'
+ update_collection FOLLOWING, @activity['object']['object']
+ else
+ p "Cannot accept @activity['object']['type']"
+ jj @activity
+ halt 501
+ end
end
def undo
@@ -106,12 +101,15 @@ helpers do
file = find_file @activity['object']['object']
FileUtils.rm(file) if file
else
+ p "Cannot undo @activity['object']['type']"
+ jj @activity
halt 501
end
end
def update
- FileUtils.rm(find_file(@activity['object']['id']))
+ file = find_file(@activity['object']['id'])
+ FileUtils.rm(file) if file
create
end
@@ -124,6 +122,39 @@ helpers do
outbox 'Follow', @activity['target'], [@activity['target']] if @activity['actor'] == @activity['object']
end
+ def handle_activity
+ type = @activity['type'].downcase.to_sym
+ save_item @activity, File.join(INBOX[:dir], @activity['type'].downcase, activity_name)
+ if ACTIVITIES.include? type
+ send(type)
+ else
+ p "Unknown activity #{type}:"
+ jj @activity
+ end
+ end
+
+ def activity_name
+ @activity['published'] ? "#{@activity['published']}_#{mention(@activity['actor'])}.json" : "_#{Time.now.utc.iso8601}_#{mention(@activity['actor'])}.json"
+ end
+
+ def save_inbox_object
+ @object = fetch(@object) if @object.is_a? String and @object.match(/^http/)
+ if @object['type'] and ACTIVITIES.include? @object['type'].downcase.to_sym
+ @activity = @object
+ handle_activity
+ return
+ end
+ # @object = @object['object'] if @object['type'] == 'Like' # lemmy likes
+ return unless @object and @object['type'] != 'Person'
+
+ if @activity['type'] != 'Update' && (@object['id'] and File.readlines(VISITED, chomp: true).include? @object['id'])
+ return
+ end
+
+ save_item @object, File.join(INBOX[:dir], 'object', @object['type'].downcase, activity_name)
+ File.open(File.join(INBOX[:dir], 'visited'), 'a+') { |f| f.puts @object['id'] }
+ end
+
# https://github.com/mastodon/mastodon/blob/main/app/controllers/concerns/signature_verification.rb
def verify!
# digest
diff --git a/update b/update
new file mode 100755
index 0000000..24eebb5
--- /dev/null
+++ b/update
@@ -0,0 +1,3 @@
+#!/bin/sh
+rsync -a --exclude='.git/' --exclude='watch' --exclude='generate-digest.rb' --exclude='update '--exclude='.gitignore' --exclude='TODO' --filter=":- .gitignore" ./ /srv/social/
+sudo systemctl restart social.service
diff --git a/watch b/watch
index 41ad68b..4c020a9 100755
--- a/watch
+++ b/watch
@@ -1,5 +1,6 @@
#!/bin/sh
while inotifywait -qq -r ./ -e create,delete,modify; do
- rsync -a --exclude='.git/' --exclude='watch' --exclude='generate-digest.rb' --exclude='.gitignore' --exclude='TODO' --filter=":- .gitignore" ./ /srv/social/
+ update
+ #rsync -a --exclude='.git/' --exclude='watch' --exclude='generate-digest.rb' --exclude='.gitignore' --exclude='TODO' --filter=":- .gitignore" ./ /srv/social/
sudo systemctl restart social.service
done