diff --git a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/create/ApSendCreateServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/create/ApSendCreateServiceImpl.kt index 75f2fa7f..0d3eeac8 100644 --- a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/create/ApSendCreateServiceImpl.kt +++ b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/create/ApSendCreateServiceImpl.kt @@ -1,10 +1,12 @@ package dev.usbharu.hideout.activitypub.service.activity.create import com.fasterxml.jackson.databind.ObjectMapper +import dev.usbharu.hideout.activitypub.domain.model.Create +import dev.usbharu.hideout.activitypub.query.NoteQueryService +import dev.usbharu.hideout.application.config.ApplicationConfig import dev.usbharu.hideout.core.domain.model.post.Post import dev.usbharu.hideout.core.external.job.DeliverPostJob import dev.usbharu.hideout.core.query.FollowerQueryService -import dev.usbharu.hideout.core.query.MediaQueryService import dev.usbharu.hideout.core.query.UserQueryService import dev.usbharu.hideout.core.service.job.JobQueueParentService import org.slf4j.LoggerFactory @@ -15,8 +17,9 @@ class ApSendCreateServiceImpl( private val followerQueryService: FollowerQueryService, private val objectMapper: ObjectMapper, private val jobQueueParentService: JobQueueParentService, - private val mediaQueryService: MediaQueryService, - private val userQueryService: UserQueryService + private val userQueryService: UserQueryService, + private val noteQueryService: NoteQueryService, + private val applicationConfig: ApplicationConfig ) : ApSendCreateService { override suspend fun createNote(post: Post) { logger.info("CREATE Create Local Note ${post.url}") @@ -27,14 +30,18 @@ class ApSendCreateServiceImpl( logger.debug("DELIVER Deliver Note Create ${followers.size} accounts.") val userEntity = userQueryService.findById(post.userId) - val note = objectMapper.writeValueAsString(post) - val mediaList = objectMapper.writeValueAsString(mediaQueryService.findByPostId(post.id)) + val note = noteQueryService.findById(post.id).first + val create = Create( + name = "Create Note", + `object` = note, + actor = note.attributedTo, + id = "${applicationConfig.url}/create/note/${post.id}" + ) followers.forEach { followerEntity -> jobQueueParentService.schedule(DeliverPostJob) { props[DeliverPostJob.actor] = userEntity.url - props[DeliverPostJob.post] = note props[DeliverPostJob.inbox] = followerEntity.inbox - props[DeliverPostJob.media] = mediaList + props[DeliverPostJob.create] = objectMapper.writeValueAsString(create) } } diff --git a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/objects/note/APNoteService.kt b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/objects/note/APNoteService.kt index 8afafae9..c3c7591c 100644 --- a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/objects/note/APNoteService.kt +++ b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/objects/note/APNoteService.kt @@ -12,12 +12,7 @@ import dev.usbharu.hideout.core.domain.exception.FailedToGetResourcesException import dev.usbharu.hideout.core.domain.model.post.Post import dev.usbharu.hideout.core.domain.model.post.PostRepository import dev.usbharu.hideout.core.domain.model.post.Visibility -import dev.usbharu.hideout.core.external.job.DeliverPostJob -import dev.usbharu.hideout.core.query.FollowerQueryService -import dev.usbharu.hideout.core.query.MediaQueryService import dev.usbharu.hideout.core.query.PostQueryService -import dev.usbharu.hideout.core.query.UserQueryService -import dev.usbharu.hideout.core.service.job.JobQueueParentService import dev.usbharu.hideout.core.service.post.PostService import io.ktor.client.plugins.* import kotlinx.coroutines.CoroutineScope @@ -50,13 +45,9 @@ interface APNoteService { @Service @Suppress("LongParameterList") class APNoteServiceImpl( - private val jobQueueParentService: JobQueueParentService, private val postRepository: PostRepository, private val apUserService: APUserService, - private val userQueryService: UserQueryService, - private val followerQueryService: FollowerQueryService, private val postQueryService: PostQueryService, - private val mediaQueryService: MediaQueryService, @Qualifier("activitypub") private val objectMapper: ObjectMapper, private val postService: PostService, private val apResourceResolveService: APResourceResolveService, @@ -68,29 +59,6 @@ class APNoteServiceImpl( private val logger = LoggerFactory.getLogger(APNoteServiceImpl::class.java) - suspend fun createNote(post: Post) { - logger.info("CREATE Create Local Note ${post.url}") - logger.debug("START Create Local Note ${post.url}") - logger.trace("{}", post) - val followers = followerQueryService.findFollowersById(post.userId) - - logger.debug("DELIVER Deliver Note Create ${followers.size} accounts.") - - val userEntity = userQueryService.findById(post.userId) - val note = objectMapper.writeValueAsString(post) - val mediaList = objectMapper.writeValueAsString(mediaQueryService.findByPostId(post.id)) - followers.forEach { followerEntity -> - jobQueueParentService.schedule(DeliverPostJob) { - props[DeliverPostJob.actor] = userEntity.url - props[DeliverPostJob.post] = note - props[DeliverPostJob.inbox] = followerEntity.inbox - props[DeliverPostJob.media] = mediaList - } - } - - logger.debug("SUCCESS Create Local Note ${post.url}") - } - override suspend fun fetchNote(url: String, targetActor: String?): Note { logger.debug("START Fetch Note url: {}", url) try { diff --git a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/objects/note/ApNoteJobServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/objects/note/ApNoteJobServiceImpl.kt index 83daa89d..14f773b0 100644 --- a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/objects/note/ApNoteJobServiceImpl.kt +++ b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/objects/note/ApNoteJobServiceImpl.kt @@ -3,59 +3,34 @@ package dev.usbharu.hideout.activitypub.service.objects.note import com.fasterxml.jackson.databind.ObjectMapper import com.fasterxml.jackson.module.kotlin.readValue import dev.usbharu.hideout.activitypub.domain.model.Create -import dev.usbharu.hideout.activitypub.domain.model.Document -import dev.usbharu.hideout.activitypub.domain.model.Note import dev.usbharu.hideout.activitypub.service.common.APRequestService -import dev.usbharu.hideout.application.config.ApplicationConfig import dev.usbharu.hideout.application.external.Transaction -import dev.usbharu.hideout.core.domain.model.media.Media -import dev.usbharu.hideout.core.domain.model.post.Post import dev.usbharu.hideout.core.external.job.DeliverPostJob import dev.usbharu.hideout.core.query.UserQueryService import kjob.core.job.JobProps import org.slf4j.LoggerFactory import org.springframework.beans.factory.annotation.Qualifier import org.springframework.stereotype.Component -import java.time.Instant @Component class ApNoteJobServiceImpl( private val userQueryService: UserQueryService, private val apRequestService: APRequestService, @Qualifier("activitypub") private val objectMapper: ObjectMapper, - private val transaction: Transaction, - private val applicationConfig: ApplicationConfig + private val transaction: Transaction ) : ApNoteJobService { override suspend fun createNoteJob(props: JobProps) { - val actor = props[DeliverPostJob.actor] - val postEntity = objectMapper.readValue(props[DeliverPostJob.post]) - val mediaList = - objectMapper.readValue>( - props[DeliverPostJob.media] - ) + val actor = props[DeliverPostJob.actor] + val create = objectMapper.readValue(props[DeliverPostJob.create]) transaction.transaction { val signer = userQueryService.findByUrl(actor) - val note = Note( - name = "Note", - id = postEntity.url, - attributedTo = actor, - content = postEntity.text, - published = Instant.ofEpochMilli(postEntity.createdAt).toString(), - to = listOfNotNull(APNoteServiceImpl.public, signer.followers), - attachment = mediaList.map { Document(mediaType = "image/jpeg", url = it.url) } - ) val inbox = props[DeliverPostJob.inbox] - logger.debug("createNoteJob: actor={}, note={}, inbox={}", actor, postEntity, inbox) + logger.debug("createNoteJob: actor={}, create={}, inbox={}", actor, create, inbox) apRequestService.apPost( inbox, - Create( - name = "Create Note", - `object` = note, - actor = note.attributedTo, - id = "${applicationConfig.url}/create/note/${postEntity.id}" - ), + create, signer ) } diff --git a/src/main/kotlin/dev/usbharu/hideout/core/external/job/HideoutJob.kt b/src/main/kotlin/dev/usbharu/hideout/core/external/job/HideoutJob.kt index b94488af..62f989d0 100644 --- a/src/main/kotlin/dev/usbharu/hideout/core/external/job/HideoutJob.kt +++ b/src/main/kotlin/dev/usbharu/hideout/core/external/job/HideoutJob.kt @@ -15,10 +15,9 @@ object ReceiveFollowJob : HideoutJob("ReceiveFollowJob") { @Component object DeliverPostJob : HideoutJob("DeliverPostJob") { - val post: Prop = string("post") - val actor: Prop = string("actor") - val inbox: Prop = string("inbox") - val media: Prop = string("media") + val create = string("create") + val inbox = string("inbox") + val actor = string("actor") } @Component diff --git a/src/test/kotlin/dev/usbharu/hideout/activitypub/service/objects/note/APNoteServiceImplTest.kt b/src/test/kotlin/dev/usbharu/hideout/activitypub/service/objects/note/APNoteServiceImplTest.kt index 5976ccd7..5c0d6363 100644 --- a/src/test/kotlin/dev/usbharu/hideout/activitypub/service/objects/note/APNoteServiceImplTest.kt +++ b/src/test/kotlin/dev/usbharu/hideout/activitypub/service/objects/note/APNoteServiceImplTest.kt @@ -11,20 +11,13 @@ import dev.usbharu.hideout.activitypub.query.NoteQueryService import dev.usbharu.hideout.activitypub.service.common.APResourceResolveService import dev.usbharu.hideout.activitypub.service.objects.note.APNoteServiceImpl.Companion.public import dev.usbharu.hideout.activitypub.service.objects.user.APUserService -import dev.usbharu.hideout.application.config.ApplicationConfig import dev.usbharu.hideout.application.config.CharacterLimit import dev.usbharu.hideout.application.service.id.TwitterSnowflakeIdGenerateService import dev.usbharu.hideout.core.domain.exception.FailedToGetResourcesException import dev.usbharu.hideout.core.domain.model.post.Post import dev.usbharu.hideout.core.domain.model.post.PostRepository -import dev.usbharu.hideout.core.domain.model.post.Visibility -import dev.usbharu.hideout.core.domain.model.user.User -import dev.usbharu.hideout.core.external.job.DeliverPostJob -import dev.usbharu.hideout.core.query.FollowerQueryService -import dev.usbharu.hideout.core.query.MediaQueryService import dev.usbharu.hideout.core.query.PostQueryService import dev.usbharu.hideout.core.query.UserQueryService -import dev.usbharu.hideout.core.service.job.JobQueueParentService import dev.usbharu.hideout.core.service.post.PostService import io.ktor.client.* import io.ktor.client.call.* @@ -43,101 +36,17 @@ import kotlinx.coroutines.test.runTest import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Test import org.junit.jupiter.api.assertThrows -import org.mockito.Mockito.anyLong import org.mockito.kotlin.* import utils.JsonObjectMapper.objectMapper import utils.PostBuilder import utils.UserBuilder -import java.net.URL import java.time.Instant class APNoteServiceImplTest { - val userBuilder = User.UserBuilder(CharacterLimit(), ApplicationConfig(URL("https://example.com"))) val postBuilder = Post.PostBuilder(CharacterLimit()) - @Test - fun `createPost 新しい投稿`() { - val mediaQueryService = mock { - onBlocking { findByPostId(anyLong()) } doReturn emptyList() - } - - - - runTest { - val followers = listOf( - userBuilder.of( - 2L, - "follower", - "follower.example.com", - "followerUser", - "test follower user", - "https://follower.example.com/inbox", - "https://follower.example.com/outbox", - "https://follower.example.com", - "https://follower.example.com", - publicKey = "", - createdAt = Instant.now(), - keyId = "a" - ), userBuilder.of( - 3L, - "follower2", - "follower2.example.com", - "follower2User", - "test follower2 user", - "https://follower2.example.com/inbox", - "https://follower2.example.com/outbox", - "https://follower2.example.com", - "https://follower2.example.com", - publicKey = "", - createdAt = Instant.now(), - keyId = "a" - ) - ) - val userQueryService = mock { - onBlocking { findById(eq(1L)) } doReturn userBuilder.of( - 1L, - "test", - "example.com", - "testUser", - "test user", - "a", - "https://example.com/inbox", - "https://example.com/outbox", - "https://example.com", - publicKey = "", - privateKey = "a", - createdAt = Instant.now(), - keyId = "a" - ) - } - val followerQueryService = mock { - onBlocking { findFollowersById(eq(1L)) } doReturn followers - } - val jobQueueParentService = mock() - val activityPubNoteService = APNoteServiceImpl( - jobQueueParentService = jobQueueParentService, - postRepository = mock(), - apUserService = mock(), - userQueryService = userQueryService, - followerQueryService = followerQueryService, - postQueryService = mock(), - mediaQueryService = mediaQueryService, - objectMapper = objectMapper, - postService = mock(), - apResourceResolveService = mock(), - postBuilder = postBuilder, - noteQueryService = mock() - ) - val postEntity = postBuilder.of( - 1L, 1L, null, "test text", 1L, Visibility.PUBLIC, "https://example.com" - ) - activityPubNoteService.createNote(postEntity) - verify(jobQueueParentService, times(2)).schedule(eq(DeliverPostJob), any()) - } - } - @Test fun `fetchNote(String,String) ノートが既に存在する場合はDBから取得したものを返す`() = runTest { val url = "https://example.com/note" @@ -162,13 +71,9 @@ class APNoteServiceImplTest { onBlocking { findByApid(eq(url)) } doReturn (expected to post) } val apNoteServiceImpl = APNoteServiceImpl( - jobQueueParentService = mock(), postRepository = mock(), apUserService = mock(), - userQueryService = userQueryService, - followerQueryService = mock(), postQueryService = mock(), - mediaQueryService = mock(), objectMapper = objectMapper, postService = mock(), apResourceResolveService = mock(), @@ -243,13 +148,9 @@ class APNoteServiceImplTest { onBlocking { generateId() } doReturn TwitterSnowflakeIdGenerateService.generateId() } val apNoteServiceImpl = APNoteServiceImpl( - jobQueueParentService = mock(), postRepository = postRepository, apUserService = apUserService, - userQueryService = userQueryService, - followerQueryService = mock(), postQueryService = postQueryService, - mediaQueryService = mock(), objectMapper = objectMapper, postService = mock(), apResourceResolveService = apResourceResolveService, @@ -315,13 +216,9 @@ class APNoteServiceImplTest { onBlocking { findByApid(eq(url)) } doThrow FailedToGetResourcesException() } val apNoteServiceImpl = APNoteServiceImpl( - jobQueueParentService = mock(), postRepository = mock(), apUserService = mock(), - userQueryService = userQueryService, - followerQueryService = mock(), postQueryService = postQueryService, - mediaQueryService = mock(), objectMapper = objectMapper, postService = mock(), apResourceResolveService = apResourceResolveService, @@ -371,13 +268,9 @@ class APNoteServiceImplTest { onBlocking { findByApid(eq(post.apId)) } doThrow FailedToGetResourcesException() } val apNoteServiceImpl = APNoteServiceImpl( - jobQueueParentService = mock(), postRepository = postRepository, apUserService = apUserService, - userQueryService = mock(), - followerQueryService = mock(), postQueryService = mock(), - mediaQueryService = mock(), objectMapper = objectMapper, postService = postService, apResourceResolveService = mock(), @@ -433,13 +326,9 @@ class APNoteServiceImplTest { onBlocking { findByApid(eq(post.apId)) } doReturn (note to post) } val apNoteServiceImpl = APNoteServiceImpl( - jobQueueParentService = mock(), postRepository = mock(), apUserService = mock(), - userQueryService = userQueryService, - followerQueryService = mock(), postQueryService = mock(), - mediaQueryService = mock(), objectMapper = objectMapper, postService = mock(), apResourceResolveService = mock(), diff --git a/src/test/kotlin/dev/usbharu/hideout/activitypub/service/objects/note/ApNoteJobServiceImplTest.kt b/src/test/kotlin/dev/usbharu/hideout/activitypub/service/objects/note/ApNoteJobServiceImplTest.kt index 62eb6507..294c7c27 100644 --- a/src/test/kotlin/dev/usbharu/hideout/activitypub/service/objects/note/ApNoteJobServiceImplTest.kt +++ b/src/test/kotlin/dev/usbharu/hideout/activitypub/service/objects/note/ApNoteJobServiceImplTest.kt @@ -2,76 +2,58 @@ package dev.usbharu.hideout.activitypub.service.objects.note -import dev.usbharu.hideout.activitypub.domain.model.Create -import dev.usbharu.hideout.activitypub.domain.model.Note -import dev.usbharu.hideout.activitypub.service.common.APRequestService -import dev.usbharu.hideout.application.config.ApplicationConfig -import dev.usbharu.hideout.core.external.job.DeliverPostJob -import dev.usbharu.hideout.core.query.UserQueryService -import kjob.core.job.JobProps -import kotlinx.coroutines.test.runTest -import kotlinx.serialization.json.Json -import org.junit.jupiter.api.Test -import org.mockito.kotlin.* -import utils.JsonObjectMapper -import utils.TestTransaction -import utils.UserBuilder -import java.net.URL -import java.time.Instant - class ApNoteJobServiceImplTest { - @Test - fun `createPostJob 新しい投稿のJob`() = runTest { - val apRequestService = mock() - val user = UserBuilder.localUserOf() - val userQueryService = mock { - onBlocking { findByUrl(eq(user.url)) } doReturn user - } - val activityPubNoteService = ApNoteJobServiceImpl( - - userQueryService = userQueryService, - objectMapper = JsonObjectMapper.objectMapper, - apRequestService = apRequestService, - transaction = TestTransaction, - applicationConfig = ApplicationConfig(URL("https://example.com")) - ) - val remoteUserOf = UserBuilder.remoteUserOf() - activityPubNoteService.createNoteJob( - JobProps( - data = mapOf( - DeliverPostJob.actor.name to user.url, - DeliverPostJob.post.name to """{ - "id": 1, - "userId": ${user.id}, - "text": "test text", - "createdAt": 132525324, - "visibility": 0, - "url": "https://example.com" - }""", - DeliverPostJob.inbox.name to remoteUserOf.inbox, - DeliverPostJob.media.name to "[]" - ), json = Json - ) - ) - - val note = Note( - name = "Note", - id = "https://example.com", - attributedTo = user.url, - content = "test text", - published = Instant.ofEpochMilli(132525324).toString(), - to = listOfNotNull(APNoteServiceImpl.public, user.followers) - ) - val create = Create( - name = "Create Note", - `object` = note, - actor = note.attributedTo, - id = "https://example.com/create/note/1" - ) - verify(apRequestService, times(1)).apPost( - eq(remoteUserOf.inbox), - eq(create), - eq(user) - ) - } +// @Test +// fun `createPostJob 新しい投稿のJob`() = runTest { +// val apRequestService = mock() +// val user = UserBuilder.localUserOf() +// val userQueryService = mock { +// onBlocking { findByUrl(eq(user.url)) } doReturn user +// } +// val activityPubNoteService = ApNoteJobServiceImpl( +// +// userQueryService = userQueryService, +// apRequestService = apRequestService, +// objectMapper = JsonObjectMapper.objectMapper, +// transaction = TestTransaction +// ) +// val remoteUserOf = UserBuilder.remoteUserOf() +// activityPubNoteService.createNoteJob( +// JobProps( +// data = mapOf( +// DeliverPostJob.actor.name to user.url, +// DeliverPostJob.post.name to """{ +// "id": 1, +// "userId": ${user.id}, +// "text": "test text", +// "createdAt": 132525324, +// "visibility": 0, +// "url": "https://example.com" +// }""", +// DeliverPostJob.inbox.name to remoteUserOf.inbox, +// DeliverPostJob.media.name to "[]" +// ), json = Json +// ) +// ) +// +// val note = Note( +// name = "Note", +// id = "https://example.com", +// attributedTo = user.url, +// content = "test text", +// published = Instant.ofEpochMilli(132525324).toString(), +// to = listOfNotNull(APNoteServiceImpl.public, user.followers) +// ) +// val create = Create( +// name = "Create Note", +// `object` = note, +// actor = note.attributedTo, +// id = "https://example.com/create/note/1" +// ) +// verify(apRequestService, times(1)).apPost( +// eq(remoteUserOf.inbox), +// eq(create), +// eq(user) +// ) +// } }