# Authors and claims

Many people who wrote or organised things on the old platform have not joined Zen Social when you move their posts,
events and comments in. Those can still come in under their name, and be handed to them later, when they have joined.
Handing them over is a **claim**. A claim covers posts, events and comments, and can be undone.

## Names from the old platform

A post created with `author` instead of `author_id` (see [Posts](posts.md#who-wrote-it-author_id-or-author)) shows the
name you sent, with no profile and no link:

```json
{"author": {"external_id": "fb-user-1002", "name": "Ole Berg"}}
```

An event takes the same `author` for its organiser (see [Events](events.md)), and a comment for its author (see
[Comments](comments.md)).

The `external_id` in `author` is your own id for that person on the old platform. It is what a claim works with: the
claim hands over **every** post, event and comment of this community that you created with that author
`external_id`. So:

- Use the same author `external_id` for all posts by the same person, and a different one for every person, even when
  two people share a name.
- **Send the post's, event's or comment's own `external_id` too.** Zen Social remembers authors only for posts, events
  and comments created with an `external_id`. One created with an `author` name but without its own `external_id` can
  never be claimed, and stays under the old name for good.

## Claim: `POST /authors/:author_external_id/claim`

When the person has joined and you have found them in `GET /members`, the claim makes them the author of all their
imported posts and comments and the organiser of all their imported events.

**Confirm with the admin first.** Show them the name match you intend to make (for example "Ole Berg on Facebook,
2 posts, 1 event and 1 comment → Ole Berg, member `Qm3TzK8pWn2D`") and wait for their yes. When a name fits more than
one member, or fits only roughly, ask; do not guess.

```sh
curl "$API/authors/fb-user-1002/claim" \
  -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
  -d '{"member_id": "Qm3TzK8pWn2D"}'
```

`member_id` is the member's `id` from [Members](members.md). Answers `201 Created`:

```json
{"claimed": 4, "claimed_ids": [9002, 9003], "claimed_event_ids": [9102], "claimed_comment_ids": [9201], "skipped": 0, "skipped_ids": [], "skipped_event_ids": [], "skipped_comment_ids": []}
```

`claimed` and `skipped` count posts, events **and** comments together. The lists are separate: `claimed_ids` and
`skipped_ids` are **post** ids, `claimed_event_ids` and `skipped_event_ids` are **event** ids, `claimed_comment_ids` and
`skipped_comment_ids` are **comment** ids. The claimed ones now belong to the member; the skipped ones were not handed
over (below).

Other answers:

- `404 not_found`: this community never imported a post, event or comment with that author `external_id`.
- `422 invalid`, with `details.member_id`: `member_id` is missing, or is not a member of this community.

What a claim does:

- The member becomes the author of those posts and comments and the organiser of those events, as if they had made
  them: their name and picture show, and they link to their profile.
- **Nobody is told**, the member included. They keep their dates, show no "edited" mark, and nothing moves in
  anyone's feed. The admin may want to tell the member themselves.
- Deleted posts, events and comments, comments on a deleted post or event, and posts and events turned into the other
  kind in the app, are left alone and not listed.
- A claim can be sent again. Posts, events and comments already claimed for the same member count as claimed again. A
  claim for a **different** member moves them to that member: this is how a wrong match is put right.
- A claimed post, event or comment can still be re-run, changed and deleted through the API (see
  [Who may change which post](posts.md#who-may-change-which-post),
  [Who may change which event](events.md#who-may-change-which-event) and
  [Who may change which comment](comments.md#who-may-change-which-comment)). A re-run never changes its author back.
- A claimed post, event or comment is the member's own. If they delete their account, it goes with it, like any of
  theirs.

## What a claim skips

A post is skipped, and listed in `skipped_ids`, an event is skipped, and listed in `skipped_event_ids`, and a comment is
skipped, and listed in `skipped_comment_ids`, when:

- **the member is not in every one of its circles.** A comment has the circles of the post or event it is on. Nothing
  is handed to someone who cannot see it. Tell the admin which circle it is; once the member has joined it in the app,
  send the same claim again and the skipped ones are claimed then.
- **the admin can no longer post in one of its circles** (for a comment: comment in one of the circles of its post or
  event). Ask the admin to rejoin that circle, or have an admin who can post (or comment) there make a key.

## Undo: `DELETE /authors/:author_external_id/claim`

A claim made by mistake is undone with `DELETE` on the same address. Confirm with the admin first, as for a claim.

```sh
curl -X DELETE "$API/authors/fb-user-1002/claim" -H "Authorization: Bearer $KEY"
```

Answers `200 OK`:

```json
{"released": 4, "released_ids": [9002, 9003], "released_event_ids": [9102], "released_comment_ids": [9201], "skipped": 0, "skipped_ids": [], "skipped_event_ids": [], "skipped_comment_ids": []}
```

It has the same pattern as a claim: `released` and `skipped` count posts, events and comments together, `released_ids`
and `skipped_ids` are post ids, `released_event_ids` and `skipped_event_ids` are event ids, `released_comment_ids` and
`skipped_comment_ids` are comment ids.

The posts, events and comments go back to the name from the old platform, exactly as they were imported, again without
telling anyone. Ones that were never claimed are left as they are and not listed. A post or event in a circle the admin
can no longer post in, and a comment in a circle the admin can no longer comment in, is skipped and listed in
`skipped_ids`, `skipped_event_ids` or `skipped_comment_ids`. `404 not_found` when this community never imported a post,
event or comment with that author `external_id`.

## The author id in the address

The author `external_id` is part of the address, so percent-encode it: a space is `%20`, and a slash **must** be sent
as `%2F`. Letters, digits, `-`, `_`, `.` and `:` can stay as they are.

For the author `external_id` `old-site/users/17`:

```sh
curl "$API/authors/old-site%2Fusers%2F17/claim" \
  -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
  -d '{"member_id": "Qm3TzK8pWn2D"}'
```

## Example: three posts and an event from two Facebook authors

The admin is moving the Facebook group's "Garden Swap" posts and events into the circle with id `412`. Three posts and
one event, by two people:

- Karen Holm wrote one post. She is already a member: `GET /members` lists her as `EveABqLyto9L`, and she is in the
  Garden Swap circle.
- Ole Berg wrote two posts and organised an event. He has not joined yet. His Facebook user id is `1002`.

You have agreed the plan with the admin. The first post is Karen's, under her member id:

```sh
curl "$API/posts" \
  -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
  -d '{"external_id": "fb-post-5001", "circle_ids": [412], "author_id": "EveABqLyto9L", "created_at": "2023-04-15T10:00:00Z", "content": "Who has spare tomato seedlings?\n\nI can swap basil."}'
```

The other two are Ole's, under his name, each with its own `external_id` and both with the same author `external_id`:

```sh
curl "$API/posts" \
  -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
  -d '{"external_id": "fb-post-5002", "circle_ids": [412], "author": {"external_id": "fb-user-1002", "name": "Ole Berg"}, "created_at": "2023-04-16T08:15:00Z", "content": "I have six seedlings for you, Karen."}'
```

```sh
curl "$API/posts" \
  -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
  -d '{"external_id": "fb-post-5003", "circle_ids": [412], "author": {"external_id": "fb-user-1002", "name": "Ole Berg"}, "created_at": "2023-05-02T18:30:00Z", "content": "The swap table is up!", "image_urls": ["https://example.org/swap-table.jpg"]}'
```

Ole's event goes in with the same author `external_id`:

```sh
curl "$API/events" \
  -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
  -d '{"external_id": "fb-event-7002", "circle_ids": [412], "author": {"external_id": "fb-user-1002", "name": "Ole Berg"}, "created_at": "2023-06-01T08:00:00Z", "title": "Midsummer weekend", "all_day": true, "starts_at": "2023-06-24", "ends_at": "2023-06-25", "time_zone": "Europe/Copenhagen"}'
```

Each answers `201 Created`, with the posts getting ids `9001`, `9002` and `9003` and the event `9102`. Nobody is told.
Ask the admin to look at the circle in the app: the posts sit in April and May 2023, the event on 24 and 25 June 2023,
and Ole's show his name without a profile.

Weeks later, Ole accepts the admin's invitation and joins Garden Swap. `GET /members` now lists him:

```json
{"id": "Qm3TzK8pWn2D", "name": "Ole Berg", "avatar_url": null, "circles": [{"id": 412, "name": "Garden Swap"}]}
```

Tell the admin: "Ole Berg on Facebook (2 posts and 1 event) looks like the member Ole Berg (`Qm3TzK8pWn2D`). Shall I
hand them to him?" When they say yes:

```sh
curl "$API/authors/fb-user-1002/claim" \
  -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
  -d '{"member_id": "Qm3TzK8pWn2D"}'
```

It answers `201 Created` with
`{"claimed": 3, "claimed_ids": [9002, 9003], "claimed_event_ids": [9102], "claimed_comment_ids": [], "skipped": 0, "skipped_ids": [], "skipped_event_ids": [], "skipped_comment_ids": []}`.
Both posts are now Ole's, and he is the organiser of the event. Karen's post was never part of it.

If the admin later says it was a different Ole, undo it with `DELETE "$API/authors/fb-user-1002/claim"`, and the
posts and the event show "Ole Berg" from Facebook again.
