mirror of https://github.com/usbharu/Hideout.git
refactor: Timeline APIをPagination APIに対応
This commit is contained in:
parent
7141c7bc6a
commit
b63288ff28
|
@ -1,5 +1,8 @@
|
||||||
package dev.usbharu.hideout.core.service.timeline
|
package dev.usbharu.hideout.core.service.timeline
|
||||||
|
|
||||||
|
import dev.usbharu.hideout.application.infrastructure.exposed.Page
|
||||||
|
import dev.usbharu.hideout.application.infrastructure.exposed.PaginationList
|
||||||
|
import dev.usbharu.hideout.application.infrastructure.exposed.pagination
|
||||||
import dev.usbharu.hideout.core.infrastructure.exposedrepository.Timelines
|
import dev.usbharu.hideout.core.infrastructure.exposedrepository.Timelines
|
||||||
import dev.usbharu.hideout.domain.mastodon.model.generated.Status
|
import dev.usbharu.hideout.domain.mastodon.model.generated.Status
|
||||||
import dev.usbharu.hideout.mastodon.interfaces.api.status.StatusQuery
|
import dev.usbharu.hideout.mastodon.interfaces.api.status.StatusQuery
|
||||||
|
@ -52,4 +55,40 @@ class ExposedGenerateTimelineService(private val statusQueryService: StatusQuery
|
||||||
|
|
||||||
return statusQueryService.findByPostIdsWithMediaIds(statusQueries)
|
return statusQueryService.findByPostIdsWithMediaIds(statusQueries)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override suspend fun getTimeline(
|
||||||
|
forUserId: Long?,
|
||||||
|
localOnly: Boolean,
|
||||||
|
mediaOnly: Boolean,
|
||||||
|
page: Page
|
||||||
|
): PaginationList<Status, Long> {
|
||||||
|
val query = Timelines.selectAll()
|
||||||
|
|
||||||
|
if (forUserId != null) {
|
||||||
|
query.andWhere { Timelines.userId eq forUserId }
|
||||||
|
}
|
||||||
|
if (localOnly) {
|
||||||
|
query.andWhere { Timelines.isLocal eq true }
|
||||||
|
}
|
||||||
|
query.pagination(page, Timelines.id)
|
||||||
|
val result = query
|
||||||
|
.orderBy(Timelines.createdAt, SortOrder.DESC)
|
||||||
|
|
||||||
|
val statusQueries = result.map {
|
||||||
|
StatusQuery(
|
||||||
|
it[Timelines.postId],
|
||||||
|
it[Timelines.replyId],
|
||||||
|
it[Timelines.repostId],
|
||||||
|
it[Timelines.mediaIds].split(",").mapNotNull { s -> s.toLongOrNull() },
|
||||||
|
it[Timelines.emojiIds].split(",").mapNotNull { s -> s.toLongOrNull() }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
val findByPostIdsWithMediaIds = statusQueryService.findByPostIdsWithMediaIds(statusQueries)
|
||||||
|
return PaginationList(
|
||||||
|
findByPostIdsWithMediaIds,
|
||||||
|
findByPostIdsWithMediaIds.lastOrNull()?.id?.toLongOrNull(),
|
||||||
|
findByPostIdsWithMediaIds.firstOrNull()?.id?.toLongOrNull()
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package dev.usbharu.hideout.core.service.timeline
|
package dev.usbharu.hideout.core.service.timeline
|
||||||
|
|
||||||
|
import dev.usbharu.hideout.application.infrastructure.exposed.Page
|
||||||
|
import dev.usbharu.hideout.application.infrastructure.exposed.PaginationList
|
||||||
import dev.usbharu.hideout.domain.mastodon.model.generated.Status
|
import dev.usbharu.hideout.domain.mastodon.model.generated.Status
|
||||||
import org.springframework.stereotype.Service
|
import org.springframework.stereotype.Service
|
||||||
|
|
||||||
|
@ -15,4 +17,11 @@ interface GenerateTimelineService {
|
||||||
sinceId: Long? = null,
|
sinceId: Long? = null,
|
||||||
limit: Int = 20
|
limit: Int = 20
|
||||||
): List<Status>
|
): List<Status>
|
||||||
|
|
||||||
|
suspend fun getTimeline(
|
||||||
|
forUserId: Long? = null,
|
||||||
|
localOnly: Boolean = false,
|
||||||
|
mediaOnly: Boolean = false,
|
||||||
|
page: Page
|
||||||
|
): PaginationList<Status, Long>
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package dev.usbharu.hideout.core.service.timeline
|
package dev.usbharu.hideout.core.service.timeline
|
||||||
|
|
||||||
|
import dev.usbharu.hideout.application.infrastructure.exposed.Page
|
||||||
|
import dev.usbharu.hideout.application.infrastructure.exposed.PaginationList
|
||||||
import dev.usbharu.hideout.core.domain.model.timeline.Timeline
|
import dev.usbharu.hideout.core.domain.model.timeline.Timeline
|
||||||
import dev.usbharu.hideout.domain.mastodon.model.generated.Status
|
import dev.usbharu.hideout.domain.mastodon.model.generated.Status
|
||||||
import dev.usbharu.hideout.mastodon.interfaces.api.status.StatusQuery
|
import dev.usbharu.hideout.mastodon.interfaces.api.status.StatusQuery
|
||||||
|
@ -63,4 +65,54 @@ class MongoGenerateTimelineService(
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override suspend fun getTimeline(
|
||||||
|
forUserId: Long?,
|
||||||
|
localOnly: Boolean,
|
||||||
|
mediaOnly: Boolean,
|
||||||
|
page: Page
|
||||||
|
): PaginationList<Status, Long> {
|
||||||
|
val query = Query()
|
||||||
|
|
||||||
|
if (forUserId != null) {
|
||||||
|
val criteria = Criteria.where("userId").`is`(forUserId)
|
||||||
|
query.addCriteria(criteria)
|
||||||
|
}
|
||||||
|
if (localOnly) {
|
||||||
|
val criteria = Criteria.where("isLocal").`is`(true)
|
||||||
|
query.addCriteria(criteria)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (page.minId != null) {
|
||||||
|
page.minId?.let { query.addCriteria(Criteria.where("id").gt(it)) }
|
||||||
|
page.maxId?.let { query.addCriteria(Criteria.where("id").lt(it)) }
|
||||||
|
} else {
|
||||||
|
query.with(Sort.by(Sort.Direction.DESC, "createdAt"))
|
||||||
|
page.sinceId?.let { query.addCriteria(Criteria.where("id").gt(it)) }
|
||||||
|
page.maxId?.let { query.addCriteria(Criteria.where("id").lt(it)) }
|
||||||
|
}
|
||||||
|
|
||||||
|
page.limit?.let { query.limit(it) }
|
||||||
|
|
||||||
|
query.with(Sort.by(Sort.Direction.DESC, "createdAt"))
|
||||||
|
|
||||||
|
val timelines = mongoTemplate.find(query, Timeline::class.java)
|
||||||
|
|
||||||
|
val statuses = statusQueryService.findByPostIdsWithMediaIds(
|
||||||
|
timelines.map {
|
||||||
|
StatusQuery(
|
||||||
|
it.postId,
|
||||||
|
it.replyId,
|
||||||
|
it.repostId,
|
||||||
|
it.mediaIds,
|
||||||
|
it.emojiIds
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
return PaginationList(
|
||||||
|
statuses,
|
||||||
|
statuses.lastOrNull()?.id?.toLongOrNull(),
|
||||||
|
statuses.firstOrNull()?.id?.toLongOrNull()
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
package dev.usbharu.hideout.mastodon.interfaces.api.timeline
|
package dev.usbharu.hideout.mastodon.interfaces.api.timeline
|
||||||
|
|
||||||
|
import dev.usbharu.hideout.application.config.ApplicationConfig
|
||||||
|
import dev.usbharu.hideout.application.infrastructure.exposed.Page
|
||||||
|
import dev.usbharu.hideout.application.infrastructure.exposed.toHttpHeader
|
||||||
import dev.usbharu.hideout.controller.mastodon.generated.TimelineApi
|
import dev.usbharu.hideout.controller.mastodon.generated.TimelineApi
|
||||||
import dev.usbharu.hideout.core.infrastructure.springframework.security.LoginUserContextHolder
|
import dev.usbharu.hideout.core.infrastructure.springframework.security.LoginUserContextHolder
|
||||||
import dev.usbharu.hideout.domain.mastodon.model.generated.Status
|
import dev.usbharu.hideout.domain.mastodon.model.generated.Status
|
||||||
|
@ -14,7 +17,8 @@ import org.springframework.stereotype.Controller
|
||||||
@Controller
|
@Controller
|
||||||
class MastodonTimelineApiController(
|
class MastodonTimelineApiController(
|
||||||
private val timelineApiService: TimelineApiService,
|
private val timelineApiService: TimelineApiService,
|
||||||
private val loginUserContextHolder: LoginUserContextHolder
|
private val loginUserContextHolder: LoginUserContextHolder,
|
||||||
|
private val applicationConfig: ApplicationConfig,
|
||||||
) : TimelineApi {
|
) : TimelineApi {
|
||||||
override fun apiV1TimelinesHomeGet(
|
override fun apiV1TimelinesHomeGet(
|
||||||
maxId: String?,
|
maxId: String?,
|
||||||
|
@ -24,10 +28,12 @@ class MastodonTimelineApiController(
|
||||||
): ResponseEntity<Flow<Status>> = runBlocking {
|
): ResponseEntity<Flow<Status>> = runBlocking {
|
||||||
val homeTimeline = timelineApiService.homeTimeline(
|
val homeTimeline = timelineApiService.homeTimeline(
|
||||||
userId = loginUserContextHolder.getLoginUserId(),
|
userId = loginUserContextHolder.getLoginUserId(),
|
||||||
|
page = Page.of(
|
||||||
maxId = maxId?.toLongOrNull(),
|
maxId = maxId?.toLongOrNull(),
|
||||||
minId = minId?.toLongOrNull(),
|
minId = minId?.toLongOrNull(),
|
||||||
sinceId = sinceId?.toLongOrNull(),
|
sinceId = sinceId?.toLongOrNull(),
|
||||||
limit = limit ?: 20
|
limit = limit?.coerceIn(0, 80) ?: 40
|
||||||
|
)
|
||||||
)
|
)
|
||||||
ResponseEntity(homeTimeline.asFlow(), HttpStatus.OK)
|
ResponseEntity(homeTimeline.asFlow(), HttpStatus.OK)
|
||||||
}
|
}
|
||||||
|
@ -45,11 +51,21 @@ class MastodonTimelineApiController(
|
||||||
localOnly = local ?: false,
|
localOnly = local ?: false,
|
||||||
remoteOnly = remote ?: false,
|
remoteOnly = remote ?: false,
|
||||||
mediaOnly = onlyMedia ?: false,
|
mediaOnly = onlyMedia ?: false,
|
||||||
|
page = Page.of(
|
||||||
maxId = maxId?.toLongOrNull(),
|
maxId = maxId?.toLongOrNull(),
|
||||||
minId = minId?.toLongOrNull(),
|
minId = minId?.toLongOrNull(),
|
||||||
sinceId = sinceId?.toLongOrNull(),
|
sinceId = sinceId?.toLongOrNull(),
|
||||||
limit = limit ?: 20
|
limit = limit?.coerceIn(0, 80) ?: 40
|
||||||
)
|
)
|
||||||
ResponseEntity(publicTimeline.asFlow(), HttpStatus.OK)
|
)
|
||||||
|
|
||||||
|
val httpHeader = publicTimeline.toHttpHeader(
|
||||||
|
{ "${applicationConfig.url}/api/v1/public?max_id=$it" },
|
||||||
|
{ "${applicationConfig.url}/api/v1/public?min_id=$it" }
|
||||||
|
) ?: return@runBlocking ResponseEntity(
|
||||||
|
publicTimeline.asFlow(),
|
||||||
|
HttpStatus.OK
|
||||||
|
)
|
||||||
|
ResponseEntity.ok().header("Link", httpHeader).body(publicTimeline.asFlow())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
package dev.usbharu.hideout.mastodon.service.timeline
|
package dev.usbharu.hideout.mastodon.service.timeline
|
||||||
|
|
||||||
import dev.usbharu.hideout.application.external.Transaction
|
import dev.usbharu.hideout.application.external.Transaction
|
||||||
|
import dev.usbharu.hideout.application.infrastructure.exposed.Page
|
||||||
|
import dev.usbharu.hideout.application.infrastructure.exposed.PaginationList
|
||||||
import dev.usbharu.hideout.core.service.timeline.GenerateTimelineService
|
import dev.usbharu.hideout.core.service.timeline.GenerateTimelineService
|
||||||
import dev.usbharu.hideout.domain.mastodon.model.generated.Status
|
import dev.usbharu.hideout.domain.mastodon.model.generated.Status
|
||||||
import org.springframework.stereotype.Service
|
import org.springframework.stereotype.Service
|
||||||
|
@ -17,6 +19,13 @@ interface TimelineApiService {
|
||||||
limit: Int = 20
|
limit: Int = 20
|
||||||
): List<Status>
|
): List<Status>
|
||||||
|
|
||||||
|
suspend fun publicTimeline(
|
||||||
|
localOnly: Boolean = false,
|
||||||
|
remoteOnly: Boolean = false,
|
||||||
|
mediaOnly: Boolean = false,
|
||||||
|
page: Page
|
||||||
|
): PaginationList<Status, Long>
|
||||||
|
|
||||||
suspend fun homeTimeline(
|
suspend fun homeTimeline(
|
||||||
userId: Long,
|
userId: Long,
|
||||||
maxId: Long?,
|
maxId: Long?,
|
||||||
|
@ -24,6 +33,11 @@ interface TimelineApiService {
|
||||||
sinceId: Long?,
|
sinceId: Long?,
|
||||||
limit: Int = 20
|
limit: Int = 20
|
||||||
): List<Status>
|
): List<Status>
|
||||||
|
|
||||||
|
suspend fun homeTimeline(
|
||||||
|
userId: Long,
|
||||||
|
page: Page
|
||||||
|
): PaginationList<Status, Long>
|
||||||
}
|
}
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
|
@ -51,6 +65,13 @@ class TimelineApiServiceImpl(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override suspend fun publicTimeline(
|
||||||
|
localOnly: Boolean,
|
||||||
|
remoteOnly: Boolean,
|
||||||
|
mediaOnly: Boolean,
|
||||||
|
page: Page
|
||||||
|
): PaginationList<Status, Long> = generateTimelineService.getTimeline(forUserId = 0, localOnly, mediaOnly, page)
|
||||||
|
|
||||||
override suspend fun homeTimeline(
|
override suspend fun homeTimeline(
|
||||||
userId: Long,
|
userId: Long,
|
||||||
maxId: Long?,
|
maxId: Long?,
|
||||||
|
@ -66,4 +87,7 @@ class TimelineApiServiceImpl(
|
||||||
limit = limit
|
limit = limit
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override suspend fun homeTimeline(userId: Long, page: Page): PaginationList<Status, Long> =
|
||||||
|
generateTimelineService.getTimeline(forUserId = userId, page = page)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue