From ced1abe69c5be166a7221dffa79d8dbbc6776c1e Mon Sep 17 00:00:00 2001 From: usbharu <64310155+usbharu@users.noreply.github.com> Date: Fri, 21 Apr 2023 18:24:13 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20API=E3=81=8B=E3=82=89=E6=8A=95=E7=A8=BF?= =?UTF-8?q?=E3=81=A7=E3=81=8D=E3=82=8B=E3=82=88=E3=81=86=E3=81=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kotlin/dev/usbharu/hideout/Application.kt | 13 ++++++---- .../dev/usbharu/hideout/domain/model/Posts.kt | 2 +- .../dev/usbharu/hideout/domain/model/User.kt | 14 ++++++++++ .../hideout/domain/model/api/Status.kt | 6 +++++ .../dev/usbharu/hideout/plugins/Routing.kt | 12 +++++++-- .../hideout/repository/PostRepositoryImpl.kt | 12 ++++----- .../hideout/routing/api/v1/Statuses.kt | 26 +++++++++++++++++++ .../hideout/service/impl/PostService.kt | 7 ++--- .../routing/activitypub/InboxRoutingKtTest.kt | 8 +++--- .../routing/activitypub/UsersAPTest.kt | 2 +- 10 files changed, 80 insertions(+), 22 deletions(-) create mode 100644 src/main/kotlin/dev/usbharu/hideout/domain/model/api/Status.kt create mode 100644 src/main/kotlin/dev/usbharu/hideout/routing/api/v1/Statuses.kt diff --git a/src/main/kotlin/dev/usbharu/hideout/Application.kt b/src/main/kotlin/dev/usbharu/hideout/Application.kt index 5b2a1acb..0f8331a1 100644 --- a/src/main/kotlin/dev/usbharu/hideout/Application.kt +++ b/src/main/kotlin/dev/usbharu/hideout/Application.kt @@ -7,13 +7,13 @@ import dev.usbharu.hideout.config.Config import dev.usbharu.hideout.config.ConfigData import dev.usbharu.hideout.domain.model.job.ReceiveFollowJob import dev.usbharu.hideout.plugins.* -import dev.usbharu.hideout.repository.IUserAuthRepository -import dev.usbharu.hideout.repository.IUserRepository -import dev.usbharu.hideout.repository.UserAuthRepository -import dev.usbharu.hideout.repository.UserRepository +import dev.usbharu.hideout.repository.* import dev.usbharu.hideout.routing.register +import dev.usbharu.hideout.service.IPostService import dev.usbharu.hideout.service.IUserAuthService +import dev.usbharu.hideout.service.TwitterSnowflakeIdGenerateService import dev.usbharu.hideout.service.activitypub.* +import dev.usbharu.hideout.service.impl.PostService import dev.usbharu.hideout.service.impl.UserAuthService import dev.usbharu.hideout.service.impl.UserService import dev.usbharu.hideout.service.job.JobQueueParentService @@ -81,6 +81,8 @@ fun Application.parent() { single { UserService(get()) } single { ActivityPubUserServiceImpl(get(), get(), get()) } single { ActivityPubNoteServiceImpl(get(), get(), get()) } + single { PostService(get(), get()) } + single { PostRepositoryImpl(get(), TwitterSnowflakeIdGenerateService) } } @@ -94,7 +96,8 @@ fun Application.parent() { inject().value, inject().value, inject().value, - inject().value + inject().value, + inject().value ) } diff --git a/src/main/kotlin/dev/usbharu/hideout/domain/model/Posts.kt b/src/main/kotlin/dev/usbharu/hideout/domain/model/Posts.kt index 4dfe0e59..3a6867db 100644 --- a/src/main/kotlin/dev/usbharu/hideout/domain/model/Posts.kt +++ b/src/main/kotlin/dev/usbharu/hideout/domain/model/Posts.kt @@ -13,6 +13,7 @@ object Posts : Table() { val url = varchar("url", 500) val repostId = long("repostId").references(id).nullable() val replyId = long("replyId").references(id).nullable() + override val primaryKey: PrimaryKey = PrimaryKey(id) } data class Post( @@ -21,7 +22,6 @@ data class Post( val text: String, val createdAt: Long, val visibility: Int, - val url: String, val repostId: Long? = null, val replyId: Long? = null ) diff --git a/src/main/kotlin/dev/usbharu/hideout/domain/model/User.kt b/src/main/kotlin/dev/usbharu/hideout/domain/model/User.kt index 28e57f99..7239465e 100644 --- a/src/main/kotlin/dev/usbharu/hideout/domain/model/User.kt +++ b/src/main/kotlin/dev/usbharu/hideout/domain/model/User.kt @@ -1,6 +1,7 @@ package dev.usbharu.hideout.domain.model import org.jetbrains.exposed.dao.id.LongIdTable +import org.jetbrains.exposed.sql.ResultRow data class User( val name: String, @@ -47,3 +48,16 @@ object Users : LongIdTable("users") { uniqueIndex(name, domain) } } + + +fun ResultRow.toUser(): User { + return User( + this[Users.name], + this[Users.domain], + this[Users.screenName], + this[Users.description], + this[Users.inbox], + this[Users.outbox], + this[Users.url] + ) +} diff --git a/src/main/kotlin/dev/usbharu/hideout/domain/model/api/Status.kt b/src/main/kotlin/dev/usbharu/hideout/domain/model/api/Status.kt new file mode 100644 index 00000000..e8e9bfe0 --- /dev/null +++ b/src/main/kotlin/dev/usbharu/hideout/domain/model/api/Status.kt @@ -0,0 +1,6 @@ +package dev.usbharu.hideout.domain.model.api + +data class StatusForPost( + val status:String, + val userId:Long +) diff --git a/src/main/kotlin/dev/usbharu/hideout/plugins/Routing.kt b/src/main/kotlin/dev/usbharu/hideout/plugins/Routing.kt index 6b44c0fd..474cff2a 100644 --- a/src/main/kotlin/dev/usbharu/hideout/plugins/Routing.kt +++ b/src/main/kotlin/dev/usbharu/hideout/plugins/Routing.kt @@ -3,7 +3,9 @@ package dev.usbharu.hideout.plugins import dev.usbharu.hideout.routing.activitypub.inbox import dev.usbharu.hideout.routing.activitypub.outbox import dev.usbharu.hideout.routing.activitypub.usersAP +import dev.usbharu.hideout.routing.api.v1.statuses import dev.usbharu.hideout.routing.wellknown.webfinger +import dev.usbharu.hideout.service.IPostService import dev.usbharu.hideout.service.activitypub.ActivityPubService import dev.usbharu.hideout.service.activitypub.ActivityPubUserService import dev.usbharu.hideout.service.impl.UserService @@ -15,8 +17,9 @@ import io.ktor.server.routing.* fun Application.configureRouting( httpSignatureVerifyService: HttpSignatureVerifyService, activityPubService: ActivityPubService, - userService:UserService, - activityPubUserService: ActivityPubUserService + userService: UserService, + activityPubUserService: ActivityPubUserService, + postService: IPostService ) { install(AutoHeadResponse) routing { @@ -24,5 +27,10 @@ fun Application.configureRouting( outbox() usersAP(activityPubUserService) webfinger(userService) + + route("api/v1") { + statuses(postService) + } + } } diff --git a/src/main/kotlin/dev/usbharu/hideout/repository/PostRepositoryImpl.kt b/src/main/kotlin/dev/usbharu/hideout/repository/PostRepositoryImpl.kt index 34ec97ae..4d30dc68 100644 --- a/src/main/kotlin/dev/usbharu/hideout/repository/PostRepositoryImpl.kt +++ b/src/main/kotlin/dev/usbharu/hideout/repository/PostRepositoryImpl.kt @@ -1,9 +1,7 @@ package dev.usbharu.hideout.repository -import dev.usbharu.hideout.domain.model.Post -import dev.usbharu.hideout.domain.model.PostEntity -import dev.usbharu.hideout.domain.model.Posts -import dev.usbharu.hideout.domain.model.toPost +import dev.usbharu.hideout.config.Config +import dev.usbharu.hideout.domain.model.* import dev.usbharu.hideout.service.IdGenerateService import kotlinx.coroutines.Dispatchers import org.jetbrains.exposed.sql.* @@ -26,6 +24,8 @@ class PostRepositoryImpl(database: Database, private val idGenerateService: IdGe return query { val generateId = idGenerateService.generateId() + val name = Users.select { Users.id eq post.userId }.single().toUser().name + val postUrl = Config.configData.url + "/users/$name/posts/$generateId" Posts.insert { it[id] = generateId it[userId] = post.userId @@ -33,7 +33,7 @@ class PostRepositoryImpl(database: Database, private val idGenerateService: IdGe it[text] = post.text it[createdAt] = post.createdAt it[visibility] = post.visibility - it[url] = post.url + it[url] = postUrl it[repostId] = post.repostId it[replyId] = post.replyId } @@ -44,7 +44,7 @@ class PostRepositoryImpl(database: Database, private val idGenerateService: IdGe post.text, post.createdAt, post.visibility, - post.url, + postUrl, post.repostId, post.replyId ) diff --git a/src/main/kotlin/dev/usbharu/hideout/routing/api/v1/Statuses.kt b/src/main/kotlin/dev/usbharu/hideout/routing/api/v1/Statuses.kt new file mode 100644 index 00000000..e5194667 --- /dev/null +++ b/src/main/kotlin/dev/usbharu/hideout/routing/api/v1/Statuses.kt @@ -0,0 +1,26 @@ +package dev.usbharu.hideout.routing.api.v1 + +import dev.usbharu.hideout.domain.model.Post +import dev.usbharu.hideout.domain.model.api.StatusForPost +import dev.usbharu.hideout.service.IPostService +import dev.usbharu.hideout.service.impl.PostService +import io.ktor.server.application.* +import io.ktor.server.request.* +import io.ktor.server.response.* +import io.ktor.server.routing.* + +fun Route.statuses(postService: IPostService) { + route("statuses") { + post { + val status: StatusForPost = call.receive() + val post = Post( + userId = status.userId, + createdAt = System.currentTimeMillis(), + text = status.status, + visibility = 1 + ) + postService.create(post) + call.respond(status) + } + } +} diff --git a/src/main/kotlin/dev/usbharu/hideout/service/impl/PostService.kt b/src/main/kotlin/dev/usbharu/hideout/service/impl/PostService.kt index f5bd2fa7..ba11153f 100644 --- a/src/main/kotlin/dev/usbharu/hideout/service/impl/PostService.kt +++ b/src/main/kotlin/dev/usbharu/hideout/service/impl/PostService.kt @@ -3,11 +3,12 @@ package dev.usbharu.hideout.service.impl import dev.usbharu.hideout.domain.model.Post import dev.usbharu.hideout.repository.IPostRepository import dev.usbharu.hideout.service.IPostService +import dev.usbharu.hideout.service.activitypub.ActivityPubNoteService import dev.usbharu.hideout.service.job.JobQueueParentService -class PostService(private val postRepository:IPostRepository,private val jobQueueParentService: JobQueueParentService) : IPostService { +class PostService(private val postRepository:IPostRepository,private val activityPubNoteService: ActivityPubNoteService) : IPostService { override suspend fun create(post: Post) { - postRepository.insert(post) - + val postEntity = postRepository.insert(post) + activityPubNoteService.createNote(postEntity) } } diff --git a/src/test/kotlin/dev/usbharu/hideout/routing/activitypub/InboxRoutingKtTest.kt b/src/test/kotlin/dev/usbharu/hideout/routing/activitypub/InboxRoutingKtTest.kt index c4de8bfb..5fa97051 100644 --- a/src/test/kotlin/dev/usbharu/hideout/routing/activitypub/InboxRoutingKtTest.kt +++ b/src/test/kotlin/dev/usbharu/hideout/routing/activitypub/InboxRoutingKtTest.kt @@ -27,7 +27,7 @@ class InboxRoutingKtTest { } application { configureSerialization() - configureRouting(mock(), mock(), mock(), mock()) + configureRouting(mock(), mock(), mock(), mock(),mock()) } client.get("/inbox").let { Assertions.assertEquals(HttpStatusCode.MethodNotAllowed, it.status) @@ -50,7 +50,7 @@ class InboxRoutingKtTest { application { configureStatusPages() configureSerialization() - configureRouting(httpSignatureVerifyService, activityPubService, userService, activityPubUserService) + configureRouting(httpSignatureVerifyService, activityPubService, userService, activityPubUserService,mock()) } client.post("/inbox").let { Assertions.assertEquals(HttpStatusCode.BadRequest, it.status) @@ -64,7 +64,7 @@ class InboxRoutingKtTest { } application { configureSerialization() - configureRouting(mock(), mock(), mock(), mock()) + configureRouting(mock(), mock(), mock(), mock(),mock()) } client.get("/users/test/inbox").let { Assertions.assertEquals(HttpStatusCode.MethodNotAllowed, it.status) @@ -87,7 +87,7 @@ class InboxRoutingKtTest { application { configureStatusPages() configureSerialization() - configureRouting(httpSignatureVerifyService, activityPubService, userService, activityPubUserService) + configureRouting(httpSignatureVerifyService, activityPubService, userService, activityPubUserService,mock()) } client.post("/users/test/inbox").let { Assertions.assertEquals(HttpStatusCode.BadRequest, it.status) diff --git a/src/test/kotlin/dev/usbharu/hideout/routing/activitypub/UsersAPTest.kt b/src/test/kotlin/dev/usbharu/hideout/routing/activitypub/UsersAPTest.kt index 6d177521..fd537617 100644 --- a/src/test/kotlin/dev/usbharu/hideout/routing/activitypub/UsersAPTest.kt +++ b/src/test/kotlin/dev/usbharu/hideout/routing/activitypub/UsersAPTest.kt @@ -70,7 +70,7 @@ class UsersAPTest { application { configureSerialization() - configureRouting(httpSignatureVerifyService, activityPubService, userService, activityPubUserService) + configureRouting(httpSignatureVerifyService, activityPubService, userService, activityPubUserService,mock()) } client.get("/users/test") { accept(ContentType.Application.Activity)