mirror of https://github.com/usbharu/Hideout.git
feat: ログを追加
This commit is contained in:
parent
7cc3094084
commit
cac777a8c0
|
@ -0,0 +1,10 @@
|
||||||
|
package dev.usbharu.hideout.exception.ap
|
||||||
|
|
||||||
|
import dev.usbharu.hideout.exception.FailedToGetResourcesException
|
||||||
|
|
||||||
|
class FailedToGetActivityPubResourceException : FailedToGetResourcesException {
|
||||||
|
constructor() : super()
|
||||||
|
constructor(s: String?) : super(s)
|
||||||
|
constructor(message: String?, cause: Throwable?) : super(message, cause)
|
||||||
|
constructor(cause: Throwable?) : super(cause)
|
||||||
|
}
|
|
@ -10,6 +10,7 @@ import dev.usbharu.hideout.query.UserQueryService
|
||||||
import dev.usbharu.hideout.service.core.Transaction
|
import dev.usbharu.hideout.service.core.Transaction
|
||||||
import dev.usbharu.hideout.service.user.UserService
|
import dev.usbharu.hideout.service.user.UserService
|
||||||
import io.ktor.http.*
|
import io.ktor.http.*
|
||||||
|
import org.slf4j.LoggerFactory
|
||||||
import org.springframework.stereotype.Service
|
import org.springframework.stereotype.Service
|
||||||
|
|
||||||
interface APAcceptService {
|
interface APAcceptService {
|
||||||
|
@ -25,21 +26,32 @@ class APAcceptServiceImpl(
|
||||||
) : APAcceptService {
|
) : APAcceptService {
|
||||||
override suspend fun receiveAccept(accept: Accept): ActivityPubResponse {
|
override suspend fun receiveAccept(accept: Accept): ActivityPubResponse {
|
||||||
return transaction.transaction {
|
return transaction.transaction {
|
||||||
|
LOGGER.debug("START Follow")
|
||||||
|
LOGGER.trace("{}", accept)
|
||||||
val value = accept.`object` ?: throw IllegalActivityPubObjectException("object is null")
|
val value = accept.`object` ?: throw IllegalActivityPubObjectException("object is null")
|
||||||
if (value.type.contains("Follow").not()) {
|
if (value.type.contains("Follow").not()) {
|
||||||
|
LOGGER.warn("FAILED Activity type is not 'Follow'")
|
||||||
throw IllegalActivityPubObjectException("Invalid type ${value.type}")
|
throw IllegalActivityPubObjectException("Invalid type ${value.type}")
|
||||||
}
|
}
|
||||||
|
|
||||||
val follow = value as Follow
|
val follow = value as Follow
|
||||||
val userUrl = follow.`object` ?: throw IllegalActivityPubObjectException("object is null")
|
val userUrl = follow.`object` ?: throw IllegalActivityPubObjectException("object is null")
|
||||||
val followerUrl = follow.actor ?: throw IllegalActivityPubObjectException("actor is null")
|
val followerUrl = follow.actor ?: throw IllegalActivityPubObjectException("actor is null")
|
||||||
|
|
||||||
val user = userQueryService.findByUrl(userUrl)
|
val user = userQueryService.findByUrl(userUrl)
|
||||||
val follower = userQueryService.findByUrl(followerUrl)
|
val follower = userQueryService.findByUrl(followerUrl)
|
||||||
|
|
||||||
if (followerQueryService.alreadyFollow(user.id, follower.id)) {
|
if (followerQueryService.alreadyFollow(user.id, follower.id)) {
|
||||||
|
LOGGER.debug("END User already follow from ${follower.url} to ${user.url}")
|
||||||
return@transaction ActivityPubStringResponse(HttpStatusCode.OK, "accepted")
|
return@transaction ActivityPubStringResponse(HttpStatusCode.OK, "accepted")
|
||||||
}
|
}
|
||||||
userService.follow(user.id, follower.id)
|
userService.follow(user.id, follower.id)
|
||||||
|
LOGGER.debug("SUCCESS Follow from ${follower.url} to ${user.url}.")
|
||||||
ActivityPubStringResponse(HttpStatusCode.OK, "accepted")
|
ActivityPubStringResponse(HttpStatusCode.OK, "accepted")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private val LOGGER = LoggerFactory.getLogger(APAcceptServiceImpl::class.java)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ import dev.usbharu.hideout.domain.model.ap.Note
|
||||||
import dev.usbharu.hideout.exception.ap.IllegalActivityPubObjectException
|
import dev.usbharu.hideout.exception.ap.IllegalActivityPubObjectException
|
||||||
import dev.usbharu.hideout.service.core.Transaction
|
import dev.usbharu.hideout.service.core.Transaction
|
||||||
import io.ktor.http.*
|
import io.ktor.http.*
|
||||||
|
import org.slf4j.LoggerFactory
|
||||||
import org.springframework.stereotype.Service
|
import org.springframework.stereotype.Service
|
||||||
|
|
||||||
interface APCreateService {
|
interface APCreateService {
|
||||||
|
@ -19,15 +20,24 @@ class APCreateServiceImpl(
|
||||||
private val transaction: Transaction
|
private val transaction: Transaction
|
||||||
) : APCreateService {
|
) : APCreateService {
|
||||||
override suspend fun receiveCreate(create: Create): ActivityPubResponse {
|
override suspend fun receiveCreate(create: Create): ActivityPubResponse {
|
||||||
|
LOGGER.debug("START Create new remote note.")
|
||||||
|
LOGGER.trace("{}", create)
|
||||||
|
|
||||||
val value = create.`object` ?: throw IllegalActivityPubObjectException("object is null")
|
val value = create.`object` ?: throw IllegalActivityPubObjectException("object is null")
|
||||||
if (value.type.contains("Note").not()) {
|
if (value.type.contains("Note").not()) {
|
||||||
|
LOGGER.warn("FAILED Object type is not 'Note'")
|
||||||
throw IllegalActivityPubObjectException("object is not Note")
|
throw IllegalActivityPubObjectException("object is not Note")
|
||||||
}
|
}
|
||||||
|
|
||||||
return transaction.transaction {
|
return transaction.transaction {
|
||||||
val note = value as Note
|
val note = value as Note
|
||||||
apNoteService.fetchNote(note)
|
apNoteService.fetchNote(note)
|
||||||
|
LOGGER.debug("SUCCESS Create new remote note. ${note.id} by ${note.attributedTo}")
|
||||||
ActivityPubStringResponse(HttpStatusCode.OK, "Created")
|
ActivityPubStringResponse(HttpStatusCode.OK, "Created")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private val LOGGER = LoggerFactory.getLogger(APCreateServiceImpl::class.java)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,11 +3,13 @@ package dev.usbharu.hideout.service.ap
|
||||||
import dev.usbharu.hideout.domain.model.ActivityPubResponse
|
import dev.usbharu.hideout.domain.model.ActivityPubResponse
|
||||||
import dev.usbharu.hideout.domain.model.ActivityPubStringResponse
|
import dev.usbharu.hideout.domain.model.ActivityPubStringResponse
|
||||||
import dev.usbharu.hideout.domain.model.ap.Like
|
import dev.usbharu.hideout.domain.model.ap.Like
|
||||||
|
import dev.usbharu.hideout.exception.ap.FailedToGetActivityPubResourceException
|
||||||
import dev.usbharu.hideout.exception.ap.IllegalActivityPubObjectException
|
import dev.usbharu.hideout.exception.ap.IllegalActivityPubObjectException
|
||||||
import dev.usbharu.hideout.query.PostQueryService
|
import dev.usbharu.hideout.query.PostQueryService
|
||||||
import dev.usbharu.hideout.service.core.Transaction
|
import dev.usbharu.hideout.service.core.Transaction
|
||||||
import dev.usbharu.hideout.service.reaction.ReactionService
|
import dev.usbharu.hideout.service.reaction.ReactionService
|
||||||
import io.ktor.http.*
|
import io.ktor.http.*
|
||||||
|
import org.slf4j.LoggerFactory
|
||||||
import org.springframework.stereotype.Service
|
import org.springframework.stereotype.Service
|
||||||
|
|
||||||
interface APLikeService {
|
interface APLikeService {
|
||||||
|
@ -23,14 +25,28 @@ class APLikeServiceImpl(
|
||||||
private val transaction: Transaction
|
private val transaction: Transaction
|
||||||
) : APLikeService {
|
) : APLikeService {
|
||||||
override suspend fun receiveLike(like: Like): ActivityPubResponse {
|
override suspend fun receiveLike(like: Like): ActivityPubResponse {
|
||||||
|
LOGGER.debug("START Add Like")
|
||||||
|
LOGGER.trace("{}", like)
|
||||||
|
|
||||||
val actor = like.actor ?: throw IllegalActivityPubObjectException("actor is null")
|
val actor = like.actor ?: throw IllegalActivityPubObjectException("actor is null")
|
||||||
val content = like.content ?: throw IllegalActivityPubObjectException("content is null")
|
val content = like.content ?: throw IllegalActivityPubObjectException("content is null")
|
||||||
like.`object` ?: throw IllegalActivityPubObjectException("object is null")
|
like.`object` ?: throw IllegalActivityPubObjectException("object is null")
|
||||||
transaction.transaction {
|
transaction.transaction {
|
||||||
val person = apUserService.fetchPersonWithEntity(actor)
|
|
||||||
apNoteService.fetchNoteAsync(like.`object` ?: return@transaction).await()
|
|
||||||
|
|
||||||
|
LOGGER.trace("FETCH Liked Person $actor")
|
||||||
|
val person = apUserService.fetchPersonWithEntity(actor)
|
||||||
|
LOGGER.trace("{}", person.second)
|
||||||
|
|
||||||
|
LOGGER.trace("FETCH Liked Note ${like.`object`}")
|
||||||
|
try {
|
||||||
|
apNoteService.fetchNoteAsync(like.`object` ?: return@transaction).await()
|
||||||
|
} catch (e: FailedToGetActivityPubResourceException) {
|
||||||
|
LOGGER.debug("FAILED Failed to Get ${like.`object`}")
|
||||||
|
LOGGER.trace("", e)
|
||||||
|
return@transaction
|
||||||
|
}
|
||||||
val post = postQueryService.findByUrl(like.`object` ?: return@transaction)
|
val post = postQueryService.findByUrl(like.`object` ?: return@transaction)
|
||||||
|
LOGGER.trace("{}", post)
|
||||||
|
|
||||||
reactionService.receiveReaction(
|
reactionService.receiveReaction(
|
||||||
content,
|
content,
|
||||||
|
@ -38,7 +54,12 @@ class APLikeServiceImpl(
|
||||||
person.second.id,
|
person.second.id,
|
||||||
post.id
|
post.id
|
||||||
)
|
)
|
||||||
|
LOGGER.debug("SUCCESS Add Like($content) from ${person.second.url} to ${post.url}")
|
||||||
}
|
}
|
||||||
return ActivityPubStringResponse(HttpStatusCode.OK, "")
|
return ActivityPubStringResponse(HttpStatusCode.OK, "")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private val LOGGER = LoggerFactory.getLogger(APLikeServiceImpl::class.java)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ import dev.usbharu.hideout.domain.model.hideout.entity.Post
|
||||||
import dev.usbharu.hideout.domain.model.hideout.entity.Visibility
|
import dev.usbharu.hideout.domain.model.hideout.entity.Visibility
|
||||||
import dev.usbharu.hideout.domain.model.job.DeliverPostJob
|
import dev.usbharu.hideout.domain.model.job.DeliverPostJob
|
||||||
import dev.usbharu.hideout.exception.FailedToGetResourcesException
|
import dev.usbharu.hideout.exception.FailedToGetResourcesException
|
||||||
|
import dev.usbharu.hideout.exception.ap.FailedToGetActivityPubResourceException
|
||||||
import dev.usbharu.hideout.exception.ap.IllegalActivityPubObjectException
|
import dev.usbharu.hideout.exception.ap.IllegalActivityPubObjectException
|
||||||
import dev.usbharu.hideout.plugins.getAp
|
import dev.usbharu.hideout.plugins.getAp
|
||||||
import dev.usbharu.hideout.plugins.postAp
|
import dev.usbharu.hideout.plugins.postAp
|
||||||
|
@ -22,6 +23,7 @@ import dev.usbharu.hideout.service.job.JobQueueParentService
|
||||||
import dev.usbharu.hideout.service.post.PostCreateInterceptor
|
import dev.usbharu.hideout.service.post.PostCreateInterceptor
|
||||||
import dev.usbharu.hideout.service.post.PostService
|
import dev.usbharu.hideout.service.post.PostService
|
||||||
import io.ktor.client.*
|
import io.ktor.client.*
|
||||||
|
import io.ktor.client.plugins.*
|
||||||
import io.ktor.client.statement.*
|
import io.ktor.client.statement.*
|
||||||
import kjob.core.job.JobProps
|
import kjob.core.job.JobProps
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
@ -77,7 +79,13 @@ class APNoteServiceImpl(
|
||||||
private val logger = LoggerFactory.getLogger(APNoteServiceImpl::class.java)
|
private val logger = LoggerFactory.getLogger(APNoteServiceImpl::class.java)
|
||||||
|
|
||||||
override suspend fun createNote(post: Post) {
|
override 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)
|
val followers = followerQueryService.findFollowersById(post.userId)
|
||||||
|
|
||||||
|
logger.debug("DELIVER Deliver Note Create ${followers.size} accounts.")
|
||||||
|
|
||||||
val userEntity = userQueryService.findById(post.userId)
|
val userEntity = userQueryService.findById(post.userId)
|
||||||
val note = objectMapper.writeValueAsString(post)
|
val note = objectMapper.writeValueAsString(post)
|
||||||
val mediaList = objectMapper.writeValueAsString(mediaQueryService.findByPostId(post.id))
|
val mediaList = objectMapper.writeValueAsString(mediaQueryService.findByPostId(post.id))
|
||||||
|
@ -89,6 +97,8 @@ class APNoteServiceImpl(
|
||||||
props[DeliverPostJob.media] = mediaList
|
props[DeliverPostJob.media] = mediaList
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
logger.debug("SUCCESS Create Local Note ${post.url}")
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun createNoteJob(props: JobProps<DeliverPostJob>) {
|
override suspend fun createNoteJob(props: JobProps<DeliverPostJob>) {
|
||||||
|
@ -124,18 +134,32 @@ class APNoteServiceImpl(
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun fetchNote(url: String, targetActor: String?): Note {
|
override suspend fun fetchNote(url: String, targetActor: String?): Note {
|
||||||
|
logger.debug("START Fetch Note url: {}", url)
|
||||||
try {
|
try {
|
||||||
val post = postQueryService.findByUrl(url)
|
val post = postQueryService.findByUrl(url)
|
||||||
|
logger.debug("SUCCESS Found in local url: {}", url)
|
||||||
return postToNote(post)
|
return postToNote(post)
|
||||||
} catch (_: FailedToGetResourcesException) {
|
} catch (_: FailedToGetResourcesException) {
|
||||||
}
|
}
|
||||||
|
|
||||||
val response = httpClient.getAp(
|
logger.info("AP GET url: {}", url)
|
||||||
url,
|
val response = try {
|
||||||
targetActor?.let { "$targetActor#pubkey" }
|
httpClient.getAp(
|
||||||
)
|
url,
|
||||||
|
targetActor?.let { "$targetActor#pubkey" }
|
||||||
|
)
|
||||||
|
} catch (e: ClientRequestException) {
|
||||||
|
logger.warn(
|
||||||
|
"FAILED Failed to retrieve ActivityPub resource. HTTP Status Code: {} url: {}",
|
||||||
|
e.response.status,
|
||||||
|
url
|
||||||
|
)
|
||||||
|
throw FailedToGetActivityPubResourceException("Could not retrieve $url.", e)
|
||||||
|
}
|
||||||
val note = objectMapper.readValue<Note>(response.bodyAsText())
|
val note = objectMapper.readValue<Note>(response.bodyAsText())
|
||||||
return note(note, targetActor, url)
|
val savedNote = saveIfMissing(note, targetActor, url)
|
||||||
|
logger.debug("SUCCESS Fetch Note url: {}", url)
|
||||||
|
return savedNote
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun postToNote(post: Post): Note {
|
private suspend fun postToNote(post: Post): Note {
|
||||||
|
@ -154,7 +178,7 @@ class APNoteServiceImpl(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun note(
|
private suspend fun saveIfMissing(
|
||||||
note: Note,
|
note: Note,
|
||||||
targetActor: String?,
|
targetActor: String?,
|
||||||
url: String
|
url: String
|
||||||
|
@ -167,12 +191,12 @@ class APNoteServiceImpl(
|
||||||
val findByApId = try {
|
val findByApId = try {
|
||||||
postQueryService.findByApId(note.id!!)
|
postQueryService.findByApId(note.id!!)
|
||||||
} catch (_: FailedToGetResourcesException) {
|
} catch (_: FailedToGetResourcesException) {
|
||||||
return internalNote(note, targetActor, url)
|
return saveNote(note, targetActor, url)
|
||||||
}
|
}
|
||||||
return postToNote(findByApId)
|
return postToNote(findByApId)
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun internalNote(note: Note, targetActor: String?, url: String): Note {
|
private suspend fun saveNote(note: Note, targetActor: String?, url: String): Note {
|
||||||
val person = apUserService.fetchPersonWithEntity(
|
val person = apUserService.fetchPersonWithEntity(
|
||||||
note.attributedTo ?: throw IllegalActivityPubObjectException("note.attributedTo is null"),
|
note.attributedTo ?: throw IllegalActivityPubObjectException("note.attributedTo is null"),
|
||||||
targetActor
|
targetActor
|
||||||
|
@ -212,7 +236,7 @@ class APNoteServiceImpl(
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun fetchNote(note: Note, targetActor: String?): Note =
|
override suspend fun fetchNote(note: Note, targetActor: String?): Note =
|
||||||
note(note, targetActor, note.id ?: throw IllegalArgumentException("note.id is null"))
|
saveIfMissing(note, targetActor, note.id ?: throw IllegalArgumentException("note.id is null"))
|
||||||
|
|
||||||
override suspend fun run(post: Post) {
|
override suspend fun run(post: Post) {
|
||||||
createNote(post)
|
createNote(post)
|
||||||
|
|
|
@ -203,16 +203,11 @@ class APServiceImpl(
|
||||||
|
|
||||||
@Suppress("CyclomaticComplexMethod", "NotImplementedDeclaration")
|
@Suppress("CyclomaticComplexMethod", "NotImplementedDeclaration")
|
||||||
override suspend fun processActivity(json: String, type: ActivityType): ActivityPubResponse {
|
override suspend fun processActivity(json: String, type: ActivityType): ActivityPubResponse {
|
||||||
logger.debug("proccess activity: {}", type)
|
logger.debug("process activity: {}", type)
|
||||||
return when (type) {
|
return when (type) {
|
||||||
ActivityType.Accept -> apAcceptService.receiveAccept(objectMapper.readValue(json))
|
ActivityType.Accept -> apAcceptService.receiveAccept(objectMapper.readValue(json))
|
||||||
ActivityType.Follow -> apReceiveFollowService.receiveFollow(
|
ActivityType.Follow -> apReceiveFollowService
|
||||||
objectMapper.readValue(
|
.receiveFollow(objectMapper.readValue(json, Follow::class.java))
|
||||||
json,
|
|
||||||
Follow::class.java
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
ActivityType.Create -> apCreateService.receiveCreate(objectMapper.readValue(json))
|
ActivityType.Create -> apCreateService.receiveCreate(objectMapper.readValue(json))
|
||||||
ActivityType.Like -> apLikeService.receiveLike(objectMapper.readValue(json))
|
ActivityType.Like -> apLikeService.receiveLike(objectMapper.readValue(json))
|
||||||
ActivityType.Undo -> apUndoService.receiveUndo(objectMapper.readValue(json))
|
ActivityType.Undo -> apUndoService.receiveUndo(objectMapper.readValue(json))
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
<logger name="org.eclipse.jetty" level="INFO"/>
|
<logger name="org.eclipse.jetty" level="INFO"/>
|
||||||
<logger name="io.netty" level="INFO"/>
|
<logger name="io.netty" level="INFO"/>
|
||||||
<logger name="kjob.core.internal.scheduler.JobServiceImpl" level="INFO"/>
|
<logger name="kjob.core.internal.scheduler.JobServiceImpl" level="INFO"/>
|
||||||
<logger name="Exposed" level="DEBUG"/>
|
<logger name="Exposed" level="INFO"/>
|
||||||
<logger name="io.ktor.server.plugins.contentnegotiation" level="INFO"/>
|
<logger name="io.ktor.server.plugins.contentnegotiation" level="INFO"/>
|
||||||
<logger name="org.springframework.web.filter.CommonsRequestLoggingFilter" level="INFO"/>
|
<logger name="org.springframework.web.filter.CommonsRequestLoggingFilter" level="INFO"/>
|
||||||
</configuration>
|
</configuration>
|
||||||
|
|
Loading…
Reference in New Issue