From 84356161a8bfece2cf1fda26736675dc35efdad2 Mon Sep 17 00:00:00 2001 From: usbharu <64310155+usbharu@users.noreply.github.com> Date: Sat, 18 Nov 2023 11:37:51 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=96=B0=E8=A6=8F=E3=83=A6=E3=83=BC?= =?UTF-8?q?=E3=82=B6=E3=83=BC=E4=BD=9C=E6=88=90=E6=99=82=E3=81=ABInstance?= =?UTF-8?q?=E3=82=92=E5=8F=96=E5=BE=97=E3=81=99=E3=82=8B=E3=82=88=E3=81=86?= =?UTF-8?q?=E3=81=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/service/instance/InstanceService.kt | 49 ++++++++++++++++++- .../service/resource/KtorResolveResponse.kt | 17 +++++++ .../core/service/resource/ResolveResponse.kt | 2 + .../core/service/user/UserServiceImpl.kt | 6 ++- 4 files changed, 72 insertions(+), 2 deletions(-) diff --git a/src/main/kotlin/dev/usbharu/hideout/core/service/instance/InstanceService.kt b/src/main/kotlin/dev/usbharu/hideout/core/service/instance/InstanceService.kt index afa182af..bb4a2a0c 100644 --- a/src/main/kotlin/dev/usbharu/hideout/core/service/instance/InstanceService.kt +++ b/src/main/kotlin/dev/usbharu/hideout/core/service/instance/InstanceService.kt @@ -1,17 +1,64 @@ package dev.usbharu.hideout.core.service.instance +import com.fasterxml.jackson.databind.ObjectMapper +import dev.usbharu.hideout.activitypub.domain.model.nodeinfo.Nodeinfo +import dev.usbharu.hideout.activitypub.domain.model.nodeinfo.Nodeinfo2_0 import dev.usbharu.hideout.core.domain.model.instance.Instance import dev.usbharu.hideout.core.domain.model.instance.InstanceRepository +import dev.usbharu.hideout.core.service.resource.ResourceResolveService import org.springframework.stereotype.Service +import java.net.URL import java.time.Instant interface InstanceService { + suspend fun fetchInstance(url: String): Instance suspend fun createNewInstance(instanceCreateDto: InstanceCreateDto): Instance } @Service -class InstanceServiceImpl(private val instanceRepository: InstanceRepository) : InstanceService { +class InstanceServiceImpl( + private val instanceRepository: InstanceRepository, + private val resourceResolveService: ResourceResolveService, + private val objectMapper: ObjectMapper +) : InstanceService { + override suspend fun fetchInstance(url: String): Instance { + val u = URL(url) + val resolveInstanceUrl = u.protocol + "://" + u.host + val nodeinfoJson = resourceResolveService.resolve("$resolveInstanceUrl/.well-known/nodeinfo").bodyAsText() + val nodeinfo = objectMapper.readValue(nodeinfoJson, Nodeinfo::class.java) + val nodeinfoPathMap = nodeinfo.links.map { it.rel to it.href }.toMap() + + + for ((key, value) in nodeinfoPathMap) { + when (key) { + "http://nodeinfo.diaspora.software/ns/schema/2.0" -> { + val nodeinfo20 = objectMapper.readValue( + resourceResolveService.resolve(value).bodyAsText(), + Nodeinfo2_0::class.java + ) + + val instanceCreateDto = InstanceCreateDto( + nodeinfo20.metadata.nodeName, + nodeinfo20.metadata.nodeDescription, + resolveInstanceUrl, + resolveInstanceUrl + "/favicon.ico", + null, + nodeinfo20.software.name, + nodeinfo20.software.version + ) + return createNewInstance(instanceCreateDto) + } + + else -> { + TODO() + } + } + } + + throw IllegalStateException("Nodeinfo aren't found.") + } + override suspend fun createNewInstance(instanceCreateDto: InstanceCreateDto): Instance { val instance = Instance( instanceRepository.generateId(), diff --git a/src/main/kotlin/dev/usbharu/hideout/core/service/resource/KtorResolveResponse.kt b/src/main/kotlin/dev/usbharu/hideout/core/service/resource/KtorResolveResponse.kt index 8261d8dc..3a5e2ad1 100644 --- a/src/main/kotlin/dev/usbharu/hideout/core/service/resource/KtorResolveResponse.kt +++ b/src/main/kotlin/dev/usbharu/hideout/core/service/resource/KtorResolveResponse.kt @@ -7,7 +7,24 @@ import java.io.InputStream class KtorResolveResponse(val ktorHttpResponse: HttpResponse) : ResolveResponse { + private lateinit var _bodyAsText: String + private lateinit var _bodyAsBytes: ByteArray + override suspend fun body(): InputStream = ktorHttpResponse.bodyAsChannel().toInputStream() + override suspend fun bodyAsText(): String { + if (!this::_bodyAsText.isInitialized) { + _bodyAsText = ktorHttpResponse.bodyAsText() + } + return _bodyAsText + } + + override suspend fun bodyAsBytes(): ByteArray { + if (!this::_bodyAsBytes.isInitialized) { + _bodyAsBytes = ktorHttpResponse.readBytes() + } + return _bodyAsBytes + } + override suspend fun header(): Map> = ktorHttpResponse.headers.toMap() override suspend fun status(): Int = ktorHttpResponse.status.value override suspend fun statusMessage(): String = ktorHttpResponse.status.description diff --git a/src/main/kotlin/dev/usbharu/hideout/core/service/resource/ResolveResponse.kt b/src/main/kotlin/dev/usbharu/hideout/core/service/resource/ResolveResponse.kt index bcfb0bcb..6b0cc202 100644 --- a/src/main/kotlin/dev/usbharu/hideout/core/service/resource/ResolveResponse.kt +++ b/src/main/kotlin/dev/usbharu/hideout/core/service/resource/ResolveResponse.kt @@ -4,6 +4,8 @@ import java.io.InputStream interface ResolveResponse { suspend fun body(): InputStream + suspend fun bodyAsText(): String + suspend fun bodyAsBytes(): ByteArray suspend fun header(): Map> suspend fun status(): Int suspend fun statusMessage(): String diff --git a/src/main/kotlin/dev/usbharu/hideout/core/service/user/UserServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/core/service/user/UserServiceImpl.kt index 40df3646..20a49f4f 100644 --- a/src/main/kotlin/dev/usbharu/hideout/core/service/user/UserServiceImpl.kt +++ b/src/main/kotlin/dev/usbharu/hideout/core/service/user/UserServiceImpl.kt @@ -8,6 +8,7 @@ import dev.usbharu.hideout.core.domain.model.user.UserRepository import dev.usbharu.hideout.core.query.FollowerQueryService import dev.usbharu.hideout.core.query.UserQueryService import dev.usbharu.hideout.core.service.follow.SendFollowDto +import dev.usbharu.hideout.core.service.instance.InstanceService import org.jetbrains.exposed.exceptions.ExposedSQLException import org.springframework.stereotype.Service import java.time.Instant @@ -20,7 +21,8 @@ class UserServiceImpl( private val userQueryService: UserQueryService, private val followerQueryService: FollowerQueryService, private val userBuilder: User.UserBuilder, - private val applicationConfig: ApplicationConfig + private val applicationConfig: ApplicationConfig, + private val instanceService: InstanceService ) : UserService { @@ -55,6 +57,8 @@ class UserServiceImpl( } override suspend fun createRemoteUser(user: RemoteUserCreateDto): User { + instanceService.fetchInstance(user.url) + val nextId = userRepository.nextId() val userEntity = userBuilder.of( id = nextId,