diff --git a/src/main/kotlin/dev/usbharu/hideout/controller/mastodon/MastodonTimelineApiController.kt b/src/main/kotlin/dev/usbharu/hideout/controller/mastodon/MastodonTimelineApiController.kt index 03f3ace8..5d7b1bdb 100644 --- a/src/main/kotlin/dev/usbharu/hideout/controller/mastodon/MastodonTimelineApiController.kt +++ b/src/main/kotlin/dev/usbharu/hideout/controller/mastodon/MastodonTimelineApiController.kt @@ -2,18 +2,31 @@ package dev.usbharu.hideout.controller.mastodon import dev.usbharu.hideout.controller.mastodon.generated.TimelineApi 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.security.core.context.SecurityContextHolder +import org.springframework.security.oauth2.jwt.Jwt import org.springframework.stereotype.Controller @Controller -class MastodonTimelineApiController : TimelineApi { +class MastodonTimelineApiController(private val timelineApiService: TimelineApiService) : TimelineApi { override fun apiV1TimelinesHomeGet( maxId: String?, sinceId: String?, minId: String?, limit: Int? - ): ResponseEntity> { - + ): ResponseEntity> = runBlocking { + val jwt = SecurityContextHolder.getContext().authentication.principal as Jwt + val homeTimeline = timelineApiService.homeTimeline( + userId = jwt.getClaim("uid").toLong(), + maxId = maxId?.toLongOrNull(), + minId = minId?.toLongOrNull(), + sinceId = sinceId?.toLongOrNull(), + limit = limit ?: 20 + ) + ResponseEntity(homeTimeline, HttpStatus.OK) } override fun apiV1TimelinesPublicGet( @@ -24,7 +37,16 @@ class MastodonTimelineApiController : TimelineApi { sinceId: String?, minId: String?, limit: Int? - ): ResponseEntity> { - + ): ResponseEntity> = 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) } } diff --git a/src/main/kotlin/dev/usbharu/hideout/query/mastodon/StatusQueryServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/query/mastodon/StatusQueryServiceImpl.kt index fb0cf012..09d0c4a5 100644 --- a/src/main/kotlin/dev/usbharu/hideout/query/mastodon/StatusQueryServiceImpl.kt +++ b/src/main/kotlin/dev/usbharu/hideout/query/mastodon/StatusQueryServiceImpl.kt @@ -6,8 +6,10 @@ import dev.usbharu.hideout.repository.Posts import dev.usbharu.hideout.repository.Users import org.jetbrains.exposed.sql.innerJoin import org.jetbrains.exposed.sql.select +import org.springframework.stereotype.Repository import java.time.Instant +@Repository class StatusQueryServiceImpl : StatusQueryService { override suspend fun findByPostIds(ids: List): List { diff --git a/src/main/kotlin/dev/usbharu/hideout/repository/MongoTimelineRepository.kt b/src/main/kotlin/dev/usbharu/hideout/repository/MongoTimelineRepository.kt index 2e92c7f4..96a69f36 100644 --- a/src/main/kotlin/dev/usbharu/hideout/repository/MongoTimelineRepository.kt +++ b/src/main/kotlin/dev/usbharu/hideout/repository/MongoTimelineRepository.kt @@ -7,7 +7,7 @@ import org.springframework.data.mongodb.repository.MongoRepository interface MongoTimelineRepository : MongoRepository { fun findByUserId(id: Long): List fun findByUserIdAndTimelineId(userId: Long, timelineId: Long): List - fun findByUserIdAndTimelineIdAndPostIdBetweenAndLocal( + fun findByUserIdAndTimelineIdAndPostIdBetweenAndIsLocal( userId: Long?, timelineId: Long?, postIdMin: Long?, diff --git a/src/main/kotlin/dev/usbharu/hideout/service/api/mastodon/TimelineApiService.kt b/src/main/kotlin/dev/usbharu/hideout/service/api/mastodon/TimelineApiService.kt new file mode 100644 index 00000000..f27dcd8a --- /dev/null +++ b/src/main/kotlin/dev/usbharu/hideout/service/api/mastodon/TimelineApiService.kt @@ -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 + + suspend fun homeTimeline( + userId: Long, + maxId: Long?, + minId: Long?, + sinceId: Long?, + limit: Int = 20 + ): List +} + + +@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 = 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 = transaction.transaction { + generateTimelineService.getTimeline( + forUserId = userId, + localOnly = false, + mediaOnly = false, + maxId = maxId, + minId = minId, + sinceId = sinceId, + limit = limit + ) + } +} diff --git a/src/main/kotlin/dev/usbharu/hideout/service/post/MongoGenerateTimelineService.kt b/src/main/kotlin/dev/usbharu/hideout/service/post/MongoGenerateTimelineService.kt index 8f1b7b33..80ecf75e 100644 --- a/src/main/kotlin/dev/usbharu/hideout/service/post/MongoGenerateTimelineService.kt +++ b/src/main/kotlin/dev/usbharu/hideout/service/post/MongoGenerateTimelineService.kt @@ -6,7 +6,9 @@ import dev.usbharu.hideout.repository.MongoTimelineRepository import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext import org.springframework.data.domain.Pageable +import org.springframework.stereotype.Service +@Service class MongoGenerateTimelineService( private val mongoTimelineRepository: MongoTimelineRepository, private val statusQueryService: StatusQueryService @@ -23,7 +25,7 @@ class MongoGenerateTimelineService( ): List { val timelines = withContext(Dispatchers.IO) { - mongoTimelineRepository.findByUserIdAndTimelineIdAndPostIdBetweenAndLocal( + mongoTimelineRepository.findByUserIdAndTimelineIdAndPostIdBetweenAndIsLocal( forUserId, 0, maxId, minId, localOnly, Pageable.ofSize(limit) ) }