aboutsummaryrefslogtreecommitdiff
path: root/src/main/java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java')
-rw-r--r--src/main/java/com/juick/www/api/Mastodon.java68
1 files changed, 62 insertions, 6 deletions
diff --git a/src/main/java/com/juick/www/api/Mastodon.java b/src/main/java/com/juick/www/api/Mastodon.java
index c595bb19..a190defe 100644
--- a/src/main/java/com/juick/www/api/Mastodon.java
+++ b/src/main/java/com/juick/www/api/Mastodon.java
@@ -22,6 +22,7 @@ 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.CommandsManager;
import com.juick.model.Chat;
import com.juick.model.Message;
import com.juick.model.User;
@@ -31,6 +32,7 @@ import com.juick.service.TagService;
import com.juick.service.UserService;
import com.juick.util.HttpBadRequestException;
import com.juick.util.MessageUtils;
+import com.juick.util.formatters.PlainTextFormatter;
import com.juick.www.WebApp;
import com.juick.www.api.activity.helpers.ProfileUriBuilder;
import io.swagger.v3.oas.annotations.Parameter;
@@ -49,6 +51,7 @@ import org.springframework.security.oauth2.server.authorization.settings.TokenSe
import org.springframework.web.bind.annotation.*;
import javax.inject.Inject;
+import java.net.URI;
import java.time.Duration;
import java.time.Instant;
import java.util.*;
@@ -66,7 +69,7 @@ public class Mastodon {
@Inject
RegisteredClientRepository registeredClientRepository;
@Inject
- TagService tagService;
+ CommandsManager commandsManager;
@Inject
ChatService chatService;
@Inject
@@ -96,6 +99,7 @@ public class Mastodon {
@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class)
public record CredentialAccount(String id, String username, String acct,
+ String url,
String displayName,
Integer followersCount,
Integer followingCount,
@@ -228,9 +232,19 @@ 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,
- List<Image> mediaAttachments) {
+ public record Tag(String name, String url) {}
+
+ public Tag toTag(com.juick.model.Tag juickTag) {
+ return new Tag(juickTag.getName(), profileUriBuilder.tagUri(juickTag));
+ }
+
+ @JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class)
+ public record Status(String id, String url, Instant createdAt, CredentialAccount account, String inReplyToId, String inReplyToAccountId,
+ Boolean sensitive, @JsonInclude String spoilerText, String visibility, String content,
+ @JsonInclude List<Image> mediaAttachments,
+ @JsonInclude List<Void> mentions,
+ @JsonInclude List<Void> emojis,
+ @JsonInclude List<Tag> tags) {
}
@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class)
@@ -247,6 +261,7 @@ public class Mastodon {
String.valueOf(user.getUid()),
user.getName(),
user.getName(),
+ profileUriBuilder.personWebUri(user),
user.getFullName(),
userService.getUserReaders(user.getUid()).size(),
userService.getUserFriends(user.getUid()).size(),
@@ -258,6 +273,7 @@ public class Mastodon {
public Status mapLastMessage(Chat chat) {
return new Status(
String.valueOf(chat.getLastMessageTimestamp().toEpochMilli()),
+ "https://juick.com/pm/inbox",
chat.getLastMessageTimestamp(),
toAccount(chat),
null,
@@ -266,7 +282,7 @@ public class Mastodon {
"",
"direct",
chat.getLastMessageText(),
- List.of()
+ List.of(), List.of(), List.of(), List.of()
);
}
@@ -301,6 +317,7 @@ public class Mastodon {
: List.of();
return new Status(
ProfileUriBuilder.messageId(message),
+ PlainTextFormatter.formatUrl(message),
message.getCreated(),
toAccount(message.getUser()),
message.getReplyto() > 0 ? ProfileUriBuilder.messageId(message.getMid(), message.getReplyto()) : null,
@@ -309,7 +326,8 @@ public class Mastodon {
"",
"public",
activityPubManager.htmlLayout(message, profileUriBuilder.baseUri()),
- attachments
+ attachments,
+ List.of(), List.of(), message.getTags().stream().map(this::toTag).collect(Collectors.toList())
);
}
@@ -357,4 +375,42 @@ public class Mastodon {
.map(this::toStatus).toList();
return new Context(List.of(), thread);
}
+
+ private Status post(User visitor, String status, String inReplyToId) throws Exception {
+ if (StringUtils.isNotEmpty(inReplyToId)) {
+ var message = activityPubManager.findMessage(inReplyToId);
+ var command = MessageUtils.isReply(message) ?
+ String.format("#%d/%d %s", message.getMid(), message.getRid(), status)
+ : String.format("#%d %s", message.getMid(), status);
+ var result = commandsManager.processCommand(
+ visitor, command, URI.create(StringUtils.EMPTY));
+ if (result.getNewMessage().isPresent()) {
+ return toStatus(result.getNewMessage().get());
+ } else {
+ throw new HttpBadRequestException();
+ }
+ } else {
+ var result = commandsManager.processCommand(visitor, status, URI.create(StringUtils.EMPTY));
+ if (result.getNewMessage().isPresent()) {
+ return toStatus(result.getNewMessage().get());
+ } else {
+ throw new HttpBadRequestException();
+ }
+ }
+ }
+ @JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class)
+ public record NewStatus(String status, @JsonProperty("in_reply_to_id") String inReplyToId) {}
+
+ @PostMapping(value = "/api/v1/statuses", consumes = MediaType.APPLICATION_JSON_VALUE)
+ public Status postStatus(User visitor, @RequestBody NewStatus newStatus) throws Exception {
+ return post(visitor, newStatus.status(), newStatus.inReplyToId());
+ }
+ @PostMapping(value = "/api/v1/statuses", consumes = {MediaType.APPLICATION_FORM_URLENCODED_VALUE,
+ MediaType.MULTIPART_FORM_DATA_VALUE})
+ public Status postStatus(
+ User visitor,
+ @RequestParam(required = false) String status,
+ @RequestParam(name = "in_reply_to_id", required = false) String inReplyToId) throws Exception {
+ return post(visitor, status, inReplyToId);
+ }
}