jekyll-activity-pub 0.1.0rc16 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/jekyll/activity_pub/activity.rb +2 -1
- data/lib/jekyll/activity_pub/actor.rb +0 -1
- data/lib/jekyll/activity_pub/following.rb +25 -0
- data/lib/jekyll/activity_pub/helper.rb +12 -12
- data/lib/jekyll/activity_pub/instance_v1.rb +130 -0
- data/lib/jekyll/activity_pub/{instance.rb → instance_v2.rb} +10 -26
- data/lib/jekyll/activity_pub/link.rb +32 -0
- data/lib/jekyll/activity_pub/notifier.rb +15 -22
- data/lib/jekyll/activity_pub.rb +3 -1
- data/lib/jekyll-activity-pub-absolute-assets.rb +29 -0
- data/lib/jekyll-activity-pub-assets-as-attachments.rb +15 -0
- data/lib/jekyll-activity-pub-fep-fffd-distributed-press.rb +82 -0
- data/lib/jekyll-activity-pub-link-iframes.rb +16 -0
- data/lib/jekyll-activity-pub-nokogiri.rb +16 -0
- data/lib/jekyll-activity-pub.rb +11 -8
- metadata +15 -9
- data/lib/jekyll/activity_pub/cache.rb~ +0 -10
- data/lib/jekyll/activity_pub/tomsbtone.rb~ +0 -61
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9bbfcc9584215764c7097b8dbd857fba16fb9638676ef80a646dd77021f9b72c
|
4
|
+
data.tar.gz: a7d019c0613766a3c107e9aa24775032e1721348a4057d62424da9aa48e8340a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b9556ee3d0b03bb45c9dd051c24edb59915056d44886d56b15b7c6a4cdfed1520e28f3aa955769e8b5d3592f71dd704ab9328b148f22ddd77f6f9be577e666c0
|
7
|
+
data.tar.gz: 89bc2152540aeaeec52c5363afa646d9318a1cf9c34f2d732fcc705e785b359dce620ef98e2175b7f0c104ba86d74600b0a22fb4a8990be900d9d2c2fa74a077
|
@@ -46,7 +46,8 @@ module Jekyll
|
|
46
46
|
}
|
47
47
|
],
|
48
48
|
'type' => 'Note',
|
49
|
-
'id' => absolute_url(
|
49
|
+
'id' => absolute_url(url),
|
50
|
+
'url' => absolute_url(doc.url),
|
50
51
|
'summary' => summary,
|
51
52
|
'published' => (doc.data['created_at'] || doc.date).xmlschema,
|
52
53
|
'updated' => doc.data['last_modified_at']&.xmlschema,
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'ordered_collection'
|
4
|
+
|
5
|
+
module Jekyll
|
6
|
+
module ActivityPub
|
7
|
+
# An empty collection of followed actors
|
8
|
+
class Following < OrderedCollection
|
9
|
+
# Initialize with default data
|
10
|
+
#
|
11
|
+
# @param :site [Jekyll::Site]
|
12
|
+
# @param :actor [Jekyll::ActivityPub::Actor]
|
13
|
+
# @param :base [String]
|
14
|
+
# @param :dir [String]
|
15
|
+
# @param :name [String]
|
16
|
+
def initialize(site, actor, base = '', dir = '', name = 'following.jsonld')
|
17
|
+
super(site, base, dir, name)
|
18
|
+
|
19
|
+
actor.data['following'] = absolute_url(url)
|
20
|
+
|
21
|
+
trigger_hooks :post_init
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -66,6 +66,18 @@ module Jekyll
|
|
66
66
|
|
67
67
|
alias type hook_owner
|
68
68
|
|
69
|
+
# Detects locale
|
70
|
+
#
|
71
|
+
# @return [String]
|
72
|
+
def locale
|
73
|
+
return @locale if defined? @locale
|
74
|
+
|
75
|
+
@locale = site.config['locale']
|
76
|
+
@locale ||= ENV['LANG']&.split('.', 2)&.first
|
77
|
+
|
78
|
+
@locale = @locale&.tr('_', '-')
|
79
|
+
end
|
80
|
+
|
69
81
|
private
|
70
82
|
|
71
83
|
# Is Liquid on strict mode?
|
@@ -137,18 +149,6 @@ module Jekyll
|
|
137
149
|
File.exist?(cname_file)
|
138
150
|
end
|
139
151
|
|
140
|
-
# Detects locale
|
141
|
-
#
|
142
|
-
# @return [String]
|
143
|
-
def locale
|
144
|
-
return @locale if defined? @locale
|
145
|
-
|
146
|
-
@locale = site.config['locale']
|
147
|
-
@locale ||= ENV['LANG']&.split('.', 2)&.first
|
148
|
-
|
149
|
-
@locale = @locale&.tr('_', '-')
|
150
|
-
end
|
151
|
-
|
152
152
|
# Finds the value of a text field amongst options
|
153
153
|
#
|
154
154
|
# @params :hash [Hash] The haystack
|
@@ -0,0 +1,130 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'jekyll/page'
|
4
|
+
require_relative 'helper'
|
5
|
+
require_relative 'version'
|
6
|
+
|
7
|
+
module Jekyll
|
8
|
+
module ActivityPub
|
9
|
+
# Points to site's metadata
|
10
|
+
class InstanceV1 < Jekyll::Page
|
11
|
+
include Helper
|
12
|
+
|
13
|
+
# Initialize with default data
|
14
|
+
#
|
15
|
+
# @param :site [Jekyll::Site]
|
16
|
+
# @param :base [String]
|
17
|
+
# @param :dir [String]
|
18
|
+
# @param :name [String]
|
19
|
+
def initialize(site, base = '', dir = 'api/v1', name = 'instance')
|
20
|
+
@context = StubContext.new(registers: { site: site })
|
21
|
+
|
22
|
+
super(site, base, dir, name)
|
23
|
+
|
24
|
+
trigger_hooks :post_init
|
25
|
+
end
|
26
|
+
|
27
|
+
def permalink
|
28
|
+
'api/v1/instance/'
|
29
|
+
end
|
30
|
+
|
31
|
+
def output_ext
|
32
|
+
'.json'
|
33
|
+
end
|
34
|
+
|
35
|
+
def read_yaml(*)
|
36
|
+
self.data = {
|
37
|
+
'uri' => hostname,
|
38
|
+
'title' => public_name,
|
39
|
+
'short_description' => summary,
|
40
|
+
'description' => summary,
|
41
|
+
'email' => email,
|
42
|
+
'version' => Jekyll::ActivityPub::VERSION,
|
43
|
+
'urls' => {},
|
44
|
+
'stats' => {
|
45
|
+
'user_count' => 1,
|
46
|
+
'status_count' => 0,
|
47
|
+
'domain_count' => 1
|
48
|
+
},
|
49
|
+
'thumbnail' => conditional_absolute_url(avatar),
|
50
|
+
'languages' => languages,
|
51
|
+
'registrations' => false,
|
52
|
+
'approval_required' => false,
|
53
|
+
'invites_enabled' => false,
|
54
|
+
'configuration' => {
|
55
|
+
'accounts' => {},
|
56
|
+
'statuses' => {},
|
57
|
+
'media_attachments' => {},
|
58
|
+
'polls' => {}
|
59
|
+
},
|
60
|
+
'contact_account' => {
|
61
|
+
'id' => 1,
|
62
|
+
'username' => username,
|
63
|
+
'acct' => username,
|
64
|
+
'display_name' => public_name,
|
65
|
+
'locked' => false,
|
66
|
+
'bot' => false,
|
67
|
+
'discoverable' => true,
|
68
|
+
'group' => false,
|
69
|
+
'created_at' => published.xmlschema,
|
70
|
+
'note' => summary,
|
71
|
+
'url' => site.config['url'],
|
72
|
+
'uri' => site.config['url'],
|
73
|
+
'avatar' => conditional_absolute_url(avatar),
|
74
|
+
'avatar_static' => conditional_absolute_url(avatar),
|
75
|
+
'header' => conditional_absolute_url(header),
|
76
|
+
'header_static' => conditional_absolute_url(header),
|
77
|
+
'followers_count' => 0,
|
78
|
+
'following_count' => 0,
|
79
|
+
'statuses_count' => 0,
|
80
|
+
'last_status_at' => nil,
|
81
|
+
'noindex' => false,
|
82
|
+
'emojis' => [],
|
83
|
+
'roles' => [],
|
84
|
+
'fields' => []
|
85
|
+
},
|
86
|
+
'rules' => []
|
87
|
+
}
|
88
|
+
end
|
89
|
+
|
90
|
+
def increase_local_posts_counter!
|
91
|
+
data['stats']['status_count'] += 1
|
92
|
+
data['contact_account']['statuses_count'] += 1
|
93
|
+
nil
|
94
|
+
end
|
95
|
+
|
96
|
+
def increase_last_status!(last_status)
|
97
|
+
self.last_status_at = last_status if !last_status_at || last_status_at < last_status
|
98
|
+
end
|
99
|
+
|
100
|
+
private
|
101
|
+
|
102
|
+
def last_status_at
|
103
|
+
data['contact_account']['last_status_at']
|
104
|
+
end
|
105
|
+
|
106
|
+
def last_status_at=(last_status)
|
107
|
+
data['contact_account']['last_status_at'] = last_status
|
108
|
+
end
|
109
|
+
|
110
|
+
# @return [String,nil]
|
111
|
+
def header
|
112
|
+
@header ||= [find_best_value_for(site.config, %w[activity_pub images], %w[image path])].flatten.compact.first
|
113
|
+
end
|
114
|
+
|
115
|
+
# @return [Array<String>]
|
116
|
+
def languages
|
117
|
+
@languages ||= site.config['locales'] || [locale]
|
118
|
+
end
|
119
|
+
|
120
|
+
# @return [String,nil]
|
121
|
+
def email
|
122
|
+
@email ||= find_best_value_for(site.config, %w[activity_pub email], 'email')
|
123
|
+
end
|
124
|
+
|
125
|
+
def avatar
|
126
|
+
@avatar ||= [find_best_value_for(site.config, %w[activity_pub icons], 'logo')].flatten.compact.first
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
@@ -1,13 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
require_relative 'helper'
|
5
|
-
require_relative 'version'
|
3
|
+
require_relative 'instance_v1'
|
6
4
|
|
7
5
|
module Jekyll
|
8
6
|
module ActivityPub
|
9
7
|
# Points to site's metadata
|
10
|
-
class
|
8
|
+
class InstanceV2 < InstanceV1
|
11
9
|
include Helper
|
12
10
|
|
13
11
|
# Initialize with default data
|
@@ -17,21 +15,13 @@ module Jekyll
|
|
17
15
|
# @param :dir [String]
|
18
16
|
# @param :name [String]
|
19
17
|
def initialize(site, base = '', dir = 'api/v2', name = 'instance')
|
20
|
-
@context = StubContext.new(registers: { site: site })
|
21
|
-
|
22
18
|
super(site, base, dir, name)
|
23
|
-
|
24
|
-
trigger_hooks :post_init
|
25
19
|
end
|
26
20
|
|
27
21
|
def permalink
|
28
22
|
'api/v2/instance/'
|
29
23
|
end
|
30
24
|
|
31
|
-
def output_ext
|
32
|
-
'.json'
|
33
|
-
end
|
34
|
-
|
35
25
|
def read_yaml(*)
|
36
26
|
self.data = {
|
37
27
|
'domain' => hostname,
|
@@ -92,25 +82,19 @@ module Jekyll
|
|
92
82
|
}
|
93
83
|
end
|
94
84
|
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
def header
|
99
|
-
@header ||= [find_best_value_for(site.config, %w[activity_pub images], %w[image path])].flatten.compact.first
|
85
|
+
def increase_local_posts_counter!
|
86
|
+
data['contact']['account']['statuses_count'] += 1
|
87
|
+
nil
|
100
88
|
end
|
101
89
|
|
102
|
-
|
103
|
-
def languages
|
104
|
-
@languages ||= site.config['locales'] || [locale]
|
105
|
-
end
|
90
|
+
private
|
106
91
|
|
107
|
-
|
108
|
-
|
109
|
-
@email ||= find_best_value_for(site.config, %w[activity_pub email], 'email')
|
92
|
+
def last_status_at
|
93
|
+
data['contact']['account']['last_status_at']
|
110
94
|
end
|
111
95
|
|
112
|
-
def
|
113
|
-
|
96
|
+
def last_status_at=(last_status)
|
97
|
+
data['contact']['account']['last_status_at'] = last_status
|
114
98
|
end
|
115
99
|
end
|
116
100
|
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'helper'
|
4
|
+
|
5
|
+
module Jekyll
|
6
|
+
module ActivityPub
|
7
|
+
# Represents a Link
|
8
|
+
class Link
|
9
|
+
include Helper
|
10
|
+
|
11
|
+
attr_reader :data
|
12
|
+
|
13
|
+
# Initialize with default data
|
14
|
+
#
|
15
|
+
# @param :site [Jekyll::Site]
|
16
|
+
# @param :href [String]
|
17
|
+
# @param :rel [String]
|
18
|
+
# @param :media_type [String]
|
19
|
+
def initialize(site, href, rel = nil, media_type = nil)
|
20
|
+
@site = site
|
21
|
+
@data = {
|
22
|
+
'type' => 'Link',
|
23
|
+
'mediaType' => media_type,
|
24
|
+
'href' => href,
|
25
|
+
'rel' => rel
|
26
|
+
}
|
27
|
+
|
28
|
+
trigger_hooks :post_init
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -4,6 +4,8 @@ require 'pathname'
|
|
4
4
|
require 'httparty'
|
5
5
|
require 'distributed_press/version'
|
6
6
|
require 'distributed_press/v1/social/client'
|
7
|
+
require 'distributed_press/v1/social/inbox'
|
8
|
+
require 'distributed_press/v1/social/outbox'
|
7
9
|
require_relative 'errors'
|
8
10
|
require_relative 'create'
|
9
11
|
require_relative 'update'
|
@@ -64,11 +66,6 @@ module Jekyll
|
|
64
66
|
"#{url}/v1/#{actor}/followers"
|
65
67
|
end
|
66
68
|
|
67
|
-
# @return [String]
|
68
|
-
def following_url
|
69
|
-
"#{url}/v1/#{actor}/following"
|
70
|
-
end
|
71
|
-
|
72
69
|
# Save the public key URL for later
|
73
70
|
#
|
74
71
|
# @param :url [String]
|
@@ -123,21 +120,10 @@ module Jekyll
|
|
123
120
|
raise NotificationError, "Public key at #{public_key_url} differs from local version"
|
124
121
|
end
|
125
122
|
|
126
|
-
base_endpoint = "/v1/#{actor}"
|
127
|
-
outbox_endpoint = "#{base_endpoint}/outbox"
|
128
123
|
actor_object = object_for(site.in_dest_dir(actor_url.sub(site.config['url'], '')))
|
129
|
-
# TODO: Move to API client
|
130
|
-
inbox_body = {
|
131
|
-
'actorUrl' => actor_url,
|
132
|
-
'publicKeyId' => public_key_url,
|
133
|
-
'keypair' => {
|
134
|
-
'publicKeyPem' => client.public_key.public_to_pem,
|
135
|
-
'privateKeyPem' => client.private_key.export
|
136
|
-
}
|
137
|
-
}
|
138
124
|
|
139
125
|
# Create inbox
|
140
|
-
unless (response =
|
126
|
+
unless (response = inbox.create(actor_url)).ok?
|
141
127
|
raise NotificationError, "Couldn't create inbox (#{response.code}: #{response.message})"
|
142
128
|
end
|
143
129
|
|
@@ -145,7 +131,7 @@ module Jekyll
|
|
145
131
|
data['notifications'].reject do |object_url, _|
|
146
132
|
done? object_url
|
147
133
|
end.each do |object_url, status|
|
148
|
-
process_object(
|
134
|
+
process_object(actor_object, object_for(object_url), status)
|
149
135
|
end
|
150
136
|
|
151
137
|
# Update actor profile
|
@@ -153,7 +139,7 @@ module Jekyll
|
|
153
139
|
Jekyll.logger.debug 'ActivityPub:', 'Updating Actor profile'
|
154
140
|
actor_update = Jekyll::ActivityPub::Update.new(site, actor_object, actor_object)
|
155
141
|
|
156
|
-
unless (response =
|
142
|
+
unless (response = outbox.post(activity: actor_update)).ok?
|
157
143
|
raise NotificationError, "Couldn't update actor (#{response.code}: #{response.message})"
|
158
144
|
end
|
159
145
|
end
|
@@ -316,6 +302,14 @@ module Jekyll
|
|
316
302
|
)
|
317
303
|
end
|
318
304
|
|
305
|
+
def inbox
|
306
|
+
@@inbox ||= DistributedPress::V1::Social::Inbox.new(client: client, actor: actor)
|
307
|
+
end
|
308
|
+
|
309
|
+
def outbox
|
310
|
+
@@outbox ||= DistributedPress::V1::Social::Outbox.new(client: client, actor: actor)
|
311
|
+
end
|
312
|
+
|
319
313
|
# Run action
|
320
314
|
#
|
321
315
|
# @param :path [String]
|
@@ -342,16 +336,15 @@ module Jekyll
|
|
342
336
|
|
343
337
|
# Turns an object into an activity and notifies outbox
|
344
338
|
#
|
345
|
-
# @param :endpoint [String]
|
346
339
|
# @param :actor [PseudoObject]
|
347
340
|
# @param :object [PseudoObject]
|
348
341
|
# @param :status [Hash]
|
349
342
|
# @return [nil]
|
350
|
-
def process_object(
|
343
|
+
def process_object(actor, object, status)
|
351
344
|
action = status['action']
|
352
345
|
activity = Object.const_get("Jekyll::ActivityPub::#{action.capitalize}").new(site, actor, object)
|
353
346
|
|
354
|
-
if (response =
|
347
|
+
if (response = outbox.post(activity: activity)).ok?
|
355
348
|
status['action'] = 'done'
|
356
349
|
status["#{action}d_at"] = Time.now.to_i
|
357
350
|
else
|
data/lib/jekyll/activity_pub.rb
CHANGED
@@ -11,7 +11,9 @@ require_relative 'activity_pub/public_key'
|
|
11
11
|
require_relative 'activity_pub/nodeinfo'
|
12
12
|
require_relative 'activity_pub/nodeinfo_20'
|
13
13
|
require_relative 'activity_pub/nodeinfo_21'
|
14
|
-
require_relative 'activity_pub/
|
14
|
+
require_relative 'activity_pub/instance_v1'
|
15
|
+
require_relative 'activity_pub/instance_v2'
|
16
|
+
require_relative 'activity_pub/following'
|
15
17
|
|
16
18
|
module Jekyll
|
17
19
|
# ActivityPub
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'jekyll-activity-pub-nokogiri'
|
4
|
+
|
5
|
+
# Modifies the Activity contents so any element with a src attribute
|
6
|
+
# uses absolute URLs
|
7
|
+
Jekyll::Hooks.register :activity, :post_init, priority: 35 do |activity|
|
8
|
+
case activity
|
9
|
+
when Jekyll::ActivityPub::Activity
|
10
|
+
url = Addressable::URI.parse(activity.data['id'])
|
11
|
+
|
12
|
+
activity.data['content'].css('[src]').each do |img|
|
13
|
+
uri = Addressable::URI.parse(img['src'])
|
14
|
+
|
15
|
+
next unless uri.relative?
|
16
|
+
|
17
|
+
raise "Can't convert relative paths yet" if uri.path.start_with? '..'
|
18
|
+
|
19
|
+
uri.path = "/#{uri.path}" unless uri.path.start_with? '/'
|
20
|
+
|
21
|
+
uri.hostname = url.hostname
|
22
|
+
uri.scheme = url.scheme
|
23
|
+
|
24
|
+
img['src'] = uri.to_s
|
25
|
+
rescue Exception => e
|
26
|
+
Jekyll.logger.error 'ActivityPub:', "#{img['src']}: #{e}"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'jekyll-activity-pub-absolute-assets'
|
4
|
+
|
5
|
+
# Convert all embedded images, videos and audios into attachments. Note
|
6
|
+
# Mastodon only supports four attachments per post.
|
7
|
+
#
|
8
|
+
# The hook run after absolute assets.
|
9
|
+
Jekyll::Hooks.register :activity, :post_init, priority: 34 do |activity|
|
10
|
+
activity.data['content'].css('img[src],video[src],audio[src]').each do |element|
|
11
|
+
src = Addressable::URI.parse(element['src'])
|
12
|
+
|
13
|
+
activity.data['attachment'] << Jekyll::ActivityPub::Document.new(activity.site, src.path, element['alt'].to_s)
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Implement FEP-fffd Proxy Objects for Distributed Press by creating new
|
4
|
+
# activities and actors under supported protocols/schemes.
|
5
|
+
#
|
6
|
+
# Priority is low so it's the last thing we do. If you need to modify
|
7
|
+
# the original activities after this plugins runs, use priority 0.
|
8
|
+
#
|
9
|
+
# The hook runs on pre render so we can add the extra pages.
|
10
|
+
Jekyll::Hooks.register :site, :pre_render, priority: 1 do |site|
|
11
|
+
require 'jekyll/activity_pub/link'
|
12
|
+
|
13
|
+
# Changes the URLs from a base URL to have a different scheme
|
14
|
+
#
|
15
|
+
# @param object [Any]
|
16
|
+
# @param base_url [String]
|
17
|
+
# @param scheme [String]
|
18
|
+
def convert_uris(object, base_url, scheme)
|
19
|
+
case object
|
20
|
+
when Hash
|
21
|
+
object.transform_values do |value|
|
22
|
+
convert_uris(value, base_url, scheme)
|
23
|
+
end
|
24
|
+
when Array
|
25
|
+
object.map do |value|
|
26
|
+
convert_uris(value, base_url, scheme)
|
27
|
+
end
|
28
|
+
when String
|
29
|
+
if object.start_with? base_url
|
30
|
+
Addressable::URI.parse(object).tap do |uri|
|
31
|
+
uri.scheme = scheme
|
32
|
+
end.to_s
|
33
|
+
else
|
34
|
+
object
|
35
|
+
end
|
36
|
+
when Nokogiri::HTML5::DocumentFragment
|
37
|
+
object.dup.tap do |html|
|
38
|
+
html.css('[src]').each do |element|
|
39
|
+
element['src'] = convert_uris(element['src'], base_url, scheme)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
when Jekyll::ActivityPub::Helper
|
43
|
+
convert_uris(object.data, base_url, scheme)
|
44
|
+
else
|
45
|
+
object
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
site.pages.each do |page|
|
50
|
+
case page
|
51
|
+
when Jekyll::ActivityPub::Activity, Jekyll::ActivityPub::Actor
|
52
|
+
site = page.site
|
53
|
+
uri = Addressable::URI.parse page.data['id']
|
54
|
+
url = [ Jekyll::ActivityPub::Link.new(site, page.data['url'], 'canonical', 'text/html') ]
|
55
|
+
|
56
|
+
%w[https ipns hyper bittorrent].each do |protocol|
|
57
|
+
uri.scheme = protocol
|
58
|
+
url <<
|
59
|
+
Jekyll::ActivityPub::Link.new(site, uri.to_s, 'alternate', 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"')
|
60
|
+
url <<
|
61
|
+
Jekyll::ActivityPub::Link.new(site, uri.to_s, 'alternate', 'application/activity+json')
|
62
|
+
end
|
63
|
+
|
64
|
+
%w[ipns hyper bittorrent].each do |protocol|
|
65
|
+
json = convert_uris(page.data, site.config['url'], protocol).reject do |_, v|
|
66
|
+
v.nil? || (v.respond_to?(:empty?) && v.empty?)
|
67
|
+
end
|
68
|
+
|
69
|
+
uri = Addressable::URI.parse(json['id'])
|
70
|
+
uri.path = uri.path.sub('.jsonld', ".#{protocol}.jsonld")
|
71
|
+
json['id'] = uri.to_s
|
72
|
+
path = uri.path.sub(%r{\A/}, '')
|
73
|
+
|
74
|
+
Jekyll::PageWithoutAFile.new(site, site.source, File.dirname(path), File.basename(path)).tap do |alternate|
|
75
|
+
site.pages << alternate
|
76
|
+
|
77
|
+
alternate.content = json.to_json
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Converts iframes to links. Priority is higher than high.
|
4
|
+
Jekyll::Hooks.register :activity, :post_init, priority: 31 do |activity|
|
5
|
+
activity.data['content'].tap do |html|
|
6
|
+
html.css('iframe[src]').each do |iframe|
|
7
|
+
::Nokogiri::XML::Node.new('p', html) do |p|
|
8
|
+
::Nokogiri::XML::Node.new('a', p) do |a|
|
9
|
+
a['href'] = iframe['src']
|
10
|
+
iframe.replace p
|
11
|
+
p << a
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'nokogiri'
|
4
|
+
|
5
|
+
# Parses the Activity contents as HTML5 so we can modify it later.
|
6
|
+
# Priority is highest so we always have the parsed contents.
|
7
|
+
Jekyll::Hooks.register :activity, :post_init, priority: 100 do |activity|
|
8
|
+
case activity.data['content']
|
9
|
+
when String
|
10
|
+
Jekyll.logger.debug 'ActivityPub:', "Parsing content for #{activity.data['id']}"
|
11
|
+
|
12
|
+
activity.data['content'] =
|
13
|
+
activity.data['contentMap'][activity.locale] =
|
14
|
+
::Nokogiri::HTML5.fragment(activity.data['content'])
|
15
|
+
end
|
16
|
+
end
|
data/lib/jekyll-activity-pub.rb
CHANGED
@@ -29,7 +29,14 @@ Jekyll::Hooks.register :site, :post_read, priority: :low do |site|
|
|
29
29
|
site.pages << site.config['webfinger'] = webfinger = Jekyll::ActivityPub::WebFinger.new(site, actor)
|
30
30
|
site.pages << site.config['outbox'] = Jekyll::ActivityPub::Outbox.new(site, actor)
|
31
31
|
site.pages << site.config['host-meta'] = Jekyll::ActivityPub::HostMeta.new(site, webfinger)
|
32
|
-
site.pages <<
|
32
|
+
site.pages << Jekyll::ActivityPub::Following.new(site, actor)
|
33
|
+
|
34
|
+
# Instances
|
35
|
+
site.config['instances'] = [Jekyll::ActivityPub::InstanceV1, Jekyll::ActivityPub::InstanceV2].map do |instance|
|
36
|
+
instance.new(site).tap do |i|
|
37
|
+
site.pages << i
|
38
|
+
end
|
39
|
+
end
|
33
40
|
|
34
41
|
# Nodeinfo
|
35
42
|
site.config['nodeinfos'] = [Jekyll::ActivityPub::Nodeinfo20, Jekyll::ActivityPub::Nodeinfo21].map do |nodeinfo|
|
@@ -97,13 +104,9 @@ Jekyll::Hooks.register(:documents, :post_convert, priority: :high) do |doc|
|
|
97
104
|
outbox.data['orderedItems'] << action
|
98
105
|
|
99
106
|
site.config['nodeinfos'].map(&:increase_local_posts_counter!)
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
last_status_at = site.config['instance'].data['contact']['account']['last_status_at']
|
104
|
-
|
105
|
-
if !last_status_at || last_status_at < doc.date
|
106
|
-
site.config['instance'].data['contact']['account']['last_status_at'] = doc.date
|
107
|
+
site.config['instances'].each do |instance|
|
108
|
+
instance.increase_local_posts_counter!
|
109
|
+
instance.increase_last_status!(doc.date)
|
107
110
|
end
|
108
111
|
|
109
112
|
site.pages << action
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: jekyll-activity-pub
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1
|
4
|
+
version: 0.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sutty
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2024-03-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: distributed-press-api-client
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 0.
|
19
|
+
version: 0.4.0
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 0.
|
26
|
+
version: 0.4.0
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: jekyll
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -139,20 +139,27 @@ extra_rdoc_files:
|
|
139
139
|
files:
|
140
140
|
- LICENSE.txt
|
141
141
|
- README.md
|
142
|
+
- lib/jekyll-activity-pub-absolute-assets.rb
|
143
|
+
- lib/jekyll-activity-pub-assets-as-attachments.rb
|
144
|
+
- lib/jekyll-activity-pub-fep-fffd-distributed-press.rb
|
145
|
+
- lib/jekyll-activity-pub-link-iframes.rb
|
146
|
+
- lib/jekyll-activity-pub-nokogiri.rb
|
142
147
|
- lib/jekyll-activity-pub.rb
|
143
148
|
- lib/jekyll/activity_pub.rb
|
144
149
|
- lib/jekyll/activity_pub/activity.rb
|
145
150
|
- lib/jekyll/activity_pub/actor.rb
|
146
|
-
- lib/jekyll/activity_pub/cache.rb~
|
147
151
|
- lib/jekyll/activity_pub/commands.rb
|
148
152
|
- lib/jekyll/activity_pub/create.rb
|
149
153
|
- lib/jekyll/activity_pub/delete.rb
|
150
154
|
- lib/jekyll/activity_pub/document.rb
|
151
155
|
- lib/jekyll/activity_pub/errors.rb
|
156
|
+
- lib/jekyll/activity_pub/following.rb
|
152
157
|
- lib/jekyll/activity_pub/helper.rb
|
153
158
|
- lib/jekyll/activity_pub/host_meta.rb
|
154
159
|
- lib/jekyll/activity_pub/image.rb
|
155
|
-
- lib/jekyll/activity_pub/
|
160
|
+
- lib/jekyll/activity_pub/instance_v1.rb
|
161
|
+
- lib/jekyll/activity_pub/instance_v2.rb
|
162
|
+
- lib/jekyll/activity_pub/link.rb
|
156
163
|
- lib/jekyll/activity_pub/nodeinfo.rb
|
157
164
|
- lib/jekyll/activity_pub/nodeinfo_20.rb
|
158
165
|
- lib/jekyll/activity_pub/nodeinfo_21.rb
|
@@ -162,7 +169,6 @@ files:
|
|
162
169
|
- lib/jekyll/activity_pub/outbox.rb
|
163
170
|
- lib/jekyll/activity_pub/property_value.rb
|
164
171
|
- lib/jekyll/activity_pub/public_key.rb
|
165
|
-
- lib/jekyll/activity_pub/tomsbtone.rb~
|
166
172
|
- lib/jekyll/activity_pub/update.rb
|
167
173
|
- lib/jekyll/activity_pub/version.rb
|
168
174
|
- lib/jekyll/activity_pub/webfinger.rb
|
@@ -196,9 +202,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
196
202
|
version: '2.7'
|
197
203
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
198
204
|
requirements:
|
199
|
-
- - "
|
205
|
+
- - ">="
|
200
206
|
- !ruby/object:Gem::Version
|
201
|
-
version:
|
207
|
+
version: '0'
|
202
208
|
requirements: []
|
203
209
|
rubygems_version: 3.3.26
|
204
210
|
signing_key:
|
@@ -1,61 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'jekyll/page'
|
4
|
-
require_relative 'helper'
|
5
|
-
|
6
|
-
module Jekyll
|
7
|
-
module ActivityPub
|
8
|
-
# Represents a removed activity
|
9
|
-
class Tombstone < Jekyll::Page
|
10
|
-
include Helper
|
11
|
-
|
12
|
-
# @param :object_id [String]
|
13
|
-
attr_reader :object_id
|
14
|
-
|
15
|
-
# Initialize with default data
|
16
|
-
#
|
17
|
-
# @param :site [Jekyll::Site]
|
18
|
-
# @param :object_id [String]
|
19
|
-
def initialize(site, object_id, )
|
20
|
-
@context = StubContext.new(registers: { site: site })
|
21
|
-
@object_id = object_id
|
22
|
-
|
23
|
-
dest = Pathname.new(object.destination(site.dest)).relative_path_from(site.dest)
|
24
|
-
name = 'tombstone.jsonld'
|
25
|
-
dir = File.join(
|
26
|
-
File.dirname(dest),
|
27
|
-
File.basename(dest, '.jsonld')
|
28
|
-
)
|
29
|
-
|
30
|
-
super(site, '', dir, name)
|
31
|
-
|
32
|
-
trigger_hooks :post_init
|
33
|
-
end
|
34
|
-
|
35
|
-
def read_yaml(*)
|
36
|
-
@data = {
|
37
|
-
'@context' => 'https://www.w3.org/ns/activitystreams',
|
38
|
-
'type' => 'Tomsbtone',
|
39
|
-
'id' => absolute_url(object_id),
|
40
|
-
'published' => object.data[DATE_ATTRIBUTE],
|
41
|
-
'to' => object.data['to'],
|
42
|
-
'cc' => object.data['cc'],
|
43
|
-
'object' => object.data,
|
44
|
-
'inReplyTo' => object.data['in_reply_to']
|
45
|
-
}
|
46
|
-
end
|
47
|
-
|
48
|
-
# @return [Time]
|
49
|
-
def date
|
50
|
-
@date ||= Time.parse(object.data[DATE_ATTRIBUTE])
|
51
|
-
end
|
52
|
-
|
53
|
-
private
|
54
|
-
|
55
|
-
def type
|
56
|
-
@type ||= self.class.name.split('::').last
|
57
|
-
end
|
58
|
-
end
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|