feat: Timelineのエンドポイントを作成

This commit is contained in:
usbharu 2023-09-29 18:14:42 +09:00
parent d9fed726fb
commit 8b93e929dc
5 changed files with 104 additions and 7 deletions

View File

@ -2,18 +2,31 @@ package dev.usbharu.hideout.controller.mastodon
import dev.usbharu.hideout.controller.mastodon.generated.TimelineApi import dev.usbharu.hideout.controller.mastodon.generated.TimelineApi
import dev.usbharu.hideout.domain.mastodon.model.generated.Status import dev.usbharu.hideout.domain.mastodon.model.generated.Status
import dev.usbharu.hideout.service.api.mastodon.TimelineApiService
import kotlinx.coroutines.runBlocking
import org.springframework.http.HttpStatus
import org.springframework.http.ResponseEntity import org.springframework.http.ResponseEntity
import org.springframework.security.core.context.SecurityContextHolder
import org.springframework.security.oauth2.jwt.Jwt
import org.springframework.stereotype.Controller import org.springframework.stereotype.Controller
@Controller @Controller
class MastodonTimelineApiController : TimelineApi { class MastodonTimelineApiController(private val timelineApiService: TimelineApiService) : TimelineApi {
override fun apiV1TimelinesHomeGet( override fun apiV1TimelinesHomeGet(
maxId: String?, maxId: String?,
sinceId: String?, sinceId: String?,
minId: String?, minId: String?,
limit: Int? limit: Int?
): ResponseEntity<List<Status>> { ): ResponseEntity<List<Status>> = runBlocking {
val jwt = SecurityContextHolder.getContext().authentication.principal as Jwt
val homeTimeline = timelineApiService.homeTimeline(
userId = jwt.getClaim<String>("uid").toLong(),
maxId = maxId?.toLongOrNull(),
minId = minId?.toLongOrNull(),
sinceId = sinceId?.toLongOrNull(),
limit = limit ?: 20
)
ResponseEntity(homeTimeline, HttpStatus.OK)
} }
override fun apiV1TimelinesPublicGet( override fun apiV1TimelinesPublicGet(
@ -24,7 +37,16 @@ class MastodonTimelineApiController : TimelineApi {
sinceId: String?, sinceId: String?,
minId: String?, minId: String?,
limit: Int? limit: Int?
): ResponseEntity<List<Status>> { ): ResponseEntity<List<Status>> = runBlocking {
val publicTimeline = timelineApiService.publicTimeline(
localOnly = local ?: false,
remoteOnly = remote ?: false,
mediaOnly = onlyMedia ?: false,
maxId = maxId?.toLongOrNull(),
minId = minId?.toLongOrNull(),
sinceId = sinceId?.toLongOrNull(),
limit = limit ?: 20
)
ResponseEntity(publicTimeline, HttpStatus.OK)
} }
} }

View File

@ -6,8 +6,10 @@ import dev.usbharu.hideout.repository.Posts
import dev.usbharu.hideout.repository.Users import dev.usbharu.hideout.repository.Users
import org.jetbrains.exposed.sql.innerJoin import org.jetbrains.exposed.sql.innerJoin
import org.jetbrains.exposed.sql.select import org.jetbrains.exposed.sql.select
import org.springframework.stereotype.Repository
import java.time.Instant import java.time.Instant
@Repository
class StatusQueryServiceImpl : StatusQueryService { class StatusQueryServiceImpl : StatusQueryService {
override suspend fun findByPostIds(ids: List<Long>): List<Status> { override suspend fun findByPostIds(ids: List<Long>): List<Status> {

View File

@ -7,7 +7,7 @@ import org.springframework.data.mongodb.repository.MongoRepository
interface MongoTimelineRepository : MongoRepository<Timeline, Long> { interface MongoTimelineRepository : MongoRepository<Timeline, Long> {
fun findByUserId(id: Long): List<Timeline> fun findByUserId(id: Long): List<Timeline>
fun findByUserIdAndTimelineId(userId: Long, timelineId: Long): List<Timeline> fun findByUserIdAndTimelineId(userId: Long, timelineId: Long): List<Timeline>
fun findByUserIdAndTimelineIdAndPostIdBetweenAndLocal( fun findByUserIdAndTimelineIdAndPostIdBetweenAndIsLocal(
userId: Long?, userId: Long?,
timelineId: Long?, timelineId: Long?,
postIdMin: Long?, postIdMin: Long?,

View File

@ -0,0 +1,71 @@
package dev.usbharu.hideout.service.api.mastodon
import dev.usbharu.hideout.domain.mastodon.model.generated.Status
import dev.usbharu.hideout.service.core.Transaction
import dev.usbharu.hideout.service.post.GenerateTimelineService
import org.springframework.stereotype.Service
interface TimelineApiService {
suspend fun publicTimeline(
localOnly: Boolean = false,
remoteOnly: Boolean = false,
mediaOnly: Boolean = false,
maxId: Long?,
minId: Long?,
sinceId: Long?,
limit: Int = 20
): List<Status>
suspend fun homeTimeline(
userId: Long,
maxId: Long?,
minId: Long?,
sinceId: Long?,
limit: Int = 20
): List<Status>
}
@Service
class TimelineApiServiceImpl(
private val generateTimelineService: GenerateTimelineService,
private val transaction: Transaction
) : TimelineApiService {
override suspend fun publicTimeline(
localOnly: Boolean,
remoteOnly: Boolean,
mediaOnly: Boolean,
maxId: Long?,
minId: Long?,
sinceId: Long?,
limit: Int
): List<Status> = transaction.transaction {
generateTimelineService.getTimeline(
forUserId = null,
localOnly = localOnly,
mediaOnly = mediaOnly,
maxId = maxId,
minId = minId,
sinceId = sinceId,
limit = limit
)
}
override suspend fun homeTimeline(
userId: Long,
maxId: Long?,
minId: Long?,
sinceId: Long?,
limit: Int
): List<Status> = transaction.transaction {
generateTimelineService.getTimeline(
forUserId = userId,
localOnly = false,
mediaOnly = false,
maxId = maxId,
minId = minId,
sinceId = sinceId,
limit = limit
)
}
}

View File

@ -6,7 +6,9 @@ import dev.usbharu.hideout.repository.MongoTimelineRepository
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import org.springframework.data.domain.Pageable import org.springframework.data.domain.Pageable
import org.springframework.stereotype.Service
@Service
class MongoGenerateTimelineService( class MongoGenerateTimelineService(
private val mongoTimelineRepository: MongoTimelineRepository, private val mongoTimelineRepository: MongoTimelineRepository,
private val statusQueryService: StatusQueryService private val statusQueryService: StatusQueryService
@ -23,7 +25,7 @@ class MongoGenerateTimelineService(
): List<Status> { ): List<Status> {
val timelines = val timelines =
withContext(Dispatchers.IO) { withContext(Dispatchers.IO) {
mongoTimelineRepository.findByUserIdAndTimelineIdAndPostIdBetweenAndLocal( mongoTimelineRepository.findByUserIdAndTimelineIdAndPostIdBetweenAndIsLocal(
forUserId, 0, maxId, minId, localOnly, Pageable.ofSize(limit) forUserId, 0, maxId, minId, localOnly, Pageable.ofSize(limit)
) )
} }