diff --git a/src/main/kotlin/dev/usbharu/hideout/core/domain/model/relationship/RelationshipRepository.kt b/src/main/kotlin/dev/usbharu/hideout/core/domain/model/relationship/RelationshipRepository.kt index ac96db6b..7dca9785 100644 --- a/src/main/kotlin/dev/usbharu/hideout/core/domain/model/relationship/RelationshipRepository.kt +++ b/src/main/kotlin/dev/usbharu/hideout/core/domain/model/relationship/RelationshipRepository.kt @@ -42,4 +42,12 @@ interface RelationshipRepository { followRequest: Boolean, ignoreFollowRequest: Boolean ): List + + suspend fun findByActorIdAntMutingAndMaxIdAndSinceId( + actorId: Long, + muting: Boolean, + maxId: Long?, + sinceId: Long?, + limit: Int + ): List } diff --git a/src/main/kotlin/dev/usbharu/hideout/core/domain/model/relationship/RelationshipRepositoryImpl.kt b/src/main/kotlin/dev/usbharu/hideout/core/domain/model/relationship/RelationshipRepositoryImpl.kt index 9cea8aaa..6aa2fd70 100644 --- a/src/main/kotlin/dev/usbharu/hideout/core/domain/model/relationship/RelationshipRepositoryImpl.kt +++ b/src/main/kotlin/dev/usbharu/hideout/core/domain/model/relationship/RelationshipRepositoryImpl.kt @@ -97,6 +97,28 @@ class RelationshipRepositoryImpl : RelationshipRepository, AbstractRepository() return@query query.map { it.toRelationships() } } + override suspend fun findByActorIdAntMutingAndMaxIdAndSinceId( + actorId: Long, + muting: Boolean, + maxId: Long?, + sinceId: Long?, + limit: Int + ): List = query { + val query = Relationships.select { + Relationships.actorId.eq(actorId).and(Relationships.muting.eq(muting)) + }.limit(limit) + + if (maxId != null) { + query.andWhere { Relationships.id lessEq maxId } + } + + if (sinceId != null) { + query.andWhere { Relationships.id greaterEq sinceId } + } + + return@query query.map { it.toRelationships() } + } + companion object { private val logger = LoggerFactory.getLogger(RelationshipRepositoryImpl::class.java) } diff --git a/src/main/kotlin/dev/usbharu/hideout/mastodon/interfaces/api/account/MastodonAccountApiController.kt b/src/main/kotlin/dev/usbharu/hideout/mastodon/interfaces/api/account/MastodonAccountApiController.kt index e8e65008..d2066b68 100644 --- a/src/main/kotlin/dev/usbharu/hideout/mastodon/interfaces/api/account/MastodonAccountApiController.kt +++ b/src/main/kotlin/dev/usbharu/hideout/mastodon/interfaces/api/account/MastodonAccountApiController.kt @@ -186,4 +186,36 @@ class MastodonAccountApiController( .asFlow() ResponseEntity.ok(accountFlow) } + + override suspend fun apiV1AccountsIdMutePost(id: String): ResponseEntity { + val principal = SecurityContextHolder.getContext().getAuthentication().principal as Jwt + + val userid = principal.getClaim("uid").toLong() + + val mute = accountApiService.mute(userid, id.toLong()) + + return ResponseEntity.ok(mute) + } + + override suspend fun apiV1AccountsIdUnmutePost(id: String): ResponseEntity { + val principal = SecurityContextHolder.getContext().getAuthentication().principal as Jwt + + val userid = principal.getClaim("uid").toLong() + + val unmute = accountApiService.unmute(userid, id.toLong()) + + return ResponseEntity.ok(unmute) + } + + override fun apiV1MutesGet(maxId: String?, sinceId: String?, limit: Int?): ResponseEntity> = + runBlocking { + val principal = SecurityContextHolder.getContext().getAuthentication().principal as Jwt + + val userid = principal.getClaim("uid").toLong() + + val unmute = + accountApiService.mutesAccount(userid, maxId?.toLong(), sinceId?.toLong(), limit ?: 20).asFlow() + + return@runBlocking ResponseEntity.ok(unmute) + } } diff --git a/src/main/kotlin/dev/usbharu/hideout/mastodon/service/account/AccountApiService.kt b/src/main/kotlin/dev/usbharu/hideout/mastodon/service/account/AccountApiService.kt index 0cefb38c..a69e0474 100644 --- a/src/main/kotlin/dev/usbharu/hideout/mastodon/service/account/AccountApiService.kt +++ b/src/main/kotlin/dev/usbharu/hideout/mastodon/service/account/AccountApiService.kt @@ -60,6 +60,9 @@ interface AccountApiService { suspend fun acceptFollowRequest(loginUser: Long, target: Long): Relationship suspend fun rejectFollowRequest(loginUser: Long, target: Long): Relationship + suspend fun mute(userid: Long, target: Long): Relationship + suspend fun unmute(userid: Long, target: Long): Relationship + suspend fun mutesAccount(userid: Long, maxId: Long?, sinceId: Long?, limit: Int): List } @Service @@ -245,6 +248,25 @@ class AccountApiServiceImpl( return@transaction fetchRelationship(loginUser, target) } + override suspend fun mute(userid: Long, target: Long): Relationship = transaction.transaction { + relationshipService.mute(userid, target) + + return@transaction fetchRelationship(userid, target) + } + + override suspend fun unmute(userid: Long, target: Long): Relationship = transaction.transaction { + relationshipService.mute(userid, target) + + return@transaction fetchRelationship(userid, target) + } + + override suspend fun mutesAccount(userid: Long, maxId: Long?, sinceId: Long?, limit: Int): List { + val mutedAccounts = + relationshipRepository.findByActorIdAntMutingAndMaxIdAndSinceId(userid, true, maxId, sinceId, limit) + + return accountService.findByIds(mutedAccounts.map { it.targetActorId }) + } + private fun from(account: Account): CredentialAccount { return CredentialAccount( id = account.id, diff --git a/src/main/resources/openapi/mastodon.yaml b/src/main/resources/openapi/mastodon.yaml index 3a6ce32c..829da25c 100644 --- a/src/main/resources/openapi/mastodon.yaml +++ b/src/main/resources/openapi/mastodon.yaml @@ -464,6 +464,80 @@ paths: schema: $ref: "#/components/schemas/Relationship" + /api/v1/accounts/{id}/mute: + post: + tags: + - account + security: + - OAuth2: + - "write:mutes" + parameters: + - in: path + name: id + required: true + schema: + type: string + responses: + 200: + description: 成功 + content: + application/json: + schema: + $ref: "#/components/schemas/Relationship" + + /api/v1/accounts/{id}/unmute: + post: + tags: + - account + security: + - OAuth2: + - "write:mutes" + parameters: + - in: path + name: id + required: true + schema: + type: string + responses: + 200: + description: 成功 + content: + application/json: + schema: + $ref: "#/components/schemas/Relationship" + + /api/v1/mutes: + get: + tags: + - account + security: + - OAuth2: + - "read:mutes" + parameters: + - in: query + name: max_id + required: false + schema: + type: string + - in: query + name: since_id + required: false + schema: + type: string + - in: query + name: limit + schema: + type: integer + required: false + responses: + 200: + description: 成功 + content: + application/json: + schema: + items: + $ref: "#/components/schemas/Account" + /api/v1/accounts/{id}/statuses: get: tags: