Merge pull request #600 from usbharu/fix-mastodon-timeline-api

fix: Mastodon互換APIからフォロー等ができない問題を修正
This commit is contained in:
usbharu 2024-09-09 18:46:58 +09:00 committed by GitHub
commit ff49f371af
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 54 additions and 30 deletions

View File

@ -16,9 +16,9 @@
package dev.usbharu.hideout.mastodon.application.accounts package dev.usbharu.hideout.mastodon.application.accounts
import dev.usbharu.hideout.core.application.shared.LocalUserAbstractApplicationService import dev.usbharu.hideout.core.application.shared.AbstractApplicationService
import dev.usbharu.hideout.core.application.shared.Transaction import dev.usbharu.hideout.core.application.shared.Transaction
import dev.usbharu.hideout.core.domain.model.support.principal.LocalUser import dev.usbharu.hideout.core.domain.model.support.principal.Principal
import dev.usbharu.hideout.mastodon.interfaces.api.generated.model.Account import dev.usbharu.hideout.mastodon.interfaces.api.generated.model.Account
import dev.usbharu.hideout.mastodon.query.AccountQueryService import dev.usbharu.hideout.mastodon.query.AccountQueryService
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
@ -26,11 +26,11 @@ import org.springframework.stereotype.Service
@Service @Service
class GetAccountApplicationService(private val accountQueryService: AccountQueryService, transaction: Transaction) : class GetAccountApplicationService(private val accountQueryService: AccountQueryService, transaction: Transaction) :
LocalUserAbstractApplicationService<GetAccount, Account>( AbstractApplicationService<GetAccount, Account>(
transaction, transaction,
logger logger
) { ) {
override suspend fun internalExecute(command: GetAccount, principal: LocalUser): Account { override suspend fun internalExecute(command: GetAccount, principal: Principal): Account {
return accountQueryService.findById(command.accountId.toLong()) return accountQueryService.findById(command.accountId.toLong())
?: throw IllegalArgumentException("Account ${command.accountId} not found") ?: throw IllegalArgumentException("Account ${command.accountId} not found")
} }

View File

@ -69,7 +69,6 @@ class MastodonReadTimelineApplicationService(
lastStatusAt = it.postActor.lastPostAt?.toString(), lastStatusAt = it.postActor.lastPostAt?.toString(),
followersCount = it.postActor.followersCount?.relationshipCount, followersCount = it.postActor.followersCount?.relationshipCount,
followingCount = it.postActor.followingCount?.relationshipCount, followingCount = it.postActor.followingCount?.relationshipCount,
source = null
), ),
content = it.post.content.content, content = it.post.content.content,
visibility = when (it.post.visibility) { visibility = when (it.post.visibility) {

View File

@ -53,10 +53,10 @@ class ExposedAccountQueryServiceImpl(private val applicationConfig: ApplicationC
url = resultRow[Actors.url], url = resultRow[Actors.url],
displayName = resultRow[Actors.screenName], displayName = resultRow[Actors.screenName],
note = resultRow[Actors.description], note = resultRow[Actors.description],
avatar = userUrl + "/icon.jpg", avatar = "$userUrl/icon.jpg",
avatarStatic = userUrl + "/icon.jpg", avatarStatic = "$userUrl/icon.jpg",
header = userUrl + "/header.jpg", header = "$userUrl/header.jpg",
headerStatic = userUrl + "/header.jpg", headerStatic = "$userUrl/header.jpg",
locked = resultRow[Actors.locked], locked = resultRow[Actors.locked],
fields = emptyList(), fields = emptyList(),
emojis = emptyList(), emojis = emptyList(),
@ -68,6 +68,10 @@ class ExposedAccountQueryServiceImpl(private val applicationConfig: ApplicationC
statusesCount = resultRow[Actors.postsCount], statusesCount = resultRow[Actors.postsCount],
followersCount = resultRow[Actors.followersCount], followersCount = resultRow[Actors.followersCount],
followingCount = resultRow[Actors.followingCount], followingCount = resultRow[Actors.followingCount],
noindex = false,
moved = false,
suspended = resultRow[Actors.suspend],
limited = false,
) )
} }
} }

View File

@ -39,11 +39,16 @@ import dev.usbharu.hideout.core.application.relationship.unfollow.Unfollow
import dev.usbharu.hideout.core.application.relationship.unfollow.UserUnfollowApplicationService import dev.usbharu.hideout.core.application.relationship.unfollow.UserUnfollowApplicationService
import dev.usbharu.hideout.core.application.relationship.unmute.Unmute import dev.usbharu.hideout.core.application.relationship.unmute.Unmute
import dev.usbharu.hideout.core.application.relationship.unmute.UserUnmuteApplicationService import dev.usbharu.hideout.core.application.relationship.unmute.UserUnmuteApplicationService
import dev.usbharu.hideout.core.domain.model.support.principal.Principal
import dev.usbharu.hideout.core.infrastructure.springframework.oauth2.SpringSecurityOauth2PrincipalContextHolder import dev.usbharu.hideout.core.infrastructure.springframework.oauth2.SpringSecurityOauth2PrincipalContextHolder
import dev.usbharu.hideout.mastodon.application.accounts.GetAccount import dev.usbharu.hideout.mastodon.application.accounts.GetAccount
import dev.usbharu.hideout.mastodon.application.accounts.GetAccountApplicationService import dev.usbharu.hideout.mastodon.application.accounts.GetAccountApplicationService
import dev.usbharu.hideout.mastodon.interfaces.api.generated.AccountApi import dev.usbharu.hideout.mastodon.interfaces.api.generated.AccountApi
import dev.usbharu.hideout.mastodon.interfaces.api.generated.model.* import dev.usbharu.hideout.mastodon.interfaces.api.generated.model.*
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.asFlow
import kotlinx.coroutines.flow.mapNotNull
import kotlinx.coroutines.runBlocking
import org.springframework.http.ResponseEntity import org.springframework.http.ResponseEntity
import org.springframework.stereotype.Controller import org.springframework.stereotype.Controller
@ -66,27 +71,30 @@ class SpringAccountApi(
) : AccountApi { ) : AccountApi {
override suspend fun apiV1AccountsIdBlockPost(id: String): ResponseEntity<Relationship> { override suspend fun apiV1AccountsIdBlockPost(id: String): ResponseEntity<Relationship> {
userBlockApplicationService.execute(Block(id.toLong()), principalContextHolder.getPrincipal()) val principal = principalContextHolder.getPrincipal()
return fetchRelationship(id) userBlockApplicationService.execute(Block(id.toLong()), principal)
return fetchRelationship(id, principal)
} }
override suspend fun apiV1AccountsIdFollowPost( override suspend fun apiV1AccountsIdFollowPost(
id: String, id: String,
followRequestBody: FollowRequestBody?, followRequestBody: FollowRequestBody?,
): ResponseEntity<Relationship> { ): ResponseEntity<Relationship> {
val principal = principalContextHolder.getPrincipal()
userFollowRequestApplicationService.execute( userFollowRequestApplicationService.execute(
FollowRequest(id.toLong()), FollowRequest(id.toLong()),
principalContextHolder.getPrincipal() principal
) )
return fetchRelationship(id) return fetchRelationship(id, principal)
} }
private suspend fun fetchRelationship( private suspend fun fetchRelationship(
id: String, id: String,
principal: Principal
): ResponseEntity<Relationship> { ): ResponseEntity<Relationship> {
val relationship = getRelationshipApplicationService.execute( val relationship = getRelationshipApplicationService.execute(
GetRelationship(id.toLong()), GetRelationship(id.toLong()),
principalContextHolder.getPrincipal() principal
) )
return ResponseEntity.ok( return ResponseEntity.ok(
Relationship( Relationship(
@ -117,43 +125,56 @@ class SpringAccountApi(
} }
override suspend fun apiV1AccountsIdMutePost(id: String): ResponseEntity<Relationship> { override suspend fun apiV1AccountsIdMutePost(id: String): ResponseEntity<Relationship> {
val principal = principalContextHolder.getPrincipal()
userMuteApplicationService.execute( userMuteApplicationService.execute(
Mute(id.toLong()), Mute(id.toLong()),
principalContextHolder.getPrincipal() principal
) )
return fetchRelationship(id) return fetchRelationship(id, principal)
} }
override suspend fun apiV1AccountsIdRemoveFromFollowersPost(id: String): ResponseEntity<Relationship> { override suspend fun apiV1AccountsIdRemoveFromFollowersPost(id: String): ResponseEntity<Relationship> {
val principal = principalContextHolder.getPrincipal()
userRemoveFromFollowersApplicationService.execute( userRemoveFromFollowersApplicationService.execute(
RemoveFromFollowers(id.toLong()), RemoveFromFollowers(id.toLong()),
principalContextHolder.getPrincipal() principal
) )
return fetchRelationship(id) return fetchRelationship(id, principal)
} }
override suspend fun apiV1AccountsIdUnblockPost(id: String): ResponseEntity<Relationship> { override suspend fun apiV1AccountsIdUnblockPost(id: String): ResponseEntity<Relationship> {
val principal = principalContextHolder.getPrincipal()
userUnblockApplicationService.execute( userUnblockApplicationService.execute(
Unblock(id.toLong()), Unblock(id.toLong()),
principalContextHolder.getPrincipal() principal
) )
return fetchRelationship(id) return fetchRelationship(id, principal)
} }
override suspend fun apiV1AccountsIdUnfollowPost(id: String): ResponseEntity<Relationship> { override suspend fun apiV1AccountsIdUnfollowPost(id: String): ResponseEntity<Relationship> {
val principal = principalContextHolder.getPrincipal()
userUnfollowApplicationService.execute( userUnfollowApplicationService.execute(
Unfollow(id.toLong()), Unfollow(id.toLong()),
principalContextHolder.getPrincipal() principal
) )
return fetchRelationship(id) return fetchRelationship(id, principal)
}
override fun apiV1AccountsRelationshipsGet(
id: List<String>?,
withSuspended: Boolean
): ResponseEntity<Flow<Relationship>> {
val principal = runBlocking { principalContextHolder.getPrincipal() }
return ResponseEntity.ok(id.orEmpty().asFlow().mapNotNull { fetchRelationship(it, principal).body })
} }
override suspend fun apiV1AccountsIdUnmutePost(id: String): ResponseEntity<Relationship> { override suspend fun apiV1AccountsIdUnmutePost(id: String): ResponseEntity<Relationship> {
val principal = principalContextHolder.getPrincipal()
userUnmuteApplicationService.execute( userUnmuteApplicationService.execute(
Unmute(id.toLong()), Unmute(id.toLong()),
principalContextHolder.getPrincipal() principal
) )
return fetchRelationship(id) return fetchRelationship(id, principal)
} }
override suspend fun apiV1AccountsPost(accountsCreateRequest: AccountsCreateRequest): ResponseEntity<Unit> = override suspend fun apiV1AccountsPost(accountsCreateRequest: AccountsCreateRequest): ResponseEntity<Unit> =
@ -220,18 +241,20 @@ class SpringAccountApi(
} }
override suspend fun apiV1FollowRequestsAccountIdAuthorizePost(accountId: String): ResponseEntity<Relationship> { override suspend fun apiV1FollowRequestsAccountIdAuthorizePost(accountId: String): ResponseEntity<Relationship> {
val principal = principalContextHolder.getPrincipal()
userAcceptFollowRequestApplicationService.execute( userAcceptFollowRequestApplicationService.execute(
AcceptFollowRequest(accountId.toLong()), AcceptFollowRequest(accountId.toLong()),
principalContextHolder.getPrincipal() principal
) )
return fetchRelationship(accountId) return fetchRelationship(accountId, principal)
} }
override suspend fun apiV1FollowRequestsAccountIdRejectPost(accountId: String): ResponseEntity<Relationship> { override suspend fun apiV1FollowRequestsAccountIdRejectPost(accountId: String): ResponseEntity<Relationship> {
val principal = principalContextHolder.getPrincipal()
userRejectFollowRequestApplicationService.execute( userRejectFollowRequestApplicationService.execute(
RejectFollowRequest(accountId.toLong()), RejectFollowRequest(accountId.toLong()),
principalContextHolder.getPrincipal() principal
) )
return fetchRelationship(accountId) return fetchRelationship(accountId, principal)
} }
} }

View File

@ -1597,8 +1597,6 @@ components:
type: integer type: integer
following_count: following_count:
type: integer type: integer
source:
$ref: "#/components/schemas/AccountSource"
required: required:
- id - id