diff --git a/src/main/kotlin/dev/usbharu/hideout/query/FollowerQueryService.kt b/src/main/kotlin/dev/usbharu/hideout/query/FollowerQueryService.kt new file mode 100644 index 00000000..3ca4e4e6 --- /dev/null +++ b/src/main/kotlin/dev/usbharu/hideout/query/FollowerQueryService.kt @@ -0,0 +1,12 @@ +package dev.usbharu.hideout.query + +import dev.usbharu.hideout.domain.model.hideout.entity.User + +interface FollowerQueryService { + suspend fun findFollowersById(id: Long): List + suspend fun findFollowersByNameAndDomain(name: String, domain: String): List + suspend fun findFollowingById(id: Long): List + suspend fun findFollowingByNameAndDomain(name: String, domain: String): List + suspend fun appendFollower(user: Long, follower: Long) + suspend fun removeFollower(user: Long, follower: Long) +} diff --git a/src/main/kotlin/dev/usbharu/hideout/query/FollowerQueryServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/query/FollowerQueryServiceImpl.kt new file mode 100644 index 00000000..ffcb1ccc --- /dev/null +++ b/src/main/kotlin/dev/usbharu/hideout/query/FollowerQueryServiceImpl.kt @@ -0,0 +1,201 @@ +package dev.usbharu.hideout.query + +import dev.usbharu.hideout.domain.model.hideout.entity.User +import dev.usbharu.hideout.repository.Users +import dev.usbharu.hideout.repository.UsersFollowers +import org.jetbrains.exposed.sql.* +import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq +import java.time.Instant + +class FollowerQueryServiceImpl : FollowerQueryService { + override suspend fun findFollowersById(id: Long): List { + val followers = Users.alias("FOLLOWERS") + return Users.innerJoin( + otherTable = UsersFollowers, + onColumn = { Users.id }, + otherColumn = { userId } + ) + .innerJoin( + otherTable = followers, + onColumn = { UsersFollowers.followerId }, + otherColumn = { followers[Users.id] } + ) + .slice( + followers[Users.id], + followers[Users.name], + followers[Users.domain], + followers[Users.screenName], + followers[Users.description], + followers[Users.password], + followers[Users.inbox], + followers[Users.outbox], + followers[Users.url], + followers[Users.publicKey], + followers[Users.privateKey], + followers[Users.createdAt] + ) + .select { Users.id eq id } + .map { + User( + id = it[followers[Users.id]], + name = it[followers[Users.name]], + domain = it[followers[Users.domain]], + screenName = it[followers[Users.screenName]], + description = it[followers[Users.description]], + password = it[followers[Users.password]], + inbox = it[followers[Users.inbox]], + outbox = it[followers[Users.outbox]], + url = it[followers[Users.url]], + publicKey = it[followers[Users.publicKey]], + privateKey = it[followers[Users.privateKey]], + createdAt = Instant.ofEpochMilli(it[followers[Users.createdAt]]) + ) + } + } + + override suspend fun findFollowersByNameAndDomain(name: String, domain: String): List { + val followers = Users.alias("FOLLOWERS") + return Users.innerJoin( + otherTable = UsersFollowers, + onColumn = { Users.id }, + otherColumn = { userId } + ) + .innerJoin( + otherTable = followers, + onColumn = { UsersFollowers.followerId }, + otherColumn = { followers[Users.id] } + ) + .slice( + followers[Users.id], + followers[Users.name], + followers[Users.domain], + followers[Users.screenName], + followers[Users.description], + followers[Users.password], + followers[Users.inbox], + followers[Users.outbox], + followers[Users.url], + followers[Users.publicKey], + followers[Users.privateKey], + followers[Users.createdAt] + ) + .select { Users.name eq name and (Users.domain eq domain) } + .map { + User( + id = it[followers[Users.id]], + name = it[followers[Users.name]], + domain = it[followers[Users.domain]], + screenName = it[followers[Users.screenName]], + description = it[followers[Users.description]], + password = it[followers[Users.password]], + inbox = it[followers[Users.inbox]], + outbox = it[followers[Users.outbox]], + url = it[followers[Users.url]], + publicKey = it[followers[Users.publicKey]], + privateKey = it[followers[Users.privateKey]], + createdAt = Instant.ofEpochMilli(it[followers[Users.createdAt]]) + ) + } + } + + override suspend fun findFollowingById(id: Long): List { + val followers = Users.alias("FOLLOWERS") + return Users.innerJoin( + otherTable = UsersFollowers, + onColumn = { Users.id }, + otherColumn = { userId } + ) + .innerJoin( + otherTable = followers, + onColumn = { UsersFollowers.followerId }, + otherColumn = { followers[Users.id] } + ) + .slice( + followers[Users.id], + followers[Users.name], + followers[Users.domain], + followers[Users.screenName], + followers[Users.description], + followers[Users.password], + followers[Users.inbox], + followers[Users.outbox], + followers[Users.url], + followers[Users.publicKey], + followers[Users.privateKey], + followers[Users.createdAt] + ) + .select { followers[Users.id] eq id } + .map { + User( + id = it[followers[Users.id]], + name = it[followers[Users.name]], + domain = it[followers[Users.domain]], + screenName = it[followers[Users.screenName]], + description = it[followers[Users.description]], + password = it[followers[Users.password]], + inbox = it[followers[Users.inbox]], + outbox = it[followers[Users.outbox]], + url = it[followers[Users.url]], + publicKey = it[followers[Users.publicKey]], + privateKey = it[followers[Users.privateKey]], + createdAt = Instant.ofEpochMilli(it[followers[Users.createdAt]]) + ) + } + } + + override suspend fun findFollowingByNameAndDomain(name: String, domain: String): List { + val followers = Users.alias("FOLLOWERS") + return Users.innerJoin( + otherTable = UsersFollowers, + onColumn = { Users.id }, + otherColumn = { userId } + ) + .innerJoin( + otherTable = followers, + onColumn = { UsersFollowers.followerId }, + otherColumn = { followers[Users.id] } + ) + .slice( + followers[Users.id], + followers[Users.name], + followers[Users.domain], + followers[Users.screenName], + followers[Users.description], + followers[Users.password], + followers[Users.inbox], + followers[Users.outbox], + followers[Users.url], + followers[Users.publicKey], + followers[Users.privateKey], + followers[Users.createdAt] + ) + .select { followers[Users.name] eq name and (followers[Users.domain] eq domain) } + .map { + User( + id = it[followers[Users.id]], + name = it[followers[Users.name]], + domain = it[followers[Users.domain]], + screenName = it[followers[Users.screenName]], + description = it[followers[Users.description]], + password = it[followers[Users.password]], + inbox = it[followers[Users.inbox]], + outbox = it[followers[Users.outbox]], + url = it[followers[Users.url]], + publicKey = it[followers[Users.publicKey]], + privateKey = it[followers[Users.privateKey]], + createdAt = Instant.ofEpochMilli(it[followers[Users.createdAt]]) + ) + } + } + + override suspend fun appendFollower(user: Long, follower: Long) { + UsersFollowers.insert { + it[userId] = user + it[followerId] = follower + } + } + + override suspend fun removeFollower(user: Long, follower: Long) { + UsersFollowers.deleteWhere { Users.id eq user and (followerId eq follower) } + } +}