mirror of https://github.com/usbharu/Hideout.git
refactor: Mastodon APIでAccountの箇所を修正
This commit is contained in:
parent
77d79e2279
commit
bdd69d258c
|
@ -52,10 +52,10 @@ data class Actor private constructor(
|
||||||
followers: String? = null,
|
followers: String? = null,
|
||||||
instance: Long? = null,
|
instance: Long? = null,
|
||||||
locked: Boolean,
|
locked: Boolean,
|
||||||
followersCount: Int,
|
followersCount: Int = 0,
|
||||||
followingCount: Int,
|
followingCount: Int = 0,
|
||||||
postsCount: Int,
|
postsCount: Int = 0,
|
||||||
lastPostDate: Instant?
|
lastPostDate: Instant? = null
|
||||||
): Actor {
|
): Actor {
|
||||||
// idは0未満ではいけない
|
// idは0未満ではいけない
|
||||||
require(id >= 0) { "id must be greater than or equal to 0." }
|
require(id >= 0) { "id must be greater than or equal to 0." }
|
||||||
|
|
|
@ -2,6 +2,7 @@ package dev.usbharu.hideout.core.service.post
|
||||||
|
|
||||||
import dev.usbharu.hideout.activitypub.service.activity.create.ApSendCreateService
|
import dev.usbharu.hideout.activitypub.service.activity.create.ApSendCreateService
|
||||||
import dev.usbharu.hideout.core.domain.exception.UserNotFoundException
|
import dev.usbharu.hideout.core.domain.exception.UserNotFoundException
|
||||||
|
import dev.usbharu.hideout.core.domain.model.actor.Actor
|
||||||
import dev.usbharu.hideout.core.domain.model.actor.ActorRepository
|
import dev.usbharu.hideout.core.domain.model.actor.ActorRepository
|
||||||
import dev.usbharu.hideout.core.domain.model.post.Post
|
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.PostRepository
|
||||||
|
@ -35,7 +36,9 @@ class PostServiceImpl(
|
||||||
|
|
||||||
override suspend fun createRemote(post: Post): Post {
|
override suspend fun createRemote(post: Post): Post {
|
||||||
logger.info("START Create Remote Post user: {}, remote url: {}", post.actorId, post.apId)
|
logger.info("START Create Remote Post user: {}, remote url: {}", post.actorId, post.apId)
|
||||||
val createdPost = internalCreate(post, false)
|
val actor =
|
||||||
|
actorRepository.findById(post.actorId) ?: throw UserNotFoundException("${post.actorId} was not found.")
|
||||||
|
val createdPost = internalCreate(post, false, actor)
|
||||||
logger.info("SUCCESS Create Remote Post url: {}", createdPost.url)
|
logger.info("SUCCESS Create Remote Post url: {}", createdPost.url)
|
||||||
return createdPost
|
return createdPost
|
||||||
}
|
}
|
||||||
|
@ -46,6 +49,10 @@ class PostServiceImpl(
|
||||||
}
|
}
|
||||||
reactionRepository.deleteByPostId(post.id)
|
reactionRepository.deleteByPostId(post.id)
|
||||||
postRepository.save(post.delete())
|
postRepository.save(post.delete())
|
||||||
|
val actor = actorRepository.findById(post.actorId)
|
||||||
|
?: throw IllegalStateException("actor: ${post.actorId} was not found.")
|
||||||
|
|
||||||
|
actorRepository.save(actor.decrementPostsCount())
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun deleteRemote(post: Post) {
|
override suspend fun deleteRemote(post: Post) {
|
||||||
|
@ -54,17 +61,28 @@ class PostServiceImpl(
|
||||||
}
|
}
|
||||||
reactionRepository.deleteByPostId(post.id)
|
reactionRepository.deleteByPostId(post.id)
|
||||||
postRepository.save(post.delete())
|
postRepository.save(post.delete())
|
||||||
|
|
||||||
|
val actor = actorRepository.findById(post.actorId)
|
||||||
|
?: throw IllegalStateException("actor: ${post.actorId} was not found.")
|
||||||
|
|
||||||
|
actorRepository.save(actor.decrementPostsCount())
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun deleteByActor(actorId: Long) {
|
override suspend fun deleteByActor(actorId: Long) {
|
||||||
postQueryService.findByActorId(actorId).filterNot { it.delted }.forEach { postRepository.save(it.delete()) }
|
postQueryService.findByActorId(actorId).filterNot { it.delted }.forEach { postRepository.save(it.delete()) }
|
||||||
|
|
||||||
|
val actor = actorRepository.findById(actorId)
|
||||||
|
?: throw IllegalStateException("actor: ${actorId} was not found.")
|
||||||
|
|
||||||
|
actorRepository.save(actor.copy(postsCount = 0, lastPostDate = null))
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun internalCreate(post: Post, isLocal: Boolean): Post {
|
private suspend fun internalCreate(post: Post, isLocal: Boolean, actor: Actor): Post {
|
||||||
return try {
|
return try {
|
||||||
if (postRepository.save(post)) {
|
if (postRepository.save(post)) {
|
||||||
try {
|
try {
|
||||||
timelineService.publishTimeline(post, isLocal)
|
timelineService.publishTimeline(post, isLocal)
|
||||||
|
actorRepository.save(actor.incrementPostsCount())
|
||||||
} catch (e: DuplicateKeyException) {
|
} catch (e: DuplicateKeyException) {
|
||||||
logger.trace("Timeline already exists.", e)
|
logger.trace("Timeline already exists.", e)
|
||||||
}
|
}
|
||||||
|
@ -91,7 +109,7 @@ class PostServiceImpl(
|
||||||
replyId = post.repolyId,
|
replyId = post.repolyId,
|
||||||
repostId = post.repostId,
|
repostId = post.repostId,
|
||||||
)
|
)
|
||||||
return internalCreate(createPost, isLocal)
|
return internalCreate(createPost, isLocal, user)
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
|
@ -2,81 +2,35 @@ package dev.usbharu.hideout.mastodon.infrastructure.exposedquery
|
||||||
|
|
||||||
import dev.usbharu.hideout.application.config.ApplicationConfig
|
import dev.usbharu.hideout.application.config.ApplicationConfig
|
||||||
import dev.usbharu.hideout.core.domain.exception.FailedToGetResourcesException
|
import dev.usbharu.hideout.core.domain.exception.FailedToGetResourcesException
|
||||||
import dev.usbharu.hideout.core.domain.model.relationship.Relationships
|
|
||||||
import dev.usbharu.hideout.core.infrastructure.exposedrepository.Actors
|
import dev.usbharu.hideout.core.infrastructure.exposedrepository.Actors
|
||||||
import dev.usbharu.hideout.core.infrastructure.exposedrepository.Posts
|
|
||||||
import dev.usbharu.hideout.domain.mastodon.model.generated.Account
|
import dev.usbharu.hideout.domain.mastodon.model.generated.Account
|
||||||
import dev.usbharu.hideout.mastodon.query.AccountQueryService
|
import dev.usbharu.hideout.mastodon.query.AccountQueryService
|
||||||
import dev.usbharu.hideout.util.singleOr
|
import dev.usbharu.hideout.util.singleOr
|
||||||
import org.jetbrains.exposed.sql.*
|
import org.jetbrains.exposed.sql.ResultRow
|
||||||
import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq
|
import org.jetbrains.exposed.sql.select
|
||||||
import org.springframework.stereotype.Repository
|
import org.springframework.stereotype.Repository
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
|
|
||||||
@Repository
|
@Repository
|
||||||
class AccountQueryServiceImpl(private val applicationConfig: ApplicationConfig) : AccountQueryService {
|
class AccountQueryServiceImpl(private val applicationConfig: ApplicationConfig) : AccountQueryService {
|
||||||
override suspend fun findById(accountId: Long): Account {
|
override suspend fun findById(accountId: Long): Account {
|
||||||
val followingCount = Count(Relationships.actorId.eq(Actors.id), true).alias("following_count")
|
|
||||||
val followersCount = Count(Relationships.targetActorId.eq(Actors.id), true).alias("followers_count")
|
val query = Actors.select { Actors.id eq accountId }
|
||||||
val postsCount = Posts.id.countDistinct().alias("posts_count")
|
|
||||||
val lastCreated = Posts.createdAt.max().alias("last_created")
|
|
||||||
val query = Actors
|
|
||||||
.join(Relationships, JoinType.LEFT) {
|
|
||||||
Actors.id eq Relationships.actorId or (Actors.id eq Relationships.targetActorId)
|
|
||||||
}
|
|
||||||
.leftJoin(Posts)
|
|
||||||
.slice(
|
|
||||||
followingCount,
|
|
||||||
followersCount,
|
|
||||||
*(Actors.realFields.toTypedArray()),
|
|
||||||
lastCreated,
|
|
||||||
postsCount
|
|
||||||
)
|
|
||||||
.select {
|
|
||||||
(Actors.id.eq(accountId)).and(
|
|
||||||
Relationships.following.eq(true).or(Relationships.following.isNull())
|
|
||||||
)
|
|
||||||
}
|
|
||||||
.groupBy(Actors.id)
|
|
||||||
|
|
||||||
return query
|
return query
|
||||||
.singleOr { FailedToGetResourcesException("accountId: $accountId wad not exist or duplicate", it) }
|
.singleOr { FailedToGetResourcesException("accountId: $accountId wad not exist or duplicate", it) }
|
||||||
.let { toAccount(it, followingCount, followersCount, postsCount, lastCreated) }
|
.let { toAccount(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun findByIds(accountIds: List<Long>): List<Account> {
|
override suspend fun findByIds(accountIds: List<Long>): List<Account> {
|
||||||
val followingCount = Count(Relationships.actorId.eq(Actors.id), true).alias("following_count")
|
val query = Actors.select { Actors.id inList accountIds }
|
||||||
val followersCount = Count(Relationships.targetActorId.eq(Actors.id), true).alias("followers_count")
|
|
||||||
val postsCount = Posts.id.countDistinct().alias("posts_count")
|
|
||||||
val lastCreated = Posts.createdAt.max().alias("last_created")
|
|
||||||
val query = Actors
|
|
||||||
.join(Relationships, JoinType.LEFT) {
|
|
||||||
Actors.id eq Relationships.actorId or (Actors.id eq Relationships.targetActorId)
|
|
||||||
}
|
|
||||||
.leftJoin(Posts)
|
|
||||||
.slice(
|
|
||||||
followingCount,
|
|
||||||
followersCount,
|
|
||||||
*(Actors.realFields.toTypedArray()),
|
|
||||||
lastCreated,
|
|
||||||
postsCount
|
|
||||||
)
|
|
||||||
.select {
|
|
||||||
Actors.id.inList(accountIds)
|
|
||||||
.and(Relationships.following.eq(true).or(Relationships.following.isNull()))
|
|
||||||
}
|
|
||||||
.groupBy(Actors.id)
|
|
||||||
|
|
||||||
return query
|
return query
|
||||||
.map { toAccount(it, followingCount, followersCount, postsCount, lastCreated) }
|
.map { toAccount(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun toAccount(
|
private fun toAccount(
|
||||||
resultRow: ResultRow,
|
resultRow: ResultRow
|
||||||
followingCount: ExpressionAlias<Long>,
|
|
||||||
followersCount: ExpressionAlias<Long>,
|
|
||||||
postsCount: ExpressionAlias<Long>,
|
|
||||||
lastCreated: ExpressionAlias<Long?>
|
|
||||||
): Account {
|
): Account {
|
||||||
val userUrl = "${applicationConfig.url}/users/${resultRow[Actors.id]}"
|
val userUrl = "${applicationConfig.url}/users/${resultRow[Actors.id]}"
|
||||||
|
|
||||||
|
@ -98,10 +52,10 @@ class AccountQueryServiceImpl(private val applicationConfig: ApplicationConfig)
|
||||||
group = false,
|
group = false,
|
||||||
discoverable = true,
|
discoverable = true,
|
||||||
createdAt = Instant.ofEpochMilli(resultRow[Actors.createdAt]).toString(),
|
createdAt = Instant.ofEpochMilli(resultRow[Actors.createdAt]).toString(),
|
||||||
lastStatusAt = resultRow[lastCreated]?.let { Instant.ofEpochMilli(it).toString() },
|
lastStatusAt = resultRow[Actors.lastPostAt]?.toString(),
|
||||||
statusesCount = resultRow[postsCount].toInt(),
|
statusesCount = resultRow[Actors.postsCount],
|
||||||
followersCount = resultRow[followersCount].toInt(),
|
followersCount = resultRow[Actors.followersCount],
|
||||||
followingCount = resultRow[followingCount].toInt(),
|
followingCount = resultRow[Actors.followingCount],
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -151,17 +151,17 @@ private fun toStatus(it: ResultRow) = Status(
|
||||||
avatarStatic = it[Actors.url] + "/icon.jpg",
|
avatarStatic = it[Actors.url] + "/icon.jpg",
|
||||||
header = it[Actors.url] + "/header.jpg",
|
header = it[Actors.url] + "/header.jpg",
|
||||||
headerStatic = it[Actors.url] + "/header.jpg",
|
headerStatic = it[Actors.url] + "/header.jpg",
|
||||||
locked = false,
|
locked = it[Actors.locked],
|
||||||
fields = emptyList(),
|
fields = emptyList(),
|
||||||
emojis = emptyList(),
|
emojis = emptyList(),
|
||||||
bot = false,
|
bot = false,
|
||||||
group = false,
|
group = false,
|
||||||
discoverable = true,
|
discoverable = true,
|
||||||
createdAt = Instant.ofEpochMilli(it[Actors.createdAt]).toString(),
|
createdAt = Instant.ofEpochMilli(it[Actors.createdAt]).toString(),
|
||||||
lastStatusAt = Instant.ofEpochMilli(it[Actors.createdAt]).toString(),
|
lastStatusAt = it[Actors.lastPostAt]?.toString(),
|
||||||
statusesCount = 0,
|
statusesCount = it[Actors.postsCount],
|
||||||
followersCount = 0,
|
followersCount = it[Actors.followersCount],
|
||||||
followingCount = 0,
|
followingCount = it[Actors.followingCount],
|
||||||
noindex = false,
|
noindex = false,
|
||||||
moved = false,
|
moved = false,
|
||||||
suspendex = false,
|
suspendex = false,
|
||||||
|
|
|
@ -31,6 +31,10 @@ create table if not exists actors
|
||||||
followers varchar(1000) null,
|
followers varchar(1000) null,
|
||||||
"instance" bigint null,
|
"instance" bigint null,
|
||||||
locked boolean not null,
|
locked boolean not null,
|
||||||
|
following_count int not null,
|
||||||
|
followers_count int not null,
|
||||||
|
posts_count int not null,
|
||||||
|
last_post_at timestamp null default null,
|
||||||
unique ("name", "domain"),
|
unique ("name", "domain"),
|
||||||
constraint fk_actors_instance__id foreign key ("instance") references instance (id) on delete restrict on update restrict
|
constraint fk_actors_instance__id foreign key ("instance") references instance (id) on delete restrict on update restrict
|
||||||
);
|
);
|
||||||
|
@ -200,8 +204,9 @@ create table if not exists relationships
|
||||||
);
|
);
|
||||||
|
|
||||||
insert into actors (id, name, domain, screen_name, description, inbox, outbox, url, public_key, private_key, created_at,
|
insert into actors (id, name, domain, screen_name, description, inbox, outbox, url, public_key, private_key, created_at,
|
||||||
key_id, following, followers, instance, locked)
|
key_id, following, followers, instance, locked, following_count, followers_count, posts_count,
|
||||||
values (0, 'ghost', '', '', '', '', '', '', '', null, 0, '', '', '', null, true);
|
last_post_at)
|
||||||
|
values (0, 'ghost', '', '', '', '', '', '', '', null, 0, '', '', '', null, true, 0, 0, 0, null);
|
||||||
|
|
||||||
create table if not exists deleted_actors
|
create table if not exists deleted_actors
|
||||||
(
|
(
|
||||||
|
|
Loading…
Reference in New Issue