README.md 10 KB
Newer Older
1 2
# ActivityPub for Drupal

3 4
Implements the ActivityPub protocol for your site. Readers will be able to
follow content on Mastodon and other federated platforms that support
swentel's avatar
swentel committed
5
ActivityPub. Responses are possible too (Reply, Like, Announce) with more to
6 7
come.

swentel's avatar
swentel committed
8
The module has been tested with the following federated platforms:
9

swentel's avatar
swentel committed
10 11
- Mastodon: follow/accept, post articles/notes (with image), reply
- Pleroma: follow/accept, post articles/notes (with image), reply
swentel's avatar
swentel committed
12
- Pixelfed: follow/accept, post photos, reply
13

14 15
Open an issue if you have successfully interacted with another platform!

16 17 18 19
## Features

- Enable ActivityPub per user
- Block remote domains from posting
swentel's avatar
swentel committed
20 21
- Discovery via Webfinger module
- Outbox, Inbox and followers endpoints
22
- HttpSignature for authorization
swentel's avatar
swentel committed
23
- Accept follow requests, Undo (follow)
24
- Send posts via drush or cron
swentel's avatar
swentel committed
25 26 27
- Create comments from Create activities from remote users
- Map Activity types and properties to content types and comments and create
  posts to send out to the Fediverse.
28

29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
## Installation and configuration.

Use composer require drupal/activitypub to get all dependencies:

- Drupal webfinger module
- Drupal nodeinfo module
- landrok/activitypub library

1. Enable Activitypub module
2. Configure permissions:
    - 'view user profiles' for anonymous users
    - 'allow users to enable activitypub' for authenticated user (or a role)
3. At this point, when a user has enabled activitypub at user
/x/activitypub/settings, they should be discoverable. Try searching for
@handle@domain on Mastodon. If you follow this user, an entry will arrive
swentel's avatar
swentel committed
44
in the inbox and an Accept outbox entry will be created automatically.
45 46 47 48 49
4. Configure global settings at admin/config/services/activitypub to
select how to process those outbox activities. Then either run cron,
configure a crontab for the drush command or manually call it. The
outbox activities will be send then.
5. On admin/config/services/activitypub/activitypub-type you get an overview
swentel's avatar
swentel committed
50 51
of all ActivityPub Type configuration entities. Three are enabled (and locked)
when enabling this module, which are the 'Accept', 'Delete' and 'Inbox reply'
52 53
types. A few examples are also installed which have basic configuration but
are not enabled yet since this depends on your own setup.
54
6. Create your own configuration
swentel's avatar
swentel committed
55
    - Select 'Type plugin', only dynamic types is currently available
56 57 58 59 60 61 62
    - Select the content type which you want to map
    - Select the activity (See '1' and '2' underneath)
    - Select the object (use Note if you do not want to populate a title)
    - Map properties to the content type fields
7. When saved, go to the content type you selected. You can now select the
entity which will process this node in the 'ActivityPub outbox' fieldset.

swentel's avatar
swentel committed
63
**Important**
64

swentel's avatar
swentel committed
65 66 67
1. The 'Send to' fieldset must have the canonical URL of a user in case the
owner does not follow you and you are replying to a post. Any post will be
sent automatically in 'cc' to all your followers too.
swentel's avatar
swentel committed
68
2. Make sure a Reply, Like or Announce URL point to the id of the post You can
swentel's avatar
swentel committed
69 70
get this id from the application/activity+json representation of a post.
Examples:
swentel's avatar
swentel committed
71 72 73 74
    - Mastodon reply/like
        - Will work: https://mastodon.social/@swentel/104960564425633436
        - Will not work: https://mastodon.social/web/statuses/104960564425633436
    - Pleroma like 'object' needs to be the id of an activity, not the browser
swentel's avatar
swentel committed
75
      URL, but works fine for a reply.
76 77 78 79

Footnotes:

1. Use Create when you want to send regular posts (e.g note, article or reply)
swentel's avatar
swentel committed
80
2. 'Announce' usually stands for the Boost/Retweet/Repeat response
81

swentel's avatar
swentel committed
82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
## Configuring comments

When an Activity is received and has an inReplyTo property, it is possible to
create a comment if the target entity has comments enabled.

You have to create an entity reference field on your comment type which points
to an activity. The activity will be saved, the author and body will be saved
on the comment entity. The reference field does not render anything, so you can
hide it on the  display of the comment. The entity reference field will only be
editable by the the owner of the activity or a user who can manage comments.

To enable this feature, go to /admin/config/services/activitypub.

The default comment format will be set to 'restricted_html'. This can be
changed via settings:

```
$settings['activitypub_comment_format'] = 'full_html';
```

102 103
## Plugins

swentel's avatar
swentel committed
104 105
ActivityPub types (activities, objects, etc) are managed by plugins. This
module ships with two types of plugins:
106 107

- Dynamic types: map content types and properties
swentel's avatar
swentel committed
108 109
- Static types: manages the 'Accept', 'Follow' and 'Undo' activity type and
  handles the comment creation queue.
110

swentel's avatar
swentel committed
111 112 113
**Important**: as this module is still alpha, the interface and methods will
most likely change, so be careful when implementing your own plugin. If a
change happens, the release notes of a new release will document those changes.
114

115 116 117
## Public and Private keys

Public and private keys are saved in private://activitypub/keys.
swentel's avatar
swentel committed
118
The default path can be overridden in settings.php via settings:
119 120

```
swentel's avatar
swentel committed
121
$settings['activitypub_keys_path'] = '/your/path/';
122 123
```

swentel's avatar
swentel committed
124 125 126 127 128 129 130 131 132 133 134
## Caching

For incoming or outgoing requests, information needs to be fetched to get the
inbox endpoint for example. This is saved in private://activitypub/cache
The default path and ttl can be overridden in settings.php:

```
$settings['activitypub_cache_path'] = '/your/path/';
$settings['activitypub_cache_ttl'] = 3600;
```

135
## Default avatar
136

137
The default avatar path can be overridden in settings.php via settings:
138

139 140 141 142 143 144
```
$settings['activitypub_default_avatar_path'] = '/default/image.png';
```

## Inbox and outbox

swentel's avatar
swentel committed
145 146
Every user has an inbox and outbox where activities from remote users are
stored and outgoing posts to your followers.
147 148 149 150 151

'Accept', 'Undo' and handled by the 'Static types' plugin. All other activity
types will be stored, but do not have any impact.

An overview can be found at user/x/activitypub.
152

153 154
## Sending posts to followers

swentel's avatar
swentel committed
155 156 157
On nodes a fieldset will be available to send it to followers. Activities in
the outbox are stored in a queue and send either by cron or drush. Configure
this at /admin/config/services/activitypub
158

swentel's avatar
swentel committed
159 160
The drush command is activitypub:process-outbox which has 3 parameters
- send: send request (defaults to 1)
swentel's avatar
swentel committed
161
- delete: remove queue item (defaults to 1)
162
- debug: show command line debug messages (defaults to 0)
swentel's avatar
swentel committed
163

swentel's avatar
swentel committed
164 165 166 167 168
## Processing inbox activities

A Create activity with inReplyTo will be added to the queue to try and create
a comment on the entity which is stored in the inReplyTo property.

169
## Drush commands
swentel's avatar
swentel committed
170

swentel's avatar
swentel committed
171 172 173
- activitypub:process-outbox: process activities ready to be send out.
- activitypub:process-inbox: process activities (e.g. Create with reply)
- activitypub:add-to-queue: adds an activity to the queue
174 175
- activitypub:delete-activity: send a delete request
- activitypub:webfinger-info: test command to get info about a remote user
176 177 178 179 180

## FAQ

### Can I follow users

swentel's avatar
typo  
swentel committed
181
Technically this would possible with a new plugin, but there's no (decent)
182
interface to view the incoming posts. In combination with the IndieWeb module,
swentel's avatar
swentel committed
183
you can set up a great stack where you can follow content from any source, and
184 185 186 187
interact with it as well.

### Can I use this together with the IndieWeb module

swentel's avatar
swentel committed
188 189
You can use the Microsub module (bundled in the IndieWeb package) to follow
users and then use your favorite  client to read content and interact via
190 191 192
Micropub.

If you are using a Micropub client (or in-built in a Reader), using one or
swentel's avatar
swentel committed
193 194
more syndication targets can help you to create an outbox request. Create a
syndication target which is not a URL. These won't be added then to the
swentel's avatar
swentel committed
195
webmention queue. Once done, you need to implement two hooks with custom code:
196 197

```
swentel's avatar
swentel committed
198 199 200 201 202 203 204 205 206 207 208 209 210
/**
 * Implements hook_indieweb_micropub_node_pre_create_alter().
 */
function hook_indieweb_micropub_node_pre_create_alter(&$values, &$payload) {
  // Reset mp-syndicate-to in case you configure to automatically send
  // a webmention to the link found in in-reply-to.
  if (!empty($payload['mp-syndicate-to'])) {
    if (in_array('activitypub_reply', $payload['mp-syndicate-to'])) {
      $payload['mp-syndicate-to'] = ['activitypub_reply'];
    }
  }
}

swentel's avatar
swentel committed
211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250
/**
 * Implements hook_indieweb_micropub_node_saved().
 */
function hook_indieweb_micropub_node_saved(NodeInterface $node, $values, $payload, $payload_original) {
  if (!empty($payload_original['mp-syndicate-to'])) {
    foreach ($payload_original['mp-syndicate-to'] as $target) {
      switch ($target) {
        // Value of syndication target.
        case 'activitypub_reply':
          if ($node->bundle() == 'reply') {

            $values = [
              'status' => TRUE,
              'collection' => 'outbox',
              // id of reply config entity
              'config_id' => 'reply',
              'uid' => $node->getOwnerId(),
              // Replace {actor_name} with the activitypub name.
              'actor' => 'https://yourdomain.com/user/1/activitypub/{actor_name}',
              'entity_type_id' => 'node',
              'entity_id' => $node->id(),
              'processed' => FALSE,
            ];

            // This is a reply, so we have the in-reply-to microformat value.
            // Other values of this can be 'followers' or the canonical link
            // of a user.
            $values['object'] = $payload_original['in-reply-to'][0];

            /** @var \Drupal\activitypub\Entity\ActivityPubActivityInterface $activity */
            $activity = \Drupal::entityTypeManager()->getStorage('activitypub_activity')->create($values);
            $activity->save();
            \Drupal::service('activitypub.outbox.client')->createQueueItem($activity);
            Cache::invalidateTags(['user:' . $node->getOwnerId()]);
          }
          break;
      }
    }
  }
}
251 252 253 254 255 256 257
```

### Can I send DM's

You can not at this moment, but you should probably just use e-mail :)
Although not tested yet, DM's probably will arrive in the inbox when a remote
user would send one.
swentel's avatar
swentel committed
258 259 260 261 262 263 264 265

## Sponsors

I would like to extend many thanks to the following sponsors for funding development.

- [NLnet Foundation](https://nlnet.nl) and [NGI0
Discovery](https://nlnet.nl/discovery/), part of the [Next Generation
Internet](https://ngi.eu) initiative.