aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/com/juick/www/api
diff options
context:
space:
mode:
authorGravatar Vitaly Takmazov2021-03-24 20:21:43 +0300
committerGravatar Vitaly Takmazov2021-03-24 20:21:43 +0300
commit44411d8ecea4e8676dd2d4d0237c9cd4fd2ec981 (patch)
treea965811cb5ebd6359e65dd9c9b9cc8140e6b976c /src/main/java/com/juick/www/api
parent7f6aa658c287308ebc1ac578e663d2aea5ab1db7 (diff)
ActivityPub: add workaround for Nextcloud Service
Remove when their fix will be merged - https://github.com/nextcloud/social/pull/1230
Diffstat (limited to 'src/main/java/com/juick/www/api')
-rw-r--r--src/main/java/com/juick/www/api/activity/Profile.java115
-rw-r--r--src/main/java/com/juick/www/api/activity/model/Context.java1
2 files changed, 66 insertions, 50 deletions
diff --git a/src/main/java/com/juick/www/api/activity/Profile.java b/src/main/java/com/juick/www/api/activity/Profile.java
index 1a243c09..d416e591 100644
--- a/src/main/java/com/juick/www/api/activity/Profile.java
+++ b/src/main/java/com/juick/www/api/activity/Profile.java
@@ -101,7 +101,8 @@ public class Profile {
@Inject
private Remark remarkConverter;
- @GetMapping(value = "/u/{userName}", produces = {Context.LD_JSON_MEDIA_TYPE, Context.ACTIVITYSTREAMS_PROFILE_MEDIA_TYPE})
+ @GetMapping(value = "/u/{userName}", produces = { Context.LD_JSON_MEDIA_TYPE,
+ Context.ACTIVITYSTREAMS_PROFILE_MEDIA_TYPE, Context.FALLBACK_JSON_MEDIA_TYPE })
public Person getUser(@PathVariable String userName) {
User user = userService.getUserByName(userName);
if (!user.isAnonymous()) {
@@ -128,7 +129,8 @@ public class Profile {
throw new HttpNotFoundException();
}
- @GetMapping(value = "/u/{userName}/blog/toc", produces = {Context.LD_JSON_MEDIA_TYPE, Context.ACTIVITYSTREAMS_PROFILE_MEDIA_TYPE})
+ @GetMapping(value = "/u/{userName}/blog/toc", produces = { Context.LD_JSON_MEDIA_TYPE,
+ Context.ACTIVITYSTREAMS_PROFILE_MEDIA_TYPE })
public OrderedCollection getOutbox(@PathVariable String userName) {
User user = userService.getUserByName(userName);
if (!user.isAnonymous()) {
@@ -142,16 +144,17 @@ public class Profile {
throw new HttpNotFoundException();
}
- @GetMapping(value = "/u/{userName}/blog", produces = {Context.LD_JSON_MEDIA_TYPE, Context.ACTIVITYSTREAMS_PROFILE_MEDIA_TYPE})
+ @GetMapping(value = "/u/{userName}/blog", produces = { Context.LD_JSON_MEDIA_TYPE,
+ Context.ACTIVITYSTREAMS_PROFILE_MEDIA_TYPE })
public OrderedCollectionPage getOutboxPage(@Visitor User visitor, @PathVariable String userName,
- @RequestParam(required = false, defaultValue = "0") int before) {
+ @RequestParam(required = false, defaultValue = "0") int before) {
User user = userService.getUserByName(userName);
if (!user.isAnonymous() && !user.isBanned()) {
UriComponentsBuilder uri = UriComponentsBuilder.fromUriString(baseUri);
String personUri = uri.path(String.format("/u/%s", userName)).toUriString();
List<Integer> mids = messagesService.getUserBlog(user.getUid(), 0, before);
- List<Note> notes = messagesService.getMessages(visitor, mids)
- .stream().map(activityPubManager::makeNote).collect(Collectors.toList());
+ List<Note> notes = messagesService.getMessages(visitor, mids).stream().map(activityPubManager::makeNote)
+ .collect(Collectors.toList());
OrderedCollectionPage page = new OrderedCollectionPage();
page.setPartOf(uri.replacePath(String.format("/u/%s/blog/toc", userName)).toUriString());
page.setFirst(uri.replacePath(String.format("/u/%s/blog", userName)).toUriString());
@@ -175,7 +178,8 @@ public class Profile {
throw new HttpNotFoundException();
}
- @GetMapping(value = "/u/{userName}/followers/toc", produces = {Context.LD_JSON_MEDIA_TYPE, Context.ACTIVITYSTREAMS_PROFILE_MEDIA_TYPE})
+ @GetMapping(value = "/u/{userName}/followers/toc", produces = { Context.LD_JSON_MEDIA_TYPE,
+ Context.ACTIVITYSTREAMS_PROFILE_MEDIA_TYPE })
public OrderedCollection getFollowers(@PathVariable String userName) {
User user = userService.getUserByName(userName);
if (!user.isAnonymous()) {
@@ -189,9 +193,10 @@ public class Profile {
throw new HttpNotFoundException();
}
- @GetMapping(value = "/u/{userName}/followers", produces = {Context.LD_JSON_MEDIA_TYPE, Context.ACTIVITYSTREAMS_PROFILE_MEDIA_TYPE})
+ @GetMapping(value = "/u/{userName}/followers", produces = { Context.LD_JSON_MEDIA_TYPE,
+ Context.ACTIVITYSTREAMS_PROFILE_MEDIA_TYPE })
public OrderedCollectionPage getFollowersPage(@PathVariable String userName,
- @RequestParam(required = false, defaultValue = "0") int page) {
+ @RequestParam(required = false, defaultValue = "0") int page) {
User user = userService.getUserByName(userName);
if (!user.isAnonymous()) {
UriComponentsBuilder uriComponentsBuilder = UriComponentsBuilder.fromUriString(baseUri);
@@ -217,7 +222,8 @@ public class Profile {
throw new HttpNotFoundException();
}
- @GetMapping(value = "/u/{userName}/following/toc", produces = {Context.LD_JSON_MEDIA_TYPE, Context.ACTIVITYSTREAMS_PROFILE_MEDIA_TYPE})
+ @GetMapping(value = "/u/{userName}/following/toc", produces = { Context.LD_JSON_MEDIA_TYPE,
+ Context.ACTIVITYSTREAMS_PROFILE_MEDIA_TYPE })
public OrderedCollection getFollowing(@PathVariable String userName) {
User user = userService.getUserByName(userName);
if (!user.isAnonymous()) {
@@ -231,9 +237,10 @@ public class Profile {
throw new HttpNotFoundException();
}
- @GetMapping(value = "/u/{userName}/following", produces = {Context.LD_JSON_MEDIA_TYPE, Context.ACTIVITYSTREAMS_PROFILE_MEDIA_TYPE})
+ @GetMapping(value = "/u/{userName}/following", produces = { Context.LD_JSON_MEDIA_TYPE,
+ Context.ACTIVITYSTREAMS_PROFILE_MEDIA_TYPE })
public OrderedCollectionPage getFollowingPage(@PathVariable String userName,
- @RequestParam(required = false, defaultValue = "0") int page) {
+ @RequestParam(required = false, defaultValue = "0") int page) {
User user = userService.getUserByName(userName);
if (!user.isAnonymous()) {
UriComponentsBuilder uriComponentsBuilder = UriComponentsBuilder.fromUriString(baseUri);
@@ -259,31 +266,28 @@ public class Profile {
throw new HttpNotFoundException();
}
- @GetMapping(value = "/n/{mid}-{rid}", produces = {Context.LD_JSON_MEDIA_TYPE, Context.ACTIVITYSTREAMS_PROFILE_MEDIA_TYPE})
+ @GetMapping(value = "/n/{mid}-{rid}", produces = { Context.LD_JSON_MEDIA_TYPE,
+ Context.ACTIVITYSTREAMS_PROFILE_MEDIA_TYPE })
public Context showNote(@PathVariable int mid, @PathVariable int rid) {
if (rid > 0) {
// reply
- return Context.build(activityPubManager.makeNote(
- messagesService.getReply(mid, rid)));
+ return Context.build(activityPubManager.makeNote(messagesService.getReply(mid, rid)));
}
- return Context.build(activityPubManager.makeNote(
- messagesService.getMessage(mid).orElseThrow(IllegalStateException::new)));
+ return Context.build(
+ activityPubManager.makeNote(messagesService.getMessage(mid).orElseThrow(IllegalStateException::new)));
}
- @PostMapping(value = "/api/inbox", consumes = {Context.LD_JSON_MEDIA_TYPE, Context.ACTIVITYSTREAMS_PROFILE_MEDIA_TYPE})
- public ResponseEntity<CommandResult> processInbox(
- @Visitor User visitor,
- InputStream inboxData) throws Exception {
+ @PostMapping(value = "/api/inbox", consumes = { Context.LD_JSON_MEDIA_TYPE,
+ Context.ACTIVITYSTREAMS_PROFILE_MEDIA_TYPE })
+ public ResponseEntity<CommandResult> processInbox(@Visitor User visitor, InputStream inboxData) throws Exception {
String inbox = IOUtils.toString(inboxData, StandardCharsets.UTF_8);
logger.info("Inbox: {}", inbox);
Activity activity = jsonMapper.readValue(inbox, Activity.class);
if ((StringUtils.isNotEmpty(visitor.getUri().toString())
- && visitor.getUri().equals(URI.create(activity.getActor())))
- || !visitor.isAnonymous()) {
+ && visitor.getUri().equals(URI.create(activity.getActor()))) || !visitor.isAnonymous()) {
if (activity instanceof Follow) {
Follow followRequest = (Follow) activity;
- applicationEventPublisher.publishEvent(
- new FollowEvent(this, followRequest));
+ applicationEventPublisher.publishEvent(new FollowEvent(this, followRequest));
return new ResponseEntity<>(CommandResult.fromString("Follow request accepted"), HttpStatus.ACCEPTED);
}
@@ -292,11 +296,15 @@ public class Profile {
String objectType = (String) object.get("type");
String objectObject = (String) object.get("object");
if (objectType.equals("Follow")) {
- applicationEventPublisher.publishEvent(new UndoFollowEvent(this, activity.getActor(), objectObject));
- return new ResponseEntity<>(CommandResult.fromString("Undo follow request accepted"), HttpStatus.OK);
+ applicationEventPublisher
+ .publishEvent(new UndoFollowEvent(this, activity.getActor(), objectObject));
+ return new ResponseEntity<>(CommandResult.fromString("Undo follow request accepted"),
+ HttpStatus.OK);
} else if (objectType.equals("Like") || objectType.equals("Announce")) {
- applicationEventPublisher.publishEvent(new UndoAnnounceEvent(this, activity.getActor(), objectObject));
- return new ResponseEntity<>(CommandResult.fromString("Undo like/announce request accepted"), HttpStatus.OK);
+ applicationEventPublisher
+ .publishEvent(new UndoAnnounceEvent(this, activity.getActor(), objectObject));
+ return new ResponseEntity<>(CommandResult.fromString("Undo like/announce request accepted"),
+ HttpStatus.OK);
}
}
if (activity instanceof Create) {
@@ -305,7 +313,8 @@ public class Profile {
if (note.get("type").equals("Note")) {
URI noteId = URI.create((String) note.get("id"));
if (messagesService.replyExists(noteId)) {
- return new ResponseEntity<>(CommandResult.fromString("Reply already exists"), HttpStatus.OK);
+ return new ResponseEntity<>(CommandResult.fromString("Reply already exists"),
+ HttpStatus.OK);
} else {
String inReplyTo = (String) note.get("inReplyTo");
if (StringUtils.isNotBlank(inReplyTo)) {
@@ -314,16 +323,17 @@ public class Profile {
User user = new User();
user.setUri(URI.create(activity.getActor()));
String markdown = remarkConverter.convertFragment((String) note.get("content"));
- String commandBody = note.get("attachment") == null ? markdown :
- ((List<Object>) note.get("attachment")).stream().map(attachmentObj -> {
+ String commandBody = note.get("attachment") == null ? markdown
+ : ((List<Object>) note.get("attachment")).stream().map(attachmentObj -> {
Map<String, String> attachment = (Map<String, String>) attachmentObj;
String attachmentUrl = attachment.get("url");
String attachmentName = attachment.get("name");
return PlainTextFormatter.markdownUrl(attachmentUrl, attachmentName);
- }).reduce(markdown, (currentUrl, nextUrl) -> String.format("%s\n%s", currentUrl, nextUrl));
+ }).reduce(markdown, (currentUrl, nextUrl) -> String.format("%s\n%s",
+ currentUrl, nextUrl));
- CommandResult result = commandsManager.processCommand(
- user, String.format("#%s %s", postId, commandBody),
+ CommandResult result = commandsManager.processCommand(user,
+ String.format("#%s %s", postId, commandBody),
URI.create(StringUtils.EMPTY));
logger.info(jsonMapper.writeValueAsString(result));
if (result.getNewMessage().isPresent()) {
@@ -337,17 +347,19 @@ public class Profile {
if (reply != null) {
User user = new User();
user.setUri(URI.create(activity.getActor()));
- String markdown = remarkConverter.convertFragment((String)note.get("content"));
+ String markdown = remarkConverter.convertFragment((String) note.get("content"));
// combine note text with attachment urls
- String commandBody = note.get("attachment") == null ? markdown :
- ((List<Object>) note.get("attachment")).stream().map(attachmentObj -> {
- Map<String, String> attachment = (Map<String, String>) attachmentObj;
- String attachmentUrl = attachment.get("url");
- String attachmentName = attachment.get("name");
- return PlainTextFormatter.markdownUrl(attachmentUrl, attachmentName);
- }).reduce(markdown, (currentUrl, nextUrl) -> String.format("%s\n%s", currentUrl, nextUrl));
- CommandResult result = commandsManager.processCommand(
- user,
+ String commandBody = note.get("attachment") == null ? markdown
+ : ((List<Object>) note.get("attachment")).stream()
+ .map(attachmentObj -> {
+ Map<String, String> attachment = (Map<String, String>) attachmentObj;
+ String attachmentUrl = attachment.get("url");
+ String attachmentName = attachment.get("name");
+ return PlainTextFormatter.markdownUrl(attachmentUrl,
+ attachmentName);
+ }).reduce(markdown, (currentUrl, nextUrl) -> String
+ .format("%s\n%s", currentUrl, nextUrl));
+ CommandResult result = commandsManager.processCommand(user,
String.format("#%d/%d %s", reply.getMid(), reply.getRid(), commandBody),
URI.create(StringUtils.EMPTY));
logger.info(jsonMapper.writeValueAsString(result));
@@ -369,13 +381,14 @@ public class Profile {
// Delete gone user
// TODO: check if it is really deleted and remove copy-paste
if (activity.getActor().equals(activity.getObject())) {
- return new ResponseEntity<>(CommandResult.fromString("Delete request accepted"), HttpStatus.ACCEPTED);
+ return new ResponseEntity<>(CommandResult.fromString("Delete request accepted"),
+ HttpStatus.ACCEPTED);
}
}
Map<String, Object> tombstone = (Map<String, Object>) activity.getObject();
if (tombstone.get("type").equals("Tombstone")) {
URI actor = URI.create(activity.getActor());
- URI reply = URI.create((String)tombstone.get("id"));
+ URI reply = URI.create((String) tombstone.get("id"));
messagesService.deleteReply(actor, reply);
return new ResponseEntity<>(CommandResult.fromString("Delete request accepted"), HttpStatus.OK);
}
@@ -383,7 +396,7 @@ public class Profile {
if (activity instanceof Like || activity instanceof Announce) {
String messageUri = activity.getObject() instanceof String ? (String) activity.getObject()
: activity.getObject() instanceof Context ? ((Context) activity.getObject()).getId()
- : (String) ((Map)activity.getObject()).get("id");
+ : (String) ((Map) activity.getObject()).get("id");
applicationEventPublisher.publishEvent(new AnnounceEvent(this, activity.getActor(), messageUri));
return new ResponseEntity<>(CommandResult.fromString("Like/announce request accepted"), HttpStatus.OK);
}
@@ -394,13 +407,15 @@ public class Profile {
if (activity.getObject() instanceof String) {
// Delete gone user
if (activity.getActor().equals(activity.getObject())) {
- return new ResponseEntity<>(CommandResult.fromString("Delete request accepted"), HttpStatus.ACCEPTED);
+ return new ResponseEntity<>(CommandResult.fromString("Delete request accepted"),
+ HttpStatus.ACCEPTED);
}
}
}
return new ResponseEntity<>(CommandResult.fromString("Can not authenticate"), HttpStatus.UNAUTHORIZED);
}
- @PostMapping(value = {"/u/", "/api/u/"}, produces = MediaType.APPLICATION_JSON_VALUE)
+
+ @PostMapping(value = { "/u/", "/api/u/" }, produces = MediaType.APPLICATION_JSON_VALUE)
public User fetchUser(@RequestParam URI uri) {
return activityPubManager.personToUser(uri);
}
diff --git a/src/main/java/com/juick/www/api/activity/model/Context.java b/src/main/java/com/juick/www/api/activity/model/Context.java
index 217d2dc1..f41aa69c 100644
--- a/src/main/java/com/juick/www/api/activity/model/Context.java
+++ b/src/main/java/com/juick/www/api/activity/model/Context.java
@@ -91,6 +91,7 @@ public abstract class Context {
public final static String ACTIVITY_STREAMS_URI = "https://www.w3.org/ns/activitystreams";
public final static String SECURITY_URI = "https://w3id.org/security/v1";
public final static String LD_JSON_MEDIA_TYPE = "application/ld+json; profile=\"https://www.w3.org/ns/activitystreams\"";
+ public final static String FALLBACK_JSON_MEDIA_TYPE = "application/json; profile=\"https://www.w3.org/ns/activitystreams\"";
public final static String ACTIVITY_MEDIA_TYPE = "application/activity+json";
public final static String ACTIVITYSTREAMS_PROFILE_MEDIA_TYPE = ACTIVITY_MEDIA_TYPE + "; profile=\"https://www.w3.org/ns/activitystreams\"";
public final static String ACTIVITYSTREAMS_PUBLIC = "https://www.w3.org/ns/activitystreams#Public";