From 2f2a6255d52d1db7288d4f4af8e494d86a3800d4 Mon Sep 17 00:00:00 2001 From: usbharu <64310155+usbharu@users.noreply.github.com> Date: Sun, 7 Jan 2024 12:56:32 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20=E7=B5=B5=E6=96=87=E5=AD=97=E3=83=AA?= =?UTF-8?q?=E3=82=A2=E3=82=AF=E3=82=B7=E3=83=A7=E3=83=B3API=E3=82=92?= =?UTF-8?q?=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/objects/emoji/EmojiService.kt | 1 + .../service/objects/emoji/EmojiServiceImpl.kt | 20 ++++- .../exposedquery/StatusQueryServiceImpl.kt | 4 + .../status/MastodonStatusesApiContoller.kt | 12 +++ .../mastodon/query/StatusQueryService.kt | 2 + .../service/status/StatusesApiService.kt | 87 ++++++++++++++++++- src/main/resources/openapi/mastodon.yaml | 73 ++++++++++++++++ 7 files changed, 197 insertions(+), 2 deletions(-) diff --git a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/objects/emoji/EmojiService.kt b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/objects/emoji/EmojiService.kt index 4dd6e2d1..430908b1 100644 --- a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/objects/emoji/EmojiService.kt +++ b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/objects/emoji/EmojiService.kt @@ -6,4 +6,5 @@ import dev.usbharu.hideout.core.domain.model.emoji.CustomEmoji interface EmojiService { suspend fun fetchEmoji(url: String): Pair suspend fun fetchEmoji(emoji: Emoji): Pair + suspend fun findByEmojiName(emojiName: String): CustomEmoji? } diff --git a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/objects/emoji/EmojiServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/objects/emoji/EmojiServiceImpl.kt index 3c990b59..90a2e1a7 100644 --- a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/objects/emoji/EmojiServiceImpl.kt +++ b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/objects/emoji/EmojiServiceImpl.kt @@ -3,6 +3,7 @@ package dev.usbharu.hideout.activitypub.service.objects.emoji import dev.usbharu.hideout.activitypub.domain.model.Emoji import dev.usbharu.hideout.activitypub.service.common.APResourceResolveServiceImpl import dev.usbharu.hideout.activitypub.service.common.resolve +import dev.usbharu.hideout.application.config.ApplicationConfig import dev.usbharu.hideout.core.domain.model.emoji.CustomEmoji import dev.usbharu.hideout.core.domain.model.emoji.CustomEmojiRepository import dev.usbharu.hideout.core.service.instance.InstanceService @@ -17,7 +18,8 @@ class EmojiServiceImpl( private val customEmojiRepository: CustomEmojiRepository, private val instanceService: InstanceService, private val mediaService: MediaService, - private val apResourceResolveServiceImpl: APResourceResolveServiceImpl + private val apResourceResolveServiceImpl: APResourceResolveServiceImpl, + private val applicationConfig: ApplicationConfig ) : EmojiService { override suspend fun fetchEmoji(url: String): Pair { val emoji = apResourceResolveServiceImpl.resolve(url, null as Long?) @@ -60,4 +62,20 @@ class EmojiServiceImpl( return customEmojiRepository.save(customEmoji1) } + + override suspend fun findByEmojiName(emojiName: String): CustomEmoji? { + val split = emojiName.trim(':').split("@") + + return when (split.size) { + 1 -> { + customEmojiRepository.findByNameAndDomain(split.first(), applicationConfig.url.host) + } + + 2 -> { + customEmojiRepository.findByNameAndDomain(split.first(), split[1]) + } + + else -> throw IllegalArgumentException("Unknown Emoji Format. $emojiName") + } + } } diff --git a/src/main/kotlin/dev/usbharu/hideout/mastodon/infrastructure/exposedquery/StatusQueryServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/mastodon/infrastructure/exposedquery/StatusQueryServiceImpl.kt index 937f2d9b..40e92ee8 100644 --- a/src/main/kotlin/dev/usbharu/hideout/mastodon/infrastructure/exposedquery/StatusQueryServiceImpl.kt +++ b/src/main/kotlin/dev/usbharu/hideout/mastodon/infrastructure/exposedquery/StatusQueryServiceImpl.kt @@ -108,6 +108,10 @@ class StatusQueryServiceImpl : StatusQueryService { return resolveReplyAndRepost(pairs) } + override suspend fun findByPostId(id: Long): Status { + TODO("Not yet implemented") + } + private fun resolveReplyAndRepost(pairs: List>): List { val statuses = pairs.map { it.first } return pairs diff --git a/src/main/kotlin/dev/usbharu/hideout/mastodon/interfaces/api/status/MastodonStatusesApiContoller.kt b/src/main/kotlin/dev/usbharu/hideout/mastodon/interfaces/api/status/MastodonStatusesApiContoller.kt index 2b2e65eb..705f94f7 100644 --- a/src/main/kotlin/dev/usbharu/hideout/mastodon/interfaces/api/status/MastodonStatusesApiContoller.kt +++ b/src/main/kotlin/dev/usbharu/hideout/mastodon/interfaces/api/status/MastodonStatusesApiContoller.kt @@ -24,4 +24,16 @@ class MastodonStatusesApiContoller(private val statusesApiService: StatusesApiSe HttpStatus.OK ) } + + override suspend fun apiV1StatusesIdEmojiReactionsEmojiDelete(id: String, emoji: String): ResponseEntity { + return super.apiV1StatusesIdEmojiReactionsEmojiDelete(id, emoji) + } + + override suspend fun apiV1StatusesIdEmojiReactionsEmojiPut(id: String, emoji: String): ResponseEntity { + return super.apiV1StatusesIdEmojiReactionsEmojiPut(id, emoji) + } + + override suspend fun apiV1StatusesIdGet(id: String): ResponseEntity { + return super.apiV1StatusesIdGet(id) + } } diff --git a/src/main/kotlin/dev/usbharu/hideout/mastodon/query/StatusQueryService.kt b/src/main/kotlin/dev/usbharu/hideout/mastodon/query/StatusQueryService.kt index 2b4e2a31..fe78a70d 100644 --- a/src/main/kotlin/dev/usbharu/hideout/mastodon/query/StatusQueryService.kt +++ b/src/main/kotlin/dev/usbharu/hideout/mastodon/query/StatusQueryService.kt @@ -36,4 +36,6 @@ interface StatusQueryService { tagged: String? = null, includeFollowers: Boolean = false ): List + + suspend fun findByPostId(id: Long): Status } diff --git a/src/main/kotlin/dev/usbharu/hideout/mastodon/service/status/StatusesApiService.kt b/src/main/kotlin/dev/usbharu/hideout/mastodon/service/status/StatusesApiService.kt index 1a095d82..de96e340 100644 --- a/src/main/kotlin/dev/usbharu/hideout/mastodon/service/status/StatusesApiService.kt +++ b/src/main/kotlin/dev/usbharu/hideout/mastodon/service/status/StatusesApiService.kt @@ -1,17 +1,24 @@ package dev.usbharu.hideout.mastodon.service.status +import dev.usbharu.hideout.activitypub.service.objects.emoji.EmojiService import dev.usbharu.hideout.application.external.Transaction import dev.usbharu.hideout.core.domain.model.actor.ActorRepository +import dev.usbharu.hideout.core.domain.model.emoji.UnicodeEmoji import dev.usbharu.hideout.core.domain.model.media.MediaRepository import dev.usbharu.hideout.core.domain.model.media.toMediaAttachments import dev.usbharu.hideout.core.domain.model.post.PostRepository +import dev.usbharu.hideout.core.domain.model.relationship.RelationshipRepository import dev.usbharu.hideout.core.service.post.PostCreateDto import dev.usbharu.hideout.core.service.post.PostService +import dev.usbharu.hideout.core.service.reaction.ReactionService import dev.usbharu.hideout.domain.mastodon.model.generated.Status +import dev.usbharu.hideout.domain.mastodon.model.generated.Status.Visibility.* import dev.usbharu.hideout.mastodon.interfaces.api.status.StatusesRequest import dev.usbharu.hideout.mastodon.interfaces.api.status.toPostVisibility import dev.usbharu.hideout.mastodon.interfaces.api.status.toStatusVisibility +import dev.usbharu.hideout.mastodon.query.StatusQueryService import dev.usbharu.hideout.mastodon.service.account.AccountService +import dev.usbharu.hideout.util.EmojiUtil import org.slf4j.LoggerFactory import org.springframework.stereotype.Service import java.time.Instant @@ -22,6 +29,23 @@ interface StatusesApiService { statusesRequest: StatusesRequest, userId: Long ): Status + + suspend fun findById( + id: Long, + userId: Long? + ): Status? + + suspend fun emojiReactions( + postId: Long, + userId: Long, + emojiName: String + ): Status? + + suspend fun removeEmojiReactions( + postId: Long, + userId: Long, + emojiName: String + ): Status? } @Service @@ -31,7 +55,11 @@ class StatsesApiServiceImpl( private val mediaRepository: MediaRepository, private val transaction: Transaction, private val actorRepository: ActorRepository, - private val postRepository: PostRepository + private val postRepository: PostRepository, + private val statusQueryService: StatusQueryService, + private val relationshipRepository: RelationshipRepository, + private val reactionService: ReactionService, + private val emojiService: EmojiService ) : StatusesApiService { override suspend fun postStatus( @@ -95,6 +123,63 @@ class StatsesApiServiceImpl( ) } + override suspend fun findById(id: Long, userId: Long?): Status? { + val status = statusQueryService.findByPostId(id) + + return status(status, userId) + } + + private suspend fun status( + status: Status, + userId: Long? + ): Status? { + return when (status.visibility) { + public -> status + unlisted -> status + private -> { + if (userId == null) { + return null + } + + val relationship = + relationshipRepository.findByUserIdAndTargetUserId(userId, status.account.id.toLong()) + ?: return null + if (relationship.following) { + return status + } + return null + } + + direct -> null + } + } + + override suspend fun emojiReactions(postId: Long, userId: Long, emojiName: String): Status? { + + status(statusQueryService.findByPostId(postId), userId) ?: return null + + val emoji = try { + if (EmojiUtil.isEmoji(emojiName)) { + UnicodeEmoji(emojiName) + } else { + emojiService.findByEmojiName(emojiName)!! + } + } catch (e: IllegalStateException) { + UnicodeEmoji("❤") + } catch (e: NullPointerException) { + UnicodeEmoji("❤") + } + reactionService.sendReaction(emoji, userId, postId) + return statusQueryService.findByPostId(postId) + } + + override suspend fun removeEmojiReactions(postId: Long, userId: Long, emojiName: String): Status? { + + reactionService.removeReaction(userId, postId) + + return status(statusQueryService.findByPostId(postId), userId) + } + companion object { private val logger = LoggerFactory.getLogger(StatusesApiService::class.java) } diff --git a/src/main/resources/openapi/mastodon.yaml b/src/main/resources/openapi/mastodon.yaml index 15df90d9..3a6ce32c 100644 --- a/src/main/resources/openapi/mastodon.yaml +++ b/src/main/resources/openapi/mastodon.yaml @@ -152,6 +152,79 @@ paths: schema: $ref: "#/components/schemas/Status" + /api/v1/statuses/{id}: + get: + tags: + - status + security: + - OAuth2: + - "write:statuses" + parameters: + - in: path + name: id + required: true + schema: + type: string + responses: + 200: + description: 成功 + content: + application/json: + schema: + $ref: "#/components/schemas/Status" + + /api/v1/statuses/{id}/emoji_reactions/{emoji}: + put: + tags: + - status + security: + - OAuth2: + - "write:statuses" + parameters: + - in: path + name: id + required: true + schema: + type: string + - in: path + name: emoji + required: true + schema: + type: string + responses: + 200: + description: 成功 + content: + application/json: + schema: + $ref: "#/components/schemas/Status" + + delete: + tags: + - status + security: + - OAuth2: + - "write:statuses" + parameters: + - in: path + name: id + required: true + schema: + type: string + - in: path + name: emoji + required: true + schema: + type: string + responses: + 200: + description: 成功 + content: + application/json: + schema: + $ref: "#/components/schemas/Status" + + /api/v1/apps: post: tags: