From d899fdeb4596759b2e22e20e407d7b65797b7123 Mon Sep 17 00:00:00 2001 From: Vitaly Takmazov Date: Mon, 9 Jan 2023 05:56:57 +0300 Subject: Mastodon API: improve status layout, avatars, attachments --- src/main/java/com/juick/ActivityPubManager.java | 28 +++++++++-------- src/main/java/com/juick/www/api/Mastodon.java | 40 +++++++++++++++++++++---- 2 files changed, 50 insertions(+), 18 deletions(-) diff --git a/src/main/java/com/juick/ActivityPubManager.java b/src/main/java/com/juick/ActivityPubManager.java index db8a1acb..b62be93a 100644 --- a/src/main/java/com/juick/ActivityPubManager.java +++ b/src/main/java/com/juick/ActivityPubManager.java @@ -283,6 +283,21 @@ public class ActivityPubManager implements ActivityListener, NotificationListene }); } + public String htmlLayout(Message msg, String baseUri) { + PebbleTemplate noteTemplate = pebbleEngine.getTemplate("layouts/note"); + Map context = new HashMap<>(); + context.put("msg", msg); + context.put("baseUri", profileUriBuilder.baseUri()); + try { + Writer writer = new StringWriter(); + noteTemplate.evaluate(writer, context); + return writer.toString(); + } catch (IOException e) { + logger.warn("template not rendered, falling back"); + return MessageUtils.formatMessage(StringUtils.defaultString(msg.getText())); + } + } + public Note makeNote(Message msg) { Note note = new Note(); note.setId(profileUriBuilder.messageUri(msg)); @@ -345,18 +360,7 @@ public class ActivityPubManager implements ActivityListener, NotificationListene if (msg.isHtml()) { note.setContent(msg.getText()); } else { - PebbleTemplate noteTemplate = pebbleEngine.getTemplate("layouts/note"); - Map context = new HashMap<>(); - context.put("msg", msg); - context.put("baseUri", profileUriBuilder.baseUri()); - try { - Writer writer = new StringWriter(); - noteTemplate.evaluate(writer, context); - note.setContent(writer.toString()); - } catch (IOException e) { - logger.warn("template not rendered, falling back"); - note.setContent(MessageUtils.formatMessage(StringUtils.defaultString(msg.getText()))); - } + note.setContent(htmlLayout(msg, profileUriBuilder.baseUri())); } return note; } diff --git a/src/main/java/com/juick/www/api/Mastodon.java b/src/main/java/com/juick/www/api/Mastodon.java index 414c291a..3d31dcdf 100644 --- a/src/main/java/com/juick/www/api/Mastodon.java +++ b/src/main/java/com/juick/www/api/Mastodon.java @@ -20,6 +20,7 @@ package com.juick.www.api; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.PropertyNamingStrategies; import com.fasterxml.jackson.databind.annotation.JsonNaming; +import com.juick.ActivityPubManager; import com.juick.model.Chat; import com.juick.model.Message; import com.juick.model.User; @@ -30,7 +31,9 @@ import com.juick.service.UserService; import com.juick.util.HttpBadRequestException; import com.juick.util.MessageUtils; import com.juick.www.WebApp; +import com.juick.www.api.activity.helpers.ProfileUriBuilder; import jakarta.validation.Valid; +import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Value; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; @@ -68,6 +71,10 @@ public class Mastodon { MessagesService messagesService; @Inject User serviceUser; + @Inject + ActivityPubManager activityPubManager; + @Inject + ProfileUriBuilder profileUriBuilder; public record ApplicationRequest( @JsonProperty("client_name") String clientName, @@ -91,8 +98,8 @@ public class Mastodon { Integer followersCount, Integer followingCount, String avatar, + String avatarStatic, AccountSource source) { - } private Collection parseScopes(String s) { @@ -219,7 +226,8 @@ public class Mastodon { @JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class) public record Status(String id, Instant createdAt, CredentialAccount account, String inReplyToId, String inReplyToAccountId, - Boolean sensitive, String spoilerText, String visibility, String content) { + Boolean sensitive, String spoilerText, String visibility, String content, + List mediaAttachments) { } @JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class) @@ -239,7 +247,9 @@ public class Mastodon { user.getFullName(), userService.getUserReaders(user.getUid()).size(), userService.getUserFriends(user.getUid()).size(), - webApp.getAvatarUrl(user), new AccountSource("public")); + webApp.getAvatarUrl(user), webApp.getAvatarUrl(user), + new AccountSource("public") + ); } public Status mapLastMessage(Chat chat) { @@ -252,7 +262,8 @@ public class Mastodon { false, "", "direct", - chat.getLastMessageText() + chat.getLastMessageText(), + List.of() ); } @@ -264,6 +275,11 @@ public class Mastodon { mapLastMessage(chat)); } + @JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class) + public record Image(String id, String type, String url, String previewUrl) { + + } + @GetMapping("/api/v1/conversations") public List conversations(@ModelAttribute User visitor) { return chatService.getLastChats(visitor).stream().map( @@ -272,6 +288,14 @@ public class Mastodon { } public Status toStatus(Message message) { + List attachments = StringUtils.isNotBlank(message.getAttachmentType()) + ? List.of(new Image( + message.getAttachment().getUrl(), + "image", + message.getAttachment().getUrl(), + message.getAttachment().getMedium().getUrl() + )) + : List.of(); return new Status( String.valueOf(message.getMid()), message.getCreated(), @@ -281,7 +305,8 @@ public class Mastodon { MessageUtils.isSensitive(message), "", "public", - MessageUtils.formatMessage(message.getText()) + activityPubManager.htmlLayout(message, profileUriBuilder.baseUri()), + attachments ); } @@ -301,7 +326,10 @@ public class Mastodon { mids = messagesService.getMyFeed(visitor.getUid(), before, true); } return messagesService.getMessages(visitor, mids).stream() - .map(this::toStatus) + .map(m -> { + m.getUser().setAvatar(webApp.getAvatarUrl(m.getUser())); + return toStatus(m); + }) .collect(Collectors.toList()); } } -- cgit v1.2.3