mirror of https://github.com/usbharu/Hideout.git
feat: 絵文字リアクションAPIを追加
This commit is contained in:
parent
a015566e52
commit
a5618e3307
|
@ -6,4 +6,5 @@ import dev.usbharu.hideout.core.domain.model.emoji.CustomEmoji
|
||||||
interface EmojiService {
|
interface EmojiService {
|
||||||
suspend fun fetchEmoji(url: String): Pair<Emoji, CustomEmoji>
|
suspend fun fetchEmoji(url: String): Pair<Emoji, CustomEmoji>
|
||||||
suspend fun fetchEmoji(emoji: Emoji): Pair<Emoji, CustomEmoji>
|
suspend fun fetchEmoji(emoji: Emoji): Pair<Emoji, CustomEmoji>
|
||||||
|
suspend fun findByEmojiName(emojiName: String): CustomEmoji?
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.domain.model.Emoji
|
||||||
import dev.usbharu.hideout.activitypub.service.common.APResourceResolveServiceImpl
|
import dev.usbharu.hideout.activitypub.service.common.APResourceResolveServiceImpl
|
||||||
import dev.usbharu.hideout.activitypub.service.common.resolve
|
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.CustomEmoji
|
||||||
import dev.usbharu.hideout.core.domain.model.emoji.CustomEmojiRepository
|
import dev.usbharu.hideout.core.domain.model.emoji.CustomEmojiRepository
|
||||||
import dev.usbharu.hideout.core.service.instance.InstanceService
|
import dev.usbharu.hideout.core.service.instance.InstanceService
|
||||||
|
@ -17,7 +18,8 @@ class EmojiServiceImpl(
|
||||||
private val customEmojiRepository: CustomEmojiRepository,
|
private val customEmojiRepository: CustomEmojiRepository,
|
||||||
private val instanceService: InstanceService,
|
private val instanceService: InstanceService,
|
||||||
private val mediaService: MediaService,
|
private val mediaService: MediaService,
|
||||||
private val apResourceResolveServiceImpl: APResourceResolveServiceImpl
|
private val apResourceResolveServiceImpl: APResourceResolveServiceImpl,
|
||||||
|
private val applicationConfig: ApplicationConfig
|
||||||
) : EmojiService {
|
) : EmojiService {
|
||||||
override suspend fun fetchEmoji(url: String): Pair<Emoji, CustomEmoji> {
|
override suspend fun fetchEmoji(url: String): Pair<Emoji, CustomEmoji> {
|
||||||
val emoji = apResourceResolveServiceImpl.resolve<Emoji>(url, null as Long?)
|
val emoji = apResourceResolveServiceImpl.resolve<Emoji>(url, null as Long?)
|
||||||
|
@ -60,4 +62,20 @@ class EmojiServiceImpl(
|
||||||
|
|
||||||
return customEmojiRepository.save(customEmoji1)
|
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")
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -108,6 +108,10 @@ class StatusQueryServiceImpl : StatusQueryService {
|
||||||
return resolveReplyAndRepost(pairs)
|
return resolveReplyAndRepost(pairs)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override suspend fun findByPostId(id: Long): Status {
|
||||||
|
TODO("Not yet implemented")
|
||||||
|
}
|
||||||
|
|
||||||
private fun resolveReplyAndRepost(pairs: List<Pair<Status, Long?>>): List<Status> {
|
private fun resolveReplyAndRepost(pairs: List<Pair<Status, Long?>>): List<Status> {
|
||||||
val statuses = pairs.map { it.first }
|
val statuses = pairs.map { it.first }
|
||||||
return pairs
|
return pairs
|
||||||
|
|
|
@ -24,4 +24,16 @@ class MastodonStatusesApiContoller(private val statusesApiService: StatusesApiSe
|
||||||
HttpStatus.OK
|
HttpStatus.OK
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override suspend fun apiV1StatusesIdEmojiReactionsEmojiDelete(id: String, emoji: String): ResponseEntity<Status> {
|
||||||
|
return super.apiV1StatusesIdEmojiReactionsEmojiDelete(id, emoji)
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun apiV1StatusesIdEmojiReactionsEmojiPut(id: String, emoji: String): ResponseEntity<Status> {
|
||||||
|
return super.apiV1StatusesIdEmojiReactionsEmojiPut(id, emoji)
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun apiV1StatusesIdGet(id: String): ResponseEntity<Status> {
|
||||||
|
return super.apiV1StatusesIdGet(id)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,4 +36,6 @@ interface StatusQueryService {
|
||||||
tagged: String? = null,
|
tagged: String? = null,
|
||||||
includeFollowers: Boolean = false
|
includeFollowers: Boolean = false
|
||||||
): List<Status>
|
): List<Status>
|
||||||
|
|
||||||
|
suspend fun findByPostId(id: Long): Status
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,24 @@
|
||||||
package dev.usbharu.hideout.mastodon.service.status
|
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.application.external.Transaction
|
||||||
import dev.usbharu.hideout.core.domain.model.actor.ActorRepository
|
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.MediaRepository
|
||||||
import dev.usbharu.hideout.core.domain.model.media.toMediaAttachments
|
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.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.PostCreateDto
|
||||||
import dev.usbharu.hideout.core.service.post.PostService
|
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
|
||||||
|
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.StatusesRequest
|
||||||
import dev.usbharu.hideout.mastodon.interfaces.api.status.toPostVisibility
|
import dev.usbharu.hideout.mastodon.interfaces.api.status.toPostVisibility
|
||||||
import dev.usbharu.hideout.mastodon.interfaces.api.status.toStatusVisibility
|
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.mastodon.service.account.AccountService
|
||||||
|
import dev.usbharu.hideout.util.EmojiUtil
|
||||||
import org.slf4j.LoggerFactory
|
import org.slf4j.LoggerFactory
|
||||||
import org.springframework.stereotype.Service
|
import org.springframework.stereotype.Service
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
|
@ -22,6 +29,23 @@ interface StatusesApiService {
|
||||||
statusesRequest: StatusesRequest,
|
statusesRequest: StatusesRequest,
|
||||||
userId: Long
|
userId: Long
|
||||||
): Status
|
): 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
|
@Service
|
||||||
|
@ -31,7 +55,11 @@ class StatsesApiServiceImpl(
|
||||||
private val mediaRepository: MediaRepository,
|
private val mediaRepository: MediaRepository,
|
||||||
private val transaction: Transaction,
|
private val transaction: Transaction,
|
||||||
private val actorRepository: ActorRepository,
|
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 {
|
StatusesApiService {
|
||||||
override suspend fun postStatus(
|
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 {
|
companion object {
|
||||||
private val logger = LoggerFactory.getLogger(StatusesApiService::class.java)
|
private val logger = LoggerFactory.getLogger(StatusesApiService::class.java)
|
||||||
}
|
}
|
||||||
|
|
|
@ -152,6 +152,79 @@ paths:
|
||||||
schema:
|
schema:
|
||||||
$ref: "#/components/schemas/Status"
|
$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:
|
/api/v1/apps:
|
||||||
post:
|
post:
|
||||||
tags:
|
tags:
|
||||||
|
|
Loading…
Reference in New Issue