diff options
author | Vitaly Takmazov | 2018-10-10 00:09:58 +0300 |
---|---|---|
committer | Vitaly Takmazov | 2018-10-24 00:00:46 +0300 |
commit | 8e6d764d6bb4391532e5376c795f634ee3898872 (patch) | |
tree | 99c5266ff0e1395b99ac5a70d2eca1e97865c856 | |
parent | ee62ef1659604a373cb1c94d3cf0b1a6fd3946e8 (diff) |
ActivityPub: Mentions and Hashtags
16 files changed, 115 insertions, 25 deletions
diff --git a/juick-common/src/main/java/com/juick/User.java b/juick-common/src/main/java/com/juick/User.java index ca907987..e2e45122 100644 --- a/juick-common/src/main/java/com/juick/User.java +++ b/juick-common/src/main/java/com/juick/User.java @@ -204,7 +204,11 @@ public class User { this.unread = unread; } + @Nonnull public URI getUri() { + if (uri == null) { + uri = URI.create(StringUtils.EMPTY); + } return uri; } diff --git a/juick-server/src/main/java/com/juick/server/ActivityPubManager.java b/juick-server/src/main/java/com/juick/server/ActivityPubManager.java index d494154c..4a6ed7be 100644 --- a/juick-server/src/main/java/com/juick/server/ActivityPubManager.java +++ b/juick-server/src/main/java/com/juick/server/ActivityPubManager.java @@ -4,9 +4,7 @@ import com.juick.Message; import com.juick.User; import com.juick.formatters.PlainTextFormatter; import com.juick.server.api.activity.model.Context; -import com.juick.server.api.activity.model.Image; -import com.juick.server.api.activity.model.Note; -import com.juick.server.api.activity.model.Person; +import com.juick.server.api.activity.model.objects.*; import com.juick.server.api.activity.model.activities.Accept; import com.juick.server.api.activity.model.activities.Announce; import com.juick.server.api.activity.model.activities.Create; @@ -31,6 +29,7 @@ import java.io.IOException; import java.net.URI; import java.util.Collections; import java.util.Optional; +import java.util.stream.Collectors; @Component public class ActivityPubManager implements ActivityListener, NotificationListener { @@ -184,6 +183,10 @@ public class ActivityPubManager implements ActivityListener, NotificationListene uri.replacePath(String.format("/n/%d-%d", mid, rid)); return uri.toUriString(); } + public String tagUri(com.juick.Tag tag) { + UriComponentsBuilder uri = UriComponentsBuilder.fromUriString(baseUri); + return uri.replacePath(String.format("/t/%s", tag.getName())).toUriString(); + } public Note makeNote(Message msg) { Note note = new Note(); @@ -204,7 +207,8 @@ public class ActivityPubManager implements ActivityListener, NotificationListene note.setCc(Collections.singletonList(followersUri(msg.getUser()))); } note.setPublished(msg.getTimestamp()); - note.setContent(msg.isHtml() ? msg.getText() : MessageUtils.formatMessage(msg.getText())); + note.setContent(msg.isHtml() ? msg.getText() + : MessageUtils.formatMessage(StringUtils.defaultString(msg.getText()))); if (StringUtils.isNotBlank(msg.getAttachmentType())) { Image attachment = new Image(); attachment.setId(msg.getAttachment().getMedium().getUrl()); @@ -212,6 +216,23 @@ public class ActivityPubManager implements ActivityListener, NotificationListene attachment.setMediaType(HttpUtils.mediaType(msg.getAttachmentType())); note.setAttachment(attachment); } + note.setTags(msg.getTags().stream().map(t -> { + Hashtag hashtag = new Hashtag(); + hashtag.setId(tagUri(t)); + hashtag.setName("#" + t.getName()); + return hashtag; + }).collect(Collectors.toList())); + if (msg.getReplyToUri().toASCIIString().length() > 0) { + Optional<Context> createContext = signatureManager.getContext(msg.getReplyToUri()); + if (createContext.isPresent()) { + Create activity = (Create) createContext.get(); + Optional<Context> personContext = signatureManager.getContext(URI.create(activity.getActor())); + if (personContext.isPresent()) { + Person person = (Person) personContext.get(); + note.getTags().add(new Mention(person.getUrl(), person.getPreferredUsername())); + } + } + } return note; } diff --git a/juick-server/src/main/java/com/juick/server/KeystoreManager.java b/juick-server/src/main/java/com/juick/server/KeystoreManager.java index 855052c4..97c3a224 100644 --- a/juick-server/src/main/java/com/juick/server/KeystoreManager.java +++ b/juick-server/src/main/java/com/juick/server/KeystoreManager.java @@ -1,6 +1,6 @@ package com.juick.server; -import com.juick.server.api.activity.model.Person; +import com.juick.server.api.activity.model.objects.Person; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; @@ -17,9 +17,7 @@ import java.security.cert.Certificate; import java.security.cert.CertificateException; import java.security.spec.X509EncodedKeySpec; import java.util.Arrays; -import java.util.List; import java.util.stream.Collectors; -import java.util.stream.IntStream; @Component public class KeystoreManager { diff --git a/juick-server/src/main/java/com/juick/server/SignatureManager.java b/juick-server/src/main/java/com/juick/server/SignatureManager.java index c610ea12..e9227b9d 100644 --- a/juick-server/src/main/java/com/juick/server/SignatureManager.java +++ b/juick-server/src/main/java/com/juick/server/SignatureManager.java @@ -2,7 +2,7 @@ package com.juick.server; import com.fasterxml.jackson.databind.ObjectMapper; import com.juick.server.api.activity.model.Context; -import com.juick.server.api.activity.model.Person; +import com.juick.server.api.activity.model.objects.Person; import com.juick.service.activities.DeleteUserEvent; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/juick-server/src/main/java/com/juick/server/api/activity/Profile.java b/juick-server/src/main/java/com/juick/server/api/activity/Profile.java index 317c0e5b..ce09436d 100644 --- a/juick-server/src/main/java/com/juick/server/api/activity/Profile.java +++ b/juick-server/src/main/java/com/juick/server/api/activity/Profile.java @@ -10,17 +10,17 @@ import com.juick.server.KeystoreManager; import com.juick.server.SignatureManager; import com.juick.server.api.activity.model.Activity; import com.juick.server.api.activity.model.Context; -import com.juick.server.api.activity.model.Image; -import com.juick.server.api.activity.model.Key; -import com.juick.server.api.activity.model.Note; -import com.juick.server.api.activity.model.OrderedCollection; -import com.juick.server.api.activity.model.OrderedCollectionPage; -import com.juick.server.api.activity.model.Person; import com.juick.server.api.activity.model.activities.Announce; import com.juick.server.api.activity.model.activities.Create; import com.juick.server.api.activity.model.activities.Delete; import com.juick.server.api.activity.model.activities.Follow; import com.juick.server.api.activity.model.activities.Undo; +import com.juick.server.api.activity.model.objects.Image; +import com.juick.server.api.activity.model.objects.Key; +import com.juick.server.api.activity.model.objects.Note; +import com.juick.server.api.activity.model.objects.OrderedCollection; +import com.juick.server.api.activity.model.objects.OrderedCollectionPage; +import com.juick.server.api.activity.model.objects.Person; import com.juick.server.util.HttpBadRequestException; import com.juick.server.util.HttpNotFoundException; import com.juick.server.util.UserUtils; diff --git a/juick-server/src/main/java/com/juick/server/api/activity/model/Context.java b/juick-server/src/main/java/com/juick/server/api/activity/model/Context.java index 0c47ef73..dd67fa64 100644 --- a/juick-server/src/main/java/com/juick/server/api/activity/model/Context.java +++ b/juick-server/src/main/java/com/juick/server/api/activity/model/Context.java @@ -5,9 +5,12 @@ import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonSubTypes; import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.juick.server.api.activity.model.activities.*; +import com.juick.server.api.activity.model.objects.*; import java.time.Instant; +import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.List; @JsonIgnoreProperties(ignoreUnknown = true) @@ -36,12 +39,16 @@ public abstract class Context { private String id; + private String name; + private Instant published; private String url; private List<String> to; + private List<Context> tags; + public String getId() { return id; } @@ -81,7 +88,8 @@ public abstract class Context { } public static Context build(Context response) { - response.context = Arrays.asList(ACTIVITY_STREAMS_URI, SECURITY_URI); + response.context = new ArrayList(Arrays.asList(ACTIVITY_STREAMS_URI, SECURITY_URI)); + response.context.add(Collections.singletonMap("Hashtag", "as:Hashtag")); return response; } @@ -92,4 +100,21 @@ public abstract class Context { public void setUrl(String url) { this.url = url; } + + @JsonProperty("tag") + public List<Context> getTags() { + return tags; + } + + public void setTags(List<Context> tags) { + this.tags = tags; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } } diff --git a/juick-server/src/main/java/com/juick/server/api/activity/model/objects/Hashtag.java b/juick-server/src/main/java/com/juick/server/api/activity/model/objects/Hashtag.java new file mode 100644 index 00000000..34e73be6 --- /dev/null +++ b/juick-server/src/main/java/com/juick/server/api/activity/model/objects/Hashtag.java @@ -0,0 +1,6 @@ +package com.juick.server.api.activity.model.objects; + +import com.juick.server.api.activity.model.Context; + +public class Hashtag extends Context { +} diff --git a/juick-server/src/main/java/com/juick/server/api/activity/model/Image.java b/juick-server/src/main/java/com/juick/server/api/activity/model/objects/Image.java index 07d6ff99..e067f729 100644 --- a/juick-server/src/main/java/com/juick/server/api/activity/model/Image.java +++ b/juick-server/src/main/java/com/juick/server/api/activity/model/objects/Image.java @@ -1,4 +1,6 @@ -package com.juick.server.api.activity.model; +package com.juick.server.api.activity.model.objects; + +import com.juick.server.api.activity.model.Context; public class Image extends Context { private String mediaType; diff --git a/juick-server/src/main/java/com/juick/server/api/activity/model/Key.java b/juick-server/src/main/java/com/juick/server/api/activity/model/objects/Key.java index bc41b460..075c51dd 100644 --- a/juick-server/src/main/java/com/juick/server/api/activity/model/Key.java +++ b/juick-server/src/main/java/com/juick/server/api/activity/model/objects/Key.java @@ -1,4 +1,6 @@ -package com.juick.server.api.activity.model; +package com.juick.server.api.activity.model.objects; + +import com.juick.server.api.activity.model.Context; public class Key extends Context { private String owner; diff --git a/juick-server/src/main/java/com/juick/server/api/activity/model/Link.java b/juick-server/src/main/java/com/juick/server/api/activity/model/objects/Link.java index 543b5f0c..0c4f26dc 100644 --- a/juick-server/src/main/java/com/juick/server/api/activity/model/Link.java +++ b/juick-server/src/main/java/com/juick/server/api/activity/model/objects/Link.java @@ -1,4 +1,6 @@ -package com.juick.server.api.activity.model; +package com.juick.server.api.activity.model.objects; + +import com.juick.server.api.activity.model.Context; public class Link extends Context { private String href; diff --git a/juick-server/src/main/java/com/juick/server/api/activity/model/objects/Mention.java b/juick-server/src/main/java/com/juick/server/api/activity/model/objects/Mention.java new file mode 100644 index 00000000..dbf3bec9 --- /dev/null +++ b/juick-server/src/main/java/com/juick/server/api/activity/model/objects/Mention.java @@ -0,0 +1,8 @@ +package com.juick.server.api.activity.model.objects; + +public class Mention extends Link { + public Mention(String href, String name) { + this.setHref(href); + this.setName(name); + } +} diff --git a/juick-server/src/main/java/com/juick/server/api/activity/model/Note.java b/juick-server/src/main/java/com/juick/server/api/activity/model/objects/Note.java index 83ef36dd..458b925c 100644 --- a/juick-server/src/main/java/com/juick/server/api/activity/model/Note.java +++ b/juick-server/src/main/java/com/juick/server/api/activity/model/objects/Note.java @@ -1,4 +1,6 @@ -package com.juick.server.api.activity.model; +package com.juick.server.api.activity.model.objects; + +import com.juick.server.api.activity.model.Context; import java.util.List; diff --git a/juick-server/src/main/java/com/juick/server/api/activity/model/OrderedCollection.java b/juick-server/src/main/java/com/juick/server/api/activity/model/objects/OrderedCollection.java index d66c55be..426cf331 100644 --- a/juick-server/src/main/java/com/juick/server/api/activity/model/OrderedCollection.java +++ b/juick-server/src/main/java/com/juick/server/api/activity/model/objects/OrderedCollection.java @@ -1,4 +1,6 @@ -package com.juick.server.api.activity.model; +package com.juick.server.api.activity.model.objects; + +import com.juick.server.api.activity.model.Context; public class OrderedCollection extends Context { diff --git a/juick-server/src/main/java/com/juick/server/api/activity/model/OrderedCollectionPage.java b/juick-server/src/main/java/com/juick/server/api/activity/model/objects/OrderedCollectionPage.java index bcae87d0..601919ba 100644 --- a/juick-server/src/main/java/com/juick/server/api/activity/model/OrderedCollectionPage.java +++ b/juick-server/src/main/java/com/juick/server/api/activity/model/objects/OrderedCollectionPage.java @@ -1,4 +1,6 @@ -package com.juick.server.api.activity.model; +package com.juick.server.api.activity.model.objects; + +import com.juick.server.api.activity.model.Context; import java.util.List; diff --git a/juick-server/src/main/java/com/juick/server/api/activity/model/Person.java b/juick-server/src/main/java/com/juick/server/api/activity/model/objects/Person.java index 00006d4f..2d3a45d7 100644 --- a/juick-server/src/main/java/com/juick/server/api/activity/model/Person.java +++ b/juick-server/src/main/java/com/juick/server/api/activity/model/objects/Person.java @@ -1,6 +1,7 @@ -package com.juick.server.api.activity.model; +package com.juick.server.api.activity.model.objects; import com.fasterxml.jackson.annotation.JsonTypeInfo; +import com.juick.server.api.activity.model.Context; public class Person extends Context { diff --git a/juick-server/src/test/java/com/juick/server/tests/ServerTests.java b/juick-server/src/test/java/com/juick/server/tests/ServerTests.java index 58596850..8a49d96a 100644 --- a/juick-server/src/test/java/com/juick/server/tests/ServerTests.java +++ b/juick-server/src/test/java/com/juick/server/tests/ServerTests.java @@ -18,6 +18,7 @@ package com.juick.server.tests; import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; import com.gargoylesoftware.htmlunit.CookieManager; @@ -33,12 +34,13 @@ import com.juick.model.PrivateChats; import com.juick.model.TagStats; import com.juick.server.*; import com.juick.server.api.activity.model.Context; -import com.juick.server.api.activity.model.Note; -import com.juick.server.api.activity.model.Person; import com.juick.server.api.activity.model.activities.Create; import com.juick.server.api.activity.model.activities.Delete; import com.juick.server.api.activity.model.activities.Follow; import com.juick.server.api.activity.model.activities.Undo; +import com.juick.server.api.activity.model.objects.Mention; +import com.juick.server.api.activity.model.objects.Note; +import com.juick.server.api.activity.model.objects.Person; import com.juick.server.util.HttpUtils; import com.juick.server.util.ImageUtils; import com.juick.server.xmpp.helpers.XMPPStatus; @@ -138,7 +140,8 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. "ios_app_id=12345678.com.juick.ExampleApp", "xmppbot_jid=juick@localhost/Juick", "hostname=localhost", - "componentname=localhost" + "componentname=localhost", + "spring.jackson.default-property-inclusion=non_default" }) @AutoConfigureMockMvc public class ServerTests { @@ -1714,6 +1717,18 @@ public class ServerTests { assertThat(replyNote.getInReplyTo(), equalTo(extMessageUri)); } @Test + public void activitySerialization() throws JsonProcessingException { + Message msg = new Message(); + msg.setMid(1); + User user = new User(); + user.setName("ugnich"); + msg.setUser(user); + msg.setReplyToUri(URI.create("http://localhost:8080/n/1")); + msg.setTags(Collections.singletonList(new Tag("YO"))); + Note note = activityPubManager.makeNote(msg); + String json = jsonMapper.writeValueAsString(Context.build(note)); + } + @Test public void signingSpec() throws IOException { Person from = (Person) signatureManager.getContext(URI.create("http://localhost:8080/u/freefd")).get(); Person to = (Person) signatureManager.getContext(URI.create("http://localhost:8080/u/ugnich")).get(); |