Merge branch 'bug/move-to-comments-enabled' into 'master'

Bug/move to comments enabled

Closes #328

See merge request framasoft/mobilizon!349
This commit is contained in:
Thomas Citharel 2019-12-16 12:06:09 +01:00
commit e3c915ed8d
5 changed files with 105 additions and 2 deletions

View File

@ -10,7 +10,7 @@ To match usernames to actors, Mobilizon uses [WebFinger](https://tools.ietf.org/
## Instance subscriptions
Instances subscribe to each other through an internal actor named `relay@instance.tld` that publishes (through `Announce`) every created content to it's followers. Each content creation share is saved so that updates and deletes are correctly sent to every
Instances subscribe to each other through an internal actor named `relay@instance.tld` that publishes (through `Announce`) every created content to it's followers. Each content creation share is saved so that updates and deletes are correctly sent to every relay subscriber.
## Activities
@ -46,6 +46,9 @@ See [the corresponding issue](https://framagit.org/framasoft/mobilizon/issues/32
Accepted values: `allow_all`, `closed`, `moderated` (not used at the moment)
!!! info
We also support PeerTube's `commentEnabled` property as a fallback. It is set to `true` only when `repliesModeration` is equal to `allow_all`.
Example:
```json
{
@ -53,6 +56,7 @@ Example:
"...",
{
"mz": "https://joinmobilizon.org/ns#",
"pt": "https://joinpeertube.org/ns#",
"repliesModerationOption": {
"@id": "mz:repliesModerationOption",
"@type": "mz:repliesModerationOptionType"
@ -60,11 +64,16 @@ Example:
"repliesModerationOptionType": {
"@id": "mz:repliesModerationOptionType",
"@type": "rdfs:Class"
},
"commentsEnabled": {
"@id": "pt:commentsEnabled",
"@type": "sc:Boolean"
}
}
],
"...": "...",
"repliesModerationOption": "allow_all",
"commentsEnabled": true,
"type": "Event",
"url": "http://mobilizon1.com/events/8cf76e9f-c426-4912-9cd6-c7030b969611"
}
@ -102,3 +111,61 @@ Example:
"url": "http://mobilizon1.com/events/8cf76e9f-c426-4912-9cd6-c7030b969611"
}
```
#### location
We use Schema.org's `location` property on `Event`.
[The ActivityStream vocabulary to represent places](https://www.w3.org/TR/activitystreams-vocabulary/#places) is quite limited so instead of using `Place` from ActivityStreams we use `Place` from Schema.org.
A [Schema.org `Place` type](https://schema.org/Place) has [an `address` property](https://schema.org/address), which we assume to be [of `PostalAddress` type](https://schema.org/PostalAddress) and [a `geo` property](https://schema.org/geo), which is assumed to be of [`GeoCoordinates` type](https://schema.org/GeoCoordinates).
```json
{
"@context": [
"...",
{
"GeoCoordinates": "sc:GeoCoordinates",
"Place": "sc:Place",
"PostalAddress": "sc:PostalAddress",
"address": {
"@id": "sc:address",
"@type": "sc:PostalAddress"
},
"addressCountry": "sc:addressCountry",
"addressLocality": "sc:addressLocality",
"addressRegion": "sc:addressRegion",
"geo": {
"@id": "sc:geo",
"@type": "sc:GeoCoordinates"
},
"location": {
"@id": "sc:location",
"@type": "sc:Place"
},
"postalCode": "sc:postalCode",
"sc": "http://schema.org#",
"streetAddress": "sc:streetAddress",
}
],
"id": "http://mobilizon2.com/events/945f350d-a3e6-4bcd-9bf2-0bd2e4d353c5",
"location": {
"address": {
"addressCountry": "France",
"addressLocality": "Lyon",
"addressRegion": "Auvergne-Rhône-Alpes",
"postalCode": "69007",
"streetAddress": "10 Rue Jangot",
"type": "PostalAddress"
},
"geo": {
"latitude": 4.8425657,
"longitude": 45.7517141,
"type": "GeoCoordinates"
},
"id": "http://mobilizon2.com/address/bdf7fb53-7177-46f3-8fb3-93c25a802522",
"name": "10 Rue Jangot",
"type": "Place"
},
"type": "Event"
}
```

View File

@ -249,6 +249,7 @@ defmodule Mobilizon.Actors do
case transaction do
{:ok, %{actor: %Actor{} = actor}} ->
{:ok, true} = Cachex.del(:activity_pub, "actor_#{actor.preferred_username}")
{:ok, actor}
{:error, remove, error, _} when remove in [:remove_banner, :remove_avatar] ->

View File

@ -328,6 +328,7 @@ defmodule Mobilizon.Service.ActivityPub do
with audience <-
Audience.calculate_to_and_cc_from_mentions(event),
{:ok, %Event{} = event} <- Events.delete_event(event),
{:ok, true} <- Cachex.del(:activity_pub, "event_#{event.uuid}"),
{:ok, %Tombstone{} = _tombstone} <-
Tombstone.create_tombstone(%{uri: event.url, actor_id: actor.id}),
Share.delete_all_by_uri(event.url),
@ -350,6 +351,7 @@ defmodule Mobilizon.Service.ActivityPub do
with audience <-
Audience.calculate_to_and_cc_from_mentions(comment),
{:ok, %Comment{} = comment} <- Events.delete_comment(comment),
{:ok, true} <- Cachex.del(:activity_pub, "comment_#{comment.uuid}"),
{:ok, %Tombstone{} = _tombstone} <-
Tombstone.create_tombstone(%{uri: comment.url, actor_id: actor.id}),
Share.delete_all_by_uri(comment.url),
@ -730,6 +732,7 @@ defmodule Mobilizon.Service.ActivityPub do
) do
with args <- prepare_args_for_event(args),
{:ok, %Event{} = new_event} <- Events.update_event(old_event, args),
{:ok, true} <- Cachex.del(:activity_pub, "event_#{new_event.uuid}"),
event_as_data <- Convertible.model_to_as(new_event),
audience <-
Audience.calculate_to_and_cc_from_mentions(new_event),
@ -748,6 +751,7 @@ defmodule Mobilizon.Service.ActivityPub do
defp update_actor(%Actor{} = old_actor, args, additional) do
with {:ok, %Actor{} = new_actor} <- Actors.update_actor(old_actor, args),
actor_as_data <- Convertible.model_to_as(new_actor),
{:ok, true} <- Cachex.del(:activity_pub, "actor_#{new_actor.preferred_username}"),
audience <-
Audience.calculate_to_and_cc_from_mentions(new_actor),
additional <- Map.merge(additional, %{"actor" => old_actor.url}),

View File

@ -119,6 +119,7 @@ defmodule Mobilizon.Service.ActivityPub.Converter.Event do
"tag" => event.tags |> ConverterUtils.build_tags(),
"maximumAttendeeCapacity" => event.options.maximum_attendee_capacity,
"repliesModerationOption" => event.options.comment_moderation,
"commentsEnabled" => event.options.comment_moderation == :allow_all,
# "draft" => event.draft,
"ical:status" => event.status |> to_string |> String.upcase(),
"id" => event.url,
@ -140,7 +141,12 @@ defmodule Mobilizon.Service.ActivityPub.Converter.Event do
defp get_options(object) do
%{
maximum_attendee_capacity: object["maximumAttendeeCapacity"],
comment_moderation: object["repliesModerationOption"]
comment_moderation:
Map.get(
object,
"repliesModerationOption",
if(Map.get(object, "commentsEnabled", true), do: :allow_all, else: :closed)
)
}
end

View File

@ -32,10 +32,31 @@ defmodule Mobilizon.Service.ActivityPub.Utils do
%{
"sc" => "http://schema.org#",
"ical" => "http://www.w3.org/2002/12/cal/ical#",
"pt" => "https://joinpeertube.org/ns#",
"Hashtag" => "as:Hashtag",
"category" => "sc:category",
"uuid" => "sc:identifier",
"maximumAttendeeCapacity" => "sc:maximumAttendeeCapacity",
"location" => %{
"@id" => "sc:location",
"@type" => "sc:Place"
},
"Place" => "sc:Place",
"PostalAddress" => "sc:PostalAddress",
"GeoCoordinates" => "sc:GeoCoordinates",
"address" => %{
"@id" => "sc:address",
"@type" => "sc:PostalAddress"
},
"geo" => %{
"@id" => "sc:geo",
"@type" => "sc:GeoCoordinates"
},
"addressCountry" => "sc:addressCountry",
"addressRegion" => "sc:addressRegion",
"postalCode" => "sc:postalCode",
"addressLocality" => "sc:addressLocality",
"streetAddress" => "sc:streetAddress",
"mz" => "https://joinmobilizon.org/ns#",
"repliesModerationOptionType" => %{
"@id" => "mz:repliesModerationOptionType",
@ -45,6 +66,10 @@ defmodule Mobilizon.Service.ActivityPub.Utils do
"@id" => "mz:repliesModerationOption",
"@type" => "mz:repliesModerationOptionType"
},
"commentsEnabled" => %{
"@type" => "sc:Boolean",
"@id" => "pt:commentsEnabled"
},
"joinModeType" => %{
"@id" => "mz:joinModeType",
"@type" => "rdfs:Class"