feat: リアクション取り消しの実装を追加

This commit is contained in:
usbharu 2023-08-02 11:29:00 +09:00
parent 2661bd3e9e
commit bf096b63ac
Signed by: usbharu
GPG Key ID: 6556747BF94EEBC8
6 changed files with 92 additions and 9 deletions

View File

@ -9,6 +9,7 @@ import dev.usbharu.hideout.config.Config
import dev.usbharu.hideout.config.ConfigData import dev.usbharu.hideout.config.ConfigData
import dev.usbharu.hideout.domain.model.job.DeliverPostJob import dev.usbharu.hideout.domain.model.job.DeliverPostJob
import dev.usbharu.hideout.domain.model.job.DeliverReactionJob import dev.usbharu.hideout.domain.model.job.DeliverReactionJob
import dev.usbharu.hideout.domain.model.job.DeliverRemoveReactionJob
import dev.usbharu.hideout.domain.model.job.ReceiveFollowJob import dev.usbharu.hideout.domain.model.job.ReceiveFollowJob
import dev.usbharu.hideout.plugins.* import dev.usbharu.hideout.plugins.*
import dev.usbharu.hideout.repository.IUserRepository import dev.usbharu.hideout.repository.IUserRepository
@ -144,4 +145,10 @@ fun Application.worker() {
activityPubService.processActivity(this, it) activityPubService.processActivity(this, it)
} }
} }
kJob.register(DeliverRemoveReactionJob) {
execute {
activityPubService.processActivity(this, it)
}
}
} }

View File

@ -25,5 +25,8 @@ object DeliverReactionJob : HideoutJob("DeliverReactionJob") {
} }
object DeliverRemoveReactionJob : HideoutJob("DeliverRemoveReactionJob") { object DeliverRemoveReactionJob : HideoutJob("DeliverRemoveReactionJob") {
val id = string("id")
val inbox = string("inbox")
val actor = string("actor")
val like = string("like")
} }

View File

@ -7,9 +7,9 @@ interface ReactionRepository {
suspend fun save(reaction: Reaction): Reaction suspend fun save(reaction: Reaction): Reaction
suspend fun reactionAlreadyExist(postId: Long, userId: Long, emojiId: Long): Boolean suspend fun reactionAlreadyExist(postId: Long, userId: Long, emojiId: Long): Boolean
suspend fun findByPostId(postId: Long): List<Reaction> suspend fun findByPostId(postId: Long): List<Reaction>
suspend fun delete(reaction: Reaction):Reaction suspend fun delete(reaction: Reaction): Reaction
suspend fun deleteById(id:Long) suspend fun deleteById(id: Long)
suspend fun deleteByPostId(postId:Long) suspend fun deleteByPostId(postId: Long)
suspend fun deleteByUserId(userId: Long) suspend fun deleteByUserId(userId: Long)
suspend fun deleteByPostIdAndUserId(postId: Long,userId: Long) suspend fun deleteByPostIdAndUserId(postId: Long, userId: Long)
} }

View File

@ -5,6 +5,7 @@ import dev.usbharu.hideout.service.core.IdGenerateService
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import org.jetbrains.exposed.dao.id.LongIdTable import org.jetbrains.exposed.dao.id.LongIdTable
import org.jetbrains.exposed.sql.* import org.jetbrains.exposed.sql.*
import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq
import org.jetbrains.exposed.sql.transactions.experimental.newSuspendedTransaction import org.jetbrains.exposed.sql.transactions.experimental.newSuspendedTransaction
import org.jetbrains.exposed.sql.transactions.transaction import org.jetbrains.exposed.sql.transactions.transaction
import org.koin.core.annotation.Single import org.koin.core.annotation.Single
@ -65,6 +66,42 @@ class ReactionRepositoryImpl(
}.map { it.toReaction() } }.map { it.toReaction() }
} }
} }
override suspend fun delete(reaction: Reaction): Reaction {
query {
Reactions.deleteWhere {
id.eq(reaction.id)
.and(postId.eq(reaction.postId))
.and(userId.eq(reaction.postId))
.and(emojiId.eq(reaction.emojiId))
}
}
return reaction
}
override suspend fun deleteById(id: Long) {
query {
Reactions.deleteWhere { Reactions.id.eq(id) }
}
}
override suspend fun deleteByPostId(postId: Long) {
query {
Reactions.deleteWhere { Reactions.postId.eq(postId) }
}
}
override suspend fun deleteByUserId(userId: Long) {
query {
Reactions.deleteWhere { Reactions.userId.eq(userId) }
}
}
override suspend fun deleteByPostIdAndUserId(postId: Long, userId: Long) {
query {
Reactions.deleteWhere { Reactions.postId.eq(postId).and(Reactions.userId.eq(userId)) }
}
}
} }
fun ResultRow.toReaction(): Reaction { fun ResultRow.toReaction(): Reaction {

View File

@ -1,9 +1,12 @@
package dev.usbharu.hideout.service.activitypub package dev.usbharu.hideout.service.activitypub
import com.fasterxml.jackson.module.kotlin.readValue
import dev.usbharu.hideout.config.Config import dev.usbharu.hideout.config.Config
import dev.usbharu.hideout.domain.model.ap.Like import dev.usbharu.hideout.domain.model.ap.Like
import dev.usbharu.hideout.domain.model.ap.Undo
import dev.usbharu.hideout.domain.model.hideout.entity.Reaction import dev.usbharu.hideout.domain.model.hideout.entity.Reaction
import dev.usbharu.hideout.domain.model.job.DeliverReactionJob import dev.usbharu.hideout.domain.model.job.DeliverReactionJob
import dev.usbharu.hideout.domain.model.job.DeliverRemoveReactionJob
import dev.usbharu.hideout.exception.PostNotFoundException import dev.usbharu.hideout.exception.PostNotFoundException
import dev.usbharu.hideout.plugins.postAp import dev.usbharu.hideout.plugins.postAp
import dev.usbharu.hideout.repository.IPostRepository import dev.usbharu.hideout.repository.IPostRepository
@ -12,6 +15,7 @@ import dev.usbharu.hideout.service.user.IUserService
import io.ktor.client.* import io.ktor.client.*
import kjob.core.job.JobProps import kjob.core.job.JobProps
import org.koin.core.annotation.Single import org.koin.core.annotation.Single
import java.time.Instant
@Single @Single
class ActivityPubReactionServiceImpl( class ActivityPubReactionServiceImpl(
@ -36,6 +40,21 @@ class ActivityPubReactionServiceImpl(
} }
} }
override suspend fun removeReaction(like: Reaction) {
val followers = userService.findFollowersById(like.userId)
val user = userService.findById(like.userId)
val post =
iPostRepository.findOneById(like.postId) ?: throw PostNotFoundException("${like.postId} was not found.")
followers.forEach { follower ->
jobQueueParentService.schedule(DeliverRemoveReactionJob) {
props[it.actor] = user.url
props[it.inbox] = follower.inbox
props[it.id] = post.id.toString()
props[it.like] = Config.configData.objectMapper.writeValueAsString(like)
}
}
}
override suspend fun reactionJob(props: JobProps<DeliverReactionJob>) { override suspend fun reactionJob(props: JobProps<DeliverReactionJob>) {
val inbox = props[DeliverReactionJob.inbox] val inbox = props[DeliverReactionJob.inbox]
val actor = props[DeliverReactionJob.actor] val actor = props[DeliverReactionJob.actor]
@ -54,4 +73,21 @@ class ActivityPubReactionServiceImpl(
) )
) )
} }
override suspend fun removeReactionJob(props: JobProps<DeliverRemoveReactionJob>) {
val inbox = props[DeliverRemoveReactionJob.inbox]
val actor = props[DeliverRemoveReactionJob.actor]
val like = Config.configData.objectMapper.readValue<Like>(props[DeliverRemoveReactionJob.like])
httpClient.postAp(
urlString = inbox,
username = "$actor#pubkey",
jsonLd = Undo(
name = "Undo Reaction",
actor = actor,
`object` = like,
id = "${Config.configData.url}/undo/note/${like.id}",
published = Instant.now()
)
)
}
} }

View File

@ -5,10 +5,7 @@ import com.fasterxml.jackson.module.kotlin.readValue
import dev.usbharu.hideout.config.Config.configData import dev.usbharu.hideout.config.Config.configData
import dev.usbharu.hideout.domain.model.ActivityPubResponse import dev.usbharu.hideout.domain.model.ActivityPubResponse
import dev.usbharu.hideout.domain.model.ap.Follow import dev.usbharu.hideout.domain.model.ap.Follow
import dev.usbharu.hideout.domain.model.job.DeliverPostJob import dev.usbharu.hideout.domain.model.job.*
import dev.usbharu.hideout.domain.model.job.DeliverReactionJob
import dev.usbharu.hideout.domain.model.job.HideoutJob
import dev.usbharu.hideout.domain.model.job.ReceiveFollowJob
import dev.usbharu.hideout.exception.JsonParseException import dev.usbharu.hideout.exception.JsonParseException
import kjob.core.dsl.JobContextWithProps import kjob.core.dsl.JobContextWithProps
import kjob.core.job.JobProps import kjob.core.job.JobProps
@ -74,6 +71,9 @@ class ActivityPubServiceImpl(
DeliverPostJob -> activityPubNoteService.createNoteJob(job.props as JobProps<DeliverPostJob>) DeliverPostJob -> activityPubNoteService.createNoteJob(job.props as JobProps<DeliverPostJob>)
DeliverReactionJob -> activityPubReactionService.reactionJob(job.props as JobProps<DeliverReactionJob>) DeliverReactionJob -> activityPubReactionService.reactionJob(job.props as JobProps<DeliverReactionJob>)
DeliverRemoveReactionJob -> activityPubReactionService.removeReactionJob(
job.props as JobProps<DeliverRemoveReactionJob>
)
} }
} }
} }