Mobilizon federation (#2544)

* Mobilizon federation

* Also accept document attachments from mobilizon
This commit is contained in:
Nutomic 2022-11-12 13:51:08 +00:00 committed by GitHub
parent 83d2959b4b
commit e3bb43542c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 535 additions and 7 deletions

View File

@ -0,0 +1,186 @@
{
"timezone": "Europe/London",
"isOnline": false,
"contacts": [
"https://rendezvous.nomagic.uk/@emorrp1"
],
"cc": [
"https://rendezvous.nomagic.uk/@emorrp1/followers"
],
"id": "https://rendezvous.nomagic.uk/events/b81c0531-a57c-497d-93ba-af0f8b255498",
"inLanguage": "en",
"endTime": "2022-12-11T21:00:00+00:00",
"repliesModerationOption": "allow_all",
"content": "<p>£6 each.</p><p></p><p>The dance style is like a posh ceilidh, with some exciting new ways to turn your partner, set patterns and learn some reels by heart. Looking forward to sharing the Hamilton House and the Inverness with those of you who can make it along to this one.</p><p></p><p>For anyone unfamiliar with <a target=\"_blank\" rel=\"noopener noreferrer ugc\" href=\"https://www.exeterceilidhs.net/\">ceilidhs</a>, they&#39;re very social and energetic dances that are very accessible because everyone gets told exactly what to do by a caller and when to do it. Here&#39;s a <a target=\"_blank\" rel=\"noopener noreferrer ugc\" href=\"https://www.facebook.com/emorrp1/videos/735558448180\">sample video</a> from when I learned CaledonianDancing at uni. The cover photo is by Dave Conner CC-BY-2.0.</p>",
"category": "SPORTS",
"actor": "https://rendezvous.nomagic.uk/@emorrp1",
"type": "Event",
"url": "https://rendezvous.nomagic.uk/events/b81c0531-a57c-497d-93ba-af0f8b255498",
"remainingAttendeeCapacity": null,
"anonymousParticipationEnabled": true,
"ical:status": "CONFIRMED",
"to": [
"https://www.w3.org/ns/activitystreams#Public"
],
"joinMode": "free",
"location": {
"address": {
"addressCountry": "United Kingdom",
"addressLocality": "Teignbridge",
"addressRegion": "England",
"postalCode": "EX6 7TW",
"streetAddress": "Devon Expressway",
"type": "PostalAddress"
},
"id": "https://rendezvous.nomagic.uk/address/e4c95383-15ac-4cc7-adf6-723d74ee2ccc",
"latitude": 50.66881615,
"longitude": -3.537739788359949,
"name": "The Kenn Centre",
"type": "Place"
},
"startTime": "2022-12-11T19:00:00+00:00",
"published": "2022-09-27T14:33:14Z",
"draft": false,
"participantCount": 0,
"uuid": "b81c0531-a57c-497d-93ba-af0f8b255498",
"maximumAttendeeCapacity": 0,
"tag": [
{
"href": "https://rendezvous.nomagic.uk/tags/dance",
"name": "#Dance",
"type": "Hashtag"
},
{
"href": "https://rendezvous.nomagic.uk/tags/caledonian",
"name": "#Caledonian",
"type": "Hashtag"
},
{
"href": "https://rendezvous.nomagic.uk/tags/lesson",
"name": "#Lesson",
"type": "Hashtag"
}
],
"updated": "2022-09-27T14:39:18Z",
"attributedTo": "https://rendezvous.nomagic.uk/@devon_caledonian_society",
"commentsEnabled": true,
"attachment": [
{
"mediaType": "image/jpeg",
"name": "Banner",
"type": "Document",
"url": "https://rendezvous.nomagic.uk/media/cd75bf2f61b66004fe20af4797f5aa847ae1f9ea1c118f53093d6fc4e51a6045.jpg?name=devon_caledonian_society%27s%20banner.jpg"
}
],
"name": "Caledonian scottish dance class",
"@context": [
"https://www.w3.org/ns/activitystreams",
"https://w3id.org/security/v1",
{
"addressRegion": "sc:addressRegion",
"timezone": {
"@id": "mz:timezone",
"@type": "sc:Text"
},
"isOnline": {
"@id": "mz:isOnline",
"@type": "sc:Boolean"
},
"pt": "https://joinpeertube.org/ns#",
"manuallyApprovesFollowers": "as:manuallyApprovesFollowers",
"inLanguage": "sc:inLanguage",
"address": {
"@id": "sc:address",
"@type": "sc:PostalAddress"
},
"discoverable": "toot:discoverable",
"repliesModerationOption": {
"@id": "mz:repliesModerationOption",
"@type": "mz:repliesModerationOptionType"
},
"sc": "http://schema.org#",
"mz": "https://joinmobilizon.org/ns#",
"category": "sc:category",
"joinModeType": {
"@id": "mz:joinModeType",
"@type": "rdfs:Class"
},
"Hashtag": "as:Hashtag",
"propertyID": "sc:propertyID",
"PostalAddress": "sc:PostalAddress",
"discussions": {
"@id": "mz:discussions",
"@type": "@id"
},
"remainingAttendeeCapacity": "sc:remainingAttendeeCapacity",
"streetAddress": "sc:streetAddress",
"anonymousParticipationEnabled": {
"@id": "mz:anonymousParticipationEnabled",
"@type": "sc:Boolean"
},
"addressLocality": "sc:addressLocality",
"joinMode": {
"@id": "mz:joinMode",
"@type": "mz:joinModeType"
},
"location": {
"@id": "sc:location",
"@type": "sc:Place"
},
"toot": "http://joinmastodon.org/ns#",
"participantCount": {
"@id": "mz:participantCount",
"@type": "sc:Integer"
},
"uuid": "sc:identifier",
"maximumAttendeeCapacity": "sc:maximumAttendeeCapacity",
"participationMessage": {
"@id": "mz:participationMessage",
"@type": "sc:Text"
},
"openness": {
"@id": "mz:openness",
"@type": "@id"
},
"members": {
"@id": "mz:members",
"@type": "@id"
},
"events": {
"@id": "mz:events",
"@type": "@id"
},
"resources": {
"@id": "mz:resources",
"@type": "@id"
},
"addressCountry": "sc:addressCountry",
"posts": {
"@id": "mz:posts",
"@type": "@id"
},
"commentsEnabled": {
"@id": "pt:commentsEnabled",
"@type": "sc:Boolean"
},
"value": "sc:value",
"PropertyValue": "sc:PropertyValue",
"repliesModerationOptionType": {
"@id": "mz:repliesModerationOptionType",
"@type": "rdfs:Class"
},
"todos": {
"@id": "mz:todos",
"@type": "@id"
},
"ical": "http://www.w3.org/2002/12/cal/ical#",
"postalCode": "sc:postalCode",
"memberCount": {
"@id": "mz:memberCount",
"@type": "sc:Integer"
},
"@language": "und"
}
],
"mediaType": "text/html"
}

View File

@ -0,0 +1,168 @@
{
"@context": [
"https://www.w3.org/ns/activitystreams",
"https://w3id.org/security/v1",
{
"addressRegion": "sc:addressRegion",
"timezone": {
"@id": "mz:timezone",
"@type": "sc:Text"
},
"isOnline": {
"@id": "mz:isOnline",
"@type": "sc:Boolean"
},
"pt": "https://joinpeertube.org/ns#",
"manuallyApprovesFollowers": "as:manuallyApprovesFollowers",
"inLanguage": "sc:inLanguage",
"address": {
"@id": "sc:address",
"@type": "sc:PostalAddress"
},
"discoverable": "toot:discoverable",
"repliesModerationOption": {
"@id": "mz:repliesModerationOption",
"@type": "mz:repliesModerationOptionType"
},
"sc": "http://schema.org#",
"mz": "https://joinmobilizon.org/ns#",
"category": "sc:category",
"joinModeType": {
"@id": "mz:joinModeType",
"@type": "rdfs:Class"
},
"Hashtag": "as:Hashtag",
"propertyID": "sc:propertyID",
"PostalAddress": "sc:PostalAddress",
"discussions": {
"@id": "mz:discussions",
"@type": "@id"
},
"remainingAttendeeCapacity": "sc:remainingAttendeeCapacity",
"streetAddress": "sc:streetAddress",
"anonymousParticipationEnabled": {
"@id": "mz:anonymousParticipationEnabled",
"@type": "sc:Boolean"
},
"addressLocality": "sc:addressLocality",
"joinMode": {
"@id": "mz:joinMode",
"@type": "mz:joinModeType"
},
"location": {
"@id": "sc:location",
"@type": "sc:Place"
},
"toot": "http://joinmastodon.org/ns#",
"participantCount": {
"@id": "mz:participantCount",
"@type": "sc:Integer"
},
"uuid": "sc:identifier",
"maximumAttendeeCapacity": "sc:maximumAttendeeCapacity",
"participationMessage": {
"@id": "mz:participationMessage",
"@type": "sc:Text"
},
"openness": {
"@id": "mz:openness",
"@type": "@id"
},
"members": {
"@id": "mz:members",
"@type": "@id"
},
"events": {
"@id": "mz:events",
"@type": "@id"
},
"resources": {
"@id": "mz:resources",
"@type": "@id"
},
"addressCountry": "sc:addressCountry",
"posts": {
"@id": "mz:posts",
"@type": "@id"
},
"commentsEnabled": {
"@id": "pt:commentsEnabled",
"@type": "sc:Boolean"
},
"value": "sc:value",
"PropertyValue": "sc:PropertyValue",
"repliesModerationOptionType": {
"@id": "mz:repliesModerationOptionType",
"@type": "rdfs:Class"
},
"todos": {
"@id": "mz:todos",
"@type": "@id"
},
"ical": "http://www.w3.org/2002/12/cal/ical#",
"postalCode": "sc:postalCode",
"memberCount": {
"@id": "mz:memberCount",
"@type": "sc:Integer"
},
"@language": "und"
}
],
"discoverable": true,
"discussions": "https://mobilizon.fr/@contribateliers/discussions",
"endpoints": {
"discussions": "https://mobilizon.fr/@contribateliers/discussions",
"events": "https://mobilizon.fr/@contribateliers/events",
"members": "https://mobilizon.fr/@contribateliers/members",
"posts": "https://mobilizon.fr/@contribateliers/posts",
"resources": "https://mobilizon.fr/@contribateliers/resources",
"sharedInbox": "https://mobilizon.fr/inbox",
"todos": "https://mobilizon.fr/@contribateliers/todos"
},
"events": "https://mobilizon.fr/@contribateliers/events",
"followers": "https://mobilizon.fr/@contribateliers/followers",
"following": "https://mobilizon.fr/@contribateliers/following",
"icon": {
"mediaType": null,
"type": "Image",
"url": "https://mobilizon.fr/media/a94f7f8da4b39f6b375f55bd8664abff4ae61d33496df7ee23ad6bf473c3632f.png?name=contribateliers%27s%20avatar.png"
},
"id": "https://mobilizon.fr/@contribateliers",
"image": {
"mediaType": null,
"type": "Image",
"url": "https://mobilizon.fr/media/7fe251dd5f8b5abcea10c31b655c09afee457efdd49f3087ba78b054b3f0dbeb.jpg?name=contribateliers%27s%20banner.jpg"
},
"inbox": "https://mobilizon.fr/@contribateliers/inbox",
"location": {
"address": {
"addressCountry": null,
"addressLocality": null,
"addressRegion": null,
"postalCode": null,
"streetAddress": null,
"type": "PostalAddress"
},
"id": "https://mobilizon.fr/address/935f207e-4c0f-4818-8762-51d6ab2ed27e",
"name": null,
"type": "Place"
},
"manuallyApprovesFollowers": false,
"memberCount": 13,
"members": "https://mobilizon.fr/@contribateliers/members",
"name": "Contribateliers",
"openness": "open",
"outbox": "https://mobilizon.fr/@contribateliers/outbox",
"posts": "https://mobilizon.fr/@contribateliers/posts",
"preferredUsername": "contribateliers",
"publicKey": {
"id": "https://mobilizon.fr/@contribateliers#main-key",
"owner": "https://mobilizon.fr/@contribateliers",
"publicKeyPem": "-----BEGIN RSA PUBLIC KEY-----\nMIIBCgKCAQEA1laog+0zKOkGdUHfWQ+lIJq5LOwWzGKLeqXzSdvaUzfk2X5Q5gTf\nbjh7pWJaWo2uxrIeNKRJSpmxeBn/lNR3+OrG05/MiYW6Y42q+ZL18coUDht46u23\nHH9+fFblmvY905cNslJ4/NouxpN0ai5JytZOzlNnJCan241rS4gkeLAy+LDW6UOd\nTvDPMJQlrAl8gr+OamRUxd4RL/8ws7/FbqNiAetXmN/5knjkQe5rFi0D/3fQtWEv\n/kSTG6CmnBhpeKE8eqp1sD0+CMROfOb7ceVIpJvUKAPHsENRE6DQFF9j3wl8AXjd\ndtGxTyOYYaMXCPyAUBjH/Rt6uV5Bc5x2CQIDAQAB\n-----END RSA PUBLIC KEY-----\n\n"
},
"resources": "https://mobilizon.fr/@contribateliers/resources",
"summary": "<p>Des ateliers pour contribuer au libre sans rien y connaître.</p>",
"todos": "https://mobilizon.fr/@contribateliers/todos",
"type": "Group",
"url": "https://mobilizon.fr/@contribateliers"
}

View File

@ -0,0 +1,144 @@
{
"@context": [
"https://www.w3.org/ns/activitystreams",
"https://w3id.org/security/v1",
{
"addressRegion": "sc:addressRegion",
"timezone": {
"@id": "mz:timezone",
"@type": "sc:Text"
},
"isOnline": {
"@id": "mz:isOnline",
"@type": "sc:Boolean"
},
"pt": "https://joinpeertube.org/ns#",
"manuallyApprovesFollowers": "as:manuallyApprovesFollowers",
"inLanguage": "sc:inLanguage",
"address": {
"@id": "sc:address",
"@type": "sc:PostalAddress"
},
"discoverable": "toot:discoverable",
"repliesModerationOption": {
"@id": "mz:repliesModerationOption",
"@type": "mz:repliesModerationOptionType"
},
"sc": "http://schema.org#",
"mz": "https://joinmobilizon.org/ns#",
"category": "sc:category",
"joinModeType": {
"@id": "mz:joinModeType",
"@type": "rdfs:Class"
},
"Hashtag": "as:Hashtag",
"propertyID": "sc:propertyID",
"PostalAddress": "sc:PostalAddress",
"discussions": {
"@id": "mz:discussions",
"@type": "@id"
},
"remainingAttendeeCapacity": "sc:remainingAttendeeCapacity",
"streetAddress": "sc:streetAddress",
"anonymousParticipationEnabled": {
"@id": "mz:anonymousParticipationEnabled",
"@type": "sc:Boolean"
},
"addressLocality": "sc:addressLocality",
"joinMode": {
"@id": "mz:joinMode",
"@type": "mz:joinModeType"
},
"location": {
"@id": "sc:location",
"@type": "sc:Place"
},
"toot": "http://joinmastodon.org/ns#",
"participantCount": {
"@id": "mz:participantCount",
"@type": "sc:Integer"
},
"uuid": "sc:identifier",
"maximumAttendeeCapacity": "sc:maximumAttendeeCapacity",
"participationMessage": {
"@id": "mz:participationMessage",
"@type": "sc:Text"
},
"openness": {
"@id": "mz:openness",
"@type": "@id"
},
"members": {
"@id": "mz:members",
"@type": "@id"
},
"events": {
"@id": "mz:events",
"@type": "@id"
},
"resources": {
"@id": "mz:resources",
"@type": "@id"
},
"addressCountry": "sc:addressCountry",
"posts": {
"@id": "mz:posts",
"@type": "@id"
},
"commentsEnabled": {
"@id": "pt:commentsEnabled",
"@type": "sc:Boolean"
},
"value": "sc:value",
"PropertyValue": "sc:PropertyValue",
"repliesModerationOptionType": {
"@id": "mz:repliesModerationOptionType",
"@type": "rdfs:Class"
},
"todos": {
"@id": "mz:todos",
"@type": "@id"
},
"ical": "http://www.w3.org/2002/12/cal/ical#",
"postalCode": "sc:postalCode",
"memberCount": {
"@id": "mz:memberCount",
"@type": "sc:Integer"
},
"@language": "und"
}
],
"discoverable": false,
"discussions": null,
"endpoints": {
"discussions": null,
"events": null,
"members": null,
"posts": null,
"resources": null,
"sharedInbox": "https://mobilizon.fr/inbox",
"todos": null
},
"events": null,
"followers": "https://mobilizon.fr/@sanof44/followers",
"following": "https://mobilizon.fr/@sanof44/following",
"id": "https://mobilizon.fr/@sanof44",
"inbox": "https://mobilizon.fr/@sanof44/inbox",
"manuallyApprovesFollowers": false,
"members": null,
"name": "Sanof44",
"openness": "moderated",
"outbox": "https://mobilizon.fr/@sanof44/outbox",
"posts": null,
"preferredUsername": "sanof44",
"publicKey": {
"id": "https://mobilizon.fr/@sanof44#main-key",
"owner": "https://mobilizon.fr/@sanof44",
"publicKeyPem": "-----BEGIN RSA PUBLIC KEY-----\nMIIBCgKCAQEAneK5zzdQQ/6ElSpPv1mj34IMoIIHcTK+iEjZYd85yPfG4krK5bqI\nkUw0TUXFekpntLfDSsGohayrvD2WhN2b499y/A9wdl77RVLIAcBfE3UXr/TfDnjh\nsQEEzV4ghcYaKmXZa/ct2sSt6poT/WhahVweEugfyA75UHgW5VA7nS5URhd7uZUw\nS2CI8fXigDbJlB9AqcxvR7Uncgsn0JCCt5boP8X1jDrh5PEsqsqePm9ZpxvvX4WD\n1yib/ZPBsTo50hJgHoA9bLXO14KvAOeIrzgOlJkyjWTQ+rk+5ewXIZuM0ECPEzAC\nRcpopBjqk07lMxPu1OMG4D+oI0n0K+PgNwIDAQAB\n-----END RSA PUBLIC KEY-----\n\n"
},
"resources": null,
"summary": "",
"todos": null,
"type": "Person",
"url": "https://mobilizon.fr/@sanof44"
}

View File

@ -167,12 +167,9 @@ impl ApubObject for ApubPost {
let community = page.extract_community(context, request_counter).await?;
let form = if !page.is_mod_action(context).await? {
let url = if let Some(attachment) = page.attachment.first() {
Some(match attachment {
// url as sent by Lemmy (new)
Attachment::Link(link) => link.href.clone(),
Attachment::Image(image) => image.url.clone(),
})
let first_attachment = page.attachment.into_iter().map(|a| a.url()).next();
let url = if first_attachment.is_some() {
first_attachment
} else if page.kind == PageType::Video {
// we cant display videos directly, so insert a link to external video page
Some(page.id.inner().clone())

View File

@ -167,4 +167,11 @@ mod tests {
test_json::<Page>("assets/peertube/objects/video.json").unwrap();
test_json::<Note>("assets/peertube/objects/note.json").unwrap();
}
#[test]
fn test_parse_object_mobilizon() {
test_json::<Group>("assets/mobilizon/objects/group.json").unwrap();
test_json::<Page>("assets/mobilizon/objects/event.json").unwrap();
test_json::<Person>("assets/mobilizon/objects/person.json").unwrap();
}
}

View File

@ -13,7 +13,10 @@ use activitypub_federation::{
},
traits::{ActivityHandler, ApubObject},
};
use activitystreams_kinds::{link::LinkType, object::ImageType};
use activitystreams_kinds::{
link::LinkType,
object::{DocumentType, ImageType},
};
use chrono::{DateTime, FixedOffset};
use itertools::Itertools;
use lemmy_db_schema::newtypes::DbUrl;
@ -29,6 +32,7 @@ pub enum PageType {
Article,
Note,
Video,
Event,
}
#[skip_serializing_none]
@ -80,11 +84,33 @@ pub(crate) struct Image {
pub(crate) url: Url,
}
#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub(crate) struct Document {
#[serde(rename = "type")]
pub(crate) kind: DocumentType,
pub(crate) url: Url,
}
#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(untagged)]
pub(crate) enum Attachment {
Link(Link),
Image(Image),
Document(Document),
}
impl Attachment {
pub(crate) fn url(self) -> Url {
match self {
// url as sent by Lemmy (new)
Attachment::Link(l) => l.href,
// image sent by lotide
Attachment::Image(i) => i.url,
// sent by mobilizon
Attachment::Document(d) => d.url,
}
}
}
#[derive(Clone, Debug, Deserialize, Serialize)]