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 46a03fbe..f3c05765 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 @@ -3,7 +3,10 @@ package dev.usbharu.hideout.mastodon.interfaces.api.account import dev.usbharu.hideout.application.external.Transaction import dev.usbharu.hideout.controller.mastodon.generated.AccountApi import dev.usbharu.hideout.core.service.user.UserCreateDto +import dev.usbharu.hideout.domain.mastodon.model.generated.Account import dev.usbharu.hideout.domain.mastodon.model.generated.CredentialAccount +import dev.usbharu.hideout.domain.mastodon.model.generated.FollowRequestBody +import dev.usbharu.hideout.domain.mastodon.model.generated.Relationship import dev.usbharu.hideout.mastodon.service.account.AccountApiService import org.springframework.http.HttpHeaders import org.springframework.http.HttpStatus @@ -18,6 +21,19 @@ class MastodonAccountApiController( private val accountApiService: AccountApiService, private val transaction: Transaction ) : AccountApi { + + override suspend fun apiV1AccountsIdFollowPost( + id: String, + followRequestBody: FollowRequestBody? + ): ResponseEntity { + val principal = SecurityContextHolder.getContext().getAuthentication().principal as Jwt + + return ResponseEntity.ok(accountApiService.follow(principal.getClaim("uid").toLong(), id.toLong())) + } + + override suspend fun apiV1AccountsIdGet(id: String): ResponseEntity = + ResponseEntity.ok(accountApiService.account(id.toLong())) + override suspend fun apiV1AccountsVerifyCredentialsGet(): ResponseEntity { val principal = SecurityContextHolder.getContext().getAuthentication().principal as Jwt 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 9fc44262..b2e2792a 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 @@ -1,25 +1,28 @@ package dev.usbharu.hideout.mastodon.service.account import dev.usbharu.hideout.application.external.Transaction +import dev.usbharu.hideout.core.domain.model.user.UserRepository +import dev.usbharu.hideout.core.query.FollowerQueryService import dev.usbharu.hideout.core.service.user.UserCreateDto import dev.usbharu.hideout.core.service.user.UserService -import dev.usbharu.hideout.domain.mastodon.model.generated.Account -import dev.usbharu.hideout.domain.mastodon.model.generated.CredentialAccount -import dev.usbharu.hideout.domain.mastodon.model.generated.CredentialAccountSource -import dev.usbharu.hideout.domain.mastodon.model.generated.Role +import dev.usbharu.hideout.domain.mastodon.model.generated.* import org.springframework.stereotype.Service @Service interface AccountApiService { suspend fun verifyCredentials(userid: Long): CredentialAccount suspend fun registerAccount(userCreateDto: UserCreateDto): Unit + suspend fun follow(userid: Long, followeeId: Long): Relationship + suspend fun account(id: Long): Account } @Service class AccountApiServiceImpl( private val accountService: AccountService, private val transaction: Transaction, - private val userService: UserService + private val userService: UserService, + private val followerQueryService: FollowerQueryService, + private val userRepository: UserRepository ) : AccountApiService { override suspend fun verifyCredentials(userid: Long): CredentialAccount = transaction.transaction { @@ -31,6 +34,42 @@ class AccountApiServiceImpl( userService.createLocalUser(UserCreateDto(userCreateDto.name, userCreateDto.name, "", userCreateDto.password)) } + override suspend fun follow(userid: Long, followeeId: Long): Relationship = transaction.transaction { + + val alreadyFollow = followerQueryService.alreadyFollow(followeeId, userid) + + + val followRequest = if (alreadyFollow) { + true + } else { + userService.followRequest(followeeId, userid) + } + + val alreadyFollow1 = followerQueryService.alreadyFollow(userid, followeeId) + + val followRequestsById = userRepository.findFollowRequestsById(followeeId, userid) + + return@transaction Relationship( + followeeId.toString(), + followRequest, + true, + false, + alreadyFollow1, + false, + false, + false, + false, + followRequestsById, + false, + false, + "" + ) + } + + override suspend fun account(id: Long): Account = transaction.transaction { + return@transaction accountService.findById(id) + } + 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 6f93fa36..03fa7a69 100644 --- a/src/main/resources/openapi/mastodon.yaml +++ b/src/main/resources/openapi/mastodon.yaml @@ -206,6 +206,55 @@ paths: 200: description: 成功 + /api/v1/accounts/{id}: + get: + tags: + - account + security: + - { } + parameters: + - in: path + name: id + required: true + schema: + type: string + responses: + 200: + description: 成功 + content: + application/json: + schema: + $ref: "#/components/schemas/Account" + + /api/v1/accounts/{id}/follow: + post: + tags: + - account + security: + - OAuth2: + - "write:follows" + parameters: + - in: path + name: id + required: true + schema: + type: string + requestBody: + required: false + content: + application/json: + schema: + $ref: "#/components/schemas/FollowRequestBody" + application/x-www-form-urlencoded: + schema: + $ref: "#/components/schemas/FollowRequestBody" + responses: + 200: + description: 成功 + content: + application/json: + schema: + $ref: "#/components/schemas/Relationship" /api/v1/timelines/public: get: tags: @@ -1314,6 +1363,8 @@ components: type: string client_secret: type: string + redirect_uri: + type: string required: - name - vapid_key @@ -1333,6 +1384,65 @@ components: - client_name - redirect_uris + Relationship: + type: object + properties: + id: + type: string + following: + type: boolean + showing_reblogs: + type: boolean + notifying: + type: boolean + followed_by: + type: boolean + blocking: + type: boolean + blocked_by: + type: boolean + muting: + type: boolean + muting_notifications: + type: boolean + requested: + type: boolean + domain_blocking: + type: boolean + endorsed: + type: boolean + note: + type: string + required: + - id + - following + - showing_reblogs + - notifying + - followed_by + - blocking + - blocked_by + - muting + - muting_notifications + - requested + - domain_blocking + - endorsed + - note + + + FollowRequestBody: + type: object + properties: + reblogs: + type: boolean + default: true + notify: + type: boolean + default: false + languages: + type: array + items: + type: string + securitySchemes: OAuth2: type: oauth2