mirror of https://github.com/usbharu/Hideout.git
commit
9a12c10f3a
|
@ -0,0 +1,146 @@
|
|||
package mastodon.account
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference
|
||||
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
|
||||
import dev.usbharu.hideout.SpringApplication
|
||||
import dev.usbharu.hideout.domain.mastodon.model.generated.Notification
|
||||
import dev.usbharu.hideout.domain.mastodon.model.generated.Status
|
||||
import org.assertj.core.api.Assertions
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.flywaydb.core.Flyway
|
||||
import org.junit.jupiter.api.AfterAll
|
||||
import org.junit.jupiter.api.BeforeEach
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.springframework.beans.factory.annotation.Autowired
|
||||
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc
|
||||
import org.springframework.boot.test.context.SpringBootTest
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority
|
||||
import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors
|
||||
import org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers
|
||||
import org.springframework.test.context.jdbc.Sql
|
||||
import org.springframework.test.web.servlet.MockMvc
|
||||
import org.springframework.test.web.servlet.get
|
||||
import org.springframework.test.web.servlet.setup.DefaultMockMvcBuilder
|
||||
import org.springframework.test.web.servlet.setup.MockMvcBuilders
|
||||
import org.springframework.transaction.annotation.Transactional
|
||||
import org.springframework.web.context.WebApplicationContext
|
||||
|
||||
@SpringBootTest(classes = [SpringApplication::class])
|
||||
@AutoConfigureMockMvc
|
||||
@Transactional
|
||||
@Sql("/sql/test-user.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_CLASS)
|
||||
@Sql("/sql/test-user2.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_CLASS)
|
||||
@Sql("/sql/accounts/test-accounts-statuses.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_CLASS)
|
||||
class AccountApiPaginationTest {
|
||||
@Autowired
|
||||
private lateinit var context: WebApplicationContext
|
||||
|
||||
private lateinit var mockMvc: MockMvc
|
||||
|
||||
@Test
|
||||
fun `apiV1AccountsIdStatusesGet 投稿を取得できる`() {
|
||||
val content = mockMvc
|
||||
.get("/api/v1/accounts/1/statuses"){
|
||||
with(
|
||||
SecurityMockMvcRequestPostProcessors.jwt()
|
||||
.jwt { it.claim("uid", "1") }.authorities(SimpleGrantedAuthority("SCOPE_read"))
|
||||
)
|
||||
}
|
||||
.asyncDispatch()
|
||||
.andExpect { status { isOk() } }
|
||||
.andExpect { header { string("Link","<https://example.com/api/v1/accounts/1/statuses?min_id=100>; rel=\"next\", <https://example.com/api/v1/accounts/1/statuses?max_id=81>; rel=\"prev\"") } }
|
||||
.andReturn()
|
||||
.response
|
||||
.contentAsString
|
||||
|
||||
val value = jacksonObjectMapper().readValue(content, object : TypeReference<List<Status>>() {})
|
||||
|
||||
assertThat(value.first().id).isEqualTo("100")
|
||||
assertThat(value.last().id).isEqualTo("81")
|
||||
assertThat(value).size().isEqualTo(20)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `apiV1AccountsIdStatusesGet 結果が0件のときはLinkヘッダーがない`() {
|
||||
val content = mockMvc
|
||||
.get("/api/v1/accounts/1/statuses?min_id=100"){
|
||||
with(
|
||||
SecurityMockMvcRequestPostProcessors.jwt()
|
||||
.jwt { it.claim("uid", "1") }.authorities(SimpleGrantedAuthority("SCOPE_read"))
|
||||
)
|
||||
}
|
||||
.asyncDispatch()
|
||||
.andExpect { status { isOk() } }
|
||||
.andExpect { header { doesNotExist("Link") } }
|
||||
.andReturn()
|
||||
.response
|
||||
.contentAsString
|
||||
|
||||
val value = jacksonObjectMapper().readValue(content, object : TypeReference<List<Status>>() {})
|
||||
|
||||
|
||||
assertThat(value).isEmpty()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `apiV1AccountsIdStatusesGet maxIdを指定して取得`() {
|
||||
val content = mockMvc
|
||||
.get("/api/v1/accounts/1/statuses?max_id=100"){
|
||||
with(
|
||||
SecurityMockMvcRequestPostProcessors.jwt()
|
||||
.jwt { it.claim("uid", "1") }.authorities(SimpleGrantedAuthority("SCOPE_read"))
|
||||
)
|
||||
}
|
||||
.asyncDispatch()
|
||||
.andExpect { status { isOk() } }
|
||||
.andExpect { header { string("Link","<https://example.com/api/v1/accounts/1/statuses?min_id=99>; rel=\"next\", <https://example.com/api/v1/accounts/1/statuses?max_id=80>; rel=\"prev\"") } }
|
||||
.andReturn()
|
||||
.response
|
||||
.contentAsString
|
||||
|
||||
val value = jacksonObjectMapper().readValue(content, object : TypeReference<List<Status>>() {})
|
||||
|
||||
assertThat(value.first().id).isEqualTo("99")
|
||||
assertThat(value.last().id).isEqualTo("80")
|
||||
assertThat(value).size().isEqualTo(20)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `apiV1AccountsIdStatusesGet minIdを指定して取得`() {
|
||||
val content = mockMvc
|
||||
.get("/api/v1/accounts/1/statuses?min_id=1"){
|
||||
with(
|
||||
SecurityMockMvcRequestPostProcessors.jwt()
|
||||
.jwt { it.claim("uid", "1") }.authorities(SimpleGrantedAuthority("SCOPE_read"))
|
||||
)
|
||||
}
|
||||
.asyncDispatch()
|
||||
.andExpect { status { isOk() } }
|
||||
.andExpect { header { string("Link","<https://example.com/api/v1/accounts/1/statuses?min_id=21>; rel=\"next\", <https://example.com/api/v1/accounts/1/statuses?max_id=2>; rel=\"prev\"") } }
|
||||
.andReturn()
|
||||
.response
|
||||
.contentAsString
|
||||
|
||||
val value = jacksonObjectMapper().readValue(content, object : TypeReference<List<Status>>() {})
|
||||
|
||||
assertThat(value.first().id).isEqualTo("21")
|
||||
assertThat(value.last().id).isEqualTo("2")
|
||||
assertThat(value).size().isEqualTo(20)
|
||||
}
|
||||
|
||||
@BeforeEach
|
||||
fun setUp() {
|
||||
mockMvc = MockMvcBuilders.webAppContextSetup(context)
|
||||
.apply<DefaultMockMvcBuilder>(SecurityMockMvcConfigurers.springSecurity())
|
||||
.build()
|
||||
}
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
@AfterAll
|
||||
fun dropDatabase(@Autowired flyway: Flyway) {
|
||||
flyway.clean()
|
||||
flyway.migrate()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,164 @@
|
|||
package mastodon.notifications
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference
|
||||
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
|
||||
import dev.usbharu.hideout.SpringApplication
|
||||
import dev.usbharu.hideout.domain.mastodon.model.generated.Notification
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.flywaydb.core.Flyway
|
||||
import org.junit.jupiter.api.AfterAll
|
||||
import org.junit.jupiter.api.BeforeEach
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.springframework.beans.factory.annotation.Autowired
|
||||
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc
|
||||
import org.springframework.boot.test.context.SpringBootTest
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority
|
||||
import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors
|
||||
import org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers
|
||||
import org.springframework.test.context.jdbc.Sql
|
||||
import org.springframework.test.web.servlet.MockMvc
|
||||
import org.springframework.test.web.servlet.get
|
||||
import org.springframework.test.web.servlet.setup.DefaultMockMvcBuilder
|
||||
import org.springframework.test.web.servlet.setup.MockMvcBuilders
|
||||
import org.springframework.transaction.annotation.Transactional
|
||||
import org.springframework.web.context.WebApplicationContext
|
||||
|
||||
@SpringBootTest(classes = [SpringApplication::class], properties = ["hideout.use-mongodb=false"])
|
||||
@AutoConfigureMockMvc
|
||||
@Transactional
|
||||
@Sql("/sql/test-user.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_CLASS)
|
||||
@Sql("/sql/test-user2.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_CLASS)
|
||||
@Sql("/sql/notification/test-notifications.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_CLASS)
|
||||
@Sql("/sql/notification/test-mastodon_notifications.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_CLASS)
|
||||
class ExposedNotificationsApiPaginationTest {
|
||||
@Autowired
|
||||
private lateinit var context: WebApplicationContext
|
||||
|
||||
private lateinit var mockMvc: MockMvc
|
||||
|
||||
@Test
|
||||
fun `通知を取得できる`() = runTest {
|
||||
val content = mockMvc
|
||||
.get("/api/v1/notifications") {
|
||||
with(
|
||||
SecurityMockMvcRequestPostProcessors.jwt()
|
||||
.jwt { it.claim("uid", "1") }.authorities(SimpleGrantedAuthority("SCOPE_read"))
|
||||
)
|
||||
}
|
||||
.asyncDispatch()
|
||||
.andExpect {
|
||||
header {
|
||||
string(
|
||||
"Link",
|
||||
"<https://example.com/api/v1/notifications?min_id=65>; rel=\"next\", <https://example.com/api/v1/notifications?max_id=26>; rel=\"prev\""
|
||||
)
|
||||
}
|
||||
}
|
||||
.andReturn()
|
||||
.response
|
||||
.contentAsString
|
||||
|
||||
val value = jacksonObjectMapper().readValue(content, object : TypeReference<List<Notification>>() {})
|
||||
|
||||
assertThat(value.first().id).isEqualTo("65")
|
||||
assertThat(value.last().id).isEqualTo("26")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun maxIdを指定して通知を取得できる() = runTest {
|
||||
val content = mockMvc
|
||||
.get("/api/v1/notifications?max_id=26") {
|
||||
with(
|
||||
SecurityMockMvcRequestPostProcessors.jwt()
|
||||
.jwt { it.claim("uid", "1") }.authorities(SimpleGrantedAuthority("SCOPE_read"))
|
||||
)
|
||||
}
|
||||
.asyncDispatch()
|
||||
.andExpect {
|
||||
header {
|
||||
string(
|
||||
"Link",
|
||||
"<https://example.com/api/v1/notifications?min_id=25>; rel=\"next\", <https://example.com/api/v1/notifications?max_id=1>; rel=\"prev\""
|
||||
)
|
||||
}
|
||||
}
|
||||
.andReturn()
|
||||
.response
|
||||
.contentAsString
|
||||
|
||||
val value = jacksonObjectMapper().readValue(content, object : TypeReference<List<Notification>>() {})
|
||||
|
||||
assertThat(value.first().id).isEqualTo("25")
|
||||
assertThat(value.last().id).isEqualTo("1")
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
fun minIdを指定して通知を取得できる() = runTest {
|
||||
val content = mockMvc
|
||||
.get("/api/v1/notifications?min_id=25") {
|
||||
with(
|
||||
SecurityMockMvcRequestPostProcessors.jwt()
|
||||
.jwt { it.claim("uid", "1") }.authorities(SimpleGrantedAuthority("SCOPE_read"))
|
||||
)
|
||||
}
|
||||
.asyncDispatch()
|
||||
.andExpect {
|
||||
header {
|
||||
string(
|
||||
"Link",
|
||||
"<https://example.com/api/v1/notifications?min_id=65>; rel=\"next\", <https://example.com/api/v1/notifications?max_id=26>; rel=\"prev\""
|
||||
)
|
||||
}
|
||||
}
|
||||
.andReturn()
|
||||
.response
|
||||
.contentAsString
|
||||
|
||||
val value = jacksonObjectMapper().readValue(content, object : TypeReference<List<Notification>>() {})
|
||||
|
||||
assertThat(value.first().id).isEqualTo("65")
|
||||
assertThat(value.last().id).isEqualTo("26")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun 結果が0件のときはページネーションのヘッダーがない() = runTest {
|
||||
val content = mockMvc
|
||||
.get("/api/v1/notifications?max_id=1") {
|
||||
with(
|
||||
SecurityMockMvcRequestPostProcessors.jwt()
|
||||
.jwt { it.claim("uid", "1") }.authorities(SimpleGrantedAuthority("SCOPE_read"))
|
||||
)
|
||||
}
|
||||
.asyncDispatch()
|
||||
.andExpect {
|
||||
header {
|
||||
doesNotExist("Link")
|
||||
}
|
||||
}
|
||||
.andReturn()
|
||||
.response
|
||||
.contentAsString
|
||||
|
||||
val value = jacksonObjectMapper().readValue(content, object : TypeReference<List<Notification>>() {})
|
||||
|
||||
assertThat(value).size().isZero()
|
||||
}
|
||||
|
||||
@BeforeEach
|
||||
fun setUp() {
|
||||
mockMvc = MockMvcBuilders.webAppContextSetup(context)
|
||||
.apply<DefaultMockMvcBuilder>(SecurityMockMvcConfigurers.springSecurity())
|
||||
.build()
|
||||
}
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
@AfterAll
|
||||
fun dropDatabase(@Autowired flyway: Flyway) {
|
||||
flyway.clean()
|
||||
flyway.migrate()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,199 @@
|
|||
package mastodon.notifications
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference
|
||||
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
|
||||
import dev.usbharu.hideout.SpringApplication
|
||||
import dev.usbharu.hideout.domain.mastodon.model.generated.Notification
|
||||
import dev.usbharu.hideout.mastodon.domain.model.MastodonNotification
|
||||
import dev.usbharu.hideout.mastodon.domain.model.NotificationType
|
||||
import dev.usbharu.hideout.mastodon.infrastructure.mongorepository.MongoMastodonNotificationRepository
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.assertj.core.api.Assertions
|
||||
import org.flywaydb.core.Flyway
|
||||
import org.junit.jupiter.api.AfterAll
|
||||
import org.junit.jupiter.api.BeforeAll
|
||||
import org.junit.jupiter.api.BeforeEach
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.springframework.beans.factory.annotation.Autowired
|
||||
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc
|
||||
import org.springframework.boot.test.context.SpringBootTest
|
||||
import org.springframework.data.mongodb.core.MongoTemplate
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority
|
||||
import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors
|
||||
import org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers
|
||||
import org.springframework.test.context.jdbc.Sql
|
||||
import org.springframework.test.web.servlet.MockMvc
|
||||
import org.springframework.test.web.servlet.get
|
||||
import org.springframework.test.web.servlet.setup.DefaultMockMvcBuilder
|
||||
import org.springframework.test.web.servlet.setup.MockMvcBuilders
|
||||
import org.springframework.transaction.annotation.Transactional
|
||||
import org.springframework.web.context.WebApplicationContext
|
||||
import java.time.Instant
|
||||
|
||||
@SpringBootTest(classes = [SpringApplication::class], properties = ["hideout.use-mongodb=true"])
|
||||
@AutoConfigureMockMvc
|
||||
@Transactional
|
||||
@Sql("/sql/test-user.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_CLASS)
|
||||
@Sql("/sql/test-user2.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_CLASS)
|
||||
@Sql("/sql/notification/test-notifications.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_CLASS)
|
||||
class MongodbNotificationsApiPaginationTest {
|
||||
@Autowired
|
||||
private lateinit var context: WebApplicationContext
|
||||
|
||||
private lateinit var mockMvc: MockMvc
|
||||
|
||||
@Test
|
||||
fun `通知を取得できる`() = runTest {
|
||||
val content = mockMvc
|
||||
.get("/api/v1/notifications") {
|
||||
with(
|
||||
SecurityMockMvcRequestPostProcessors.jwt()
|
||||
.jwt { it.claim("uid", "1") }.authorities(SimpleGrantedAuthority("SCOPE_read"))
|
||||
)
|
||||
}
|
||||
.asyncDispatch()
|
||||
.andDo { print() }
|
||||
.andExpect {
|
||||
header {
|
||||
string(
|
||||
"Link",
|
||||
"<https://example.com/api/v1/notifications?min_id=65>; rel=\"next\", <https://example.com/api/v1/notifications?max_id=26>; rel=\"prev\""
|
||||
)
|
||||
}
|
||||
}
|
||||
.andReturn()
|
||||
.response
|
||||
.contentAsString
|
||||
|
||||
val value = jacksonObjectMapper().readValue(content, object : TypeReference<List<Notification>>() {})
|
||||
|
||||
Assertions.assertThat(value.first().id).isEqualTo("65")
|
||||
Assertions.assertThat(value.last().id).isEqualTo("26")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun maxIdを指定して通知を取得できる() = runTest {
|
||||
val content = mockMvc
|
||||
.get("/api/v1/notifications?max_id=26") {
|
||||
with(
|
||||
SecurityMockMvcRequestPostProcessors.jwt()
|
||||
.jwt { it.claim("uid", "1") }.authorities(SimpleGrantedAuthority("SCOPE_read"))
|
||||
)
|
||||
}
|
||||
.asyncDispatch()
|
||||
.andExpect {
|
||||
header {
|
||||
string(
|
||||
"Link",
|
||||
"<https://example.com/api/v1/notifications?min_id=25>; rel=\"next\", <https://example.com/api/v1/notifications?max_id=1>; rel=\"prev\""
|
||||
)
|
||||
}
|
||||
}
|
||||
.andReturn()
|
||||
.response
|
||||
.contentAsString
|
||||
|
||||
val value = jacksonObjectMapper().readValue(content, object : TypeReference<List<Notification>>() {})
|
||||
|
||||
Assertions.assertThat(value.first().id).isEqualTo("25")
|
||||
Assertions.assertThat(value.last().id).isEqualTo("1")
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
fun minIdを指定して通知を取得できる() = runTest {
|
||||
val content = mockMvc
|
||||
.get("/api/v1/notifications?min_id=25") {
|
||||
with(
|
||||
SecurityMockMvcRequestPostProcessors.jwt()
|
||||
.jwt { it.claim("uid", "1") }.authorities(SimpleGrantedAuthority("SCOPE_read"))
|
||||
)
|
||||
}
|
||||
.asyncDispatch()
|
||||
.andExpect {
|
||||
header {
|
||||
string(
|
||||
"Link",
|
||||
"<https://example.com/api/v1/notifications?min_id=65>; rel=\"next\", <https://example.com/api/v1/notifications?max_id=26>; rel=\"prev\""
|
||||
)
|
||||
}
|
||||
}
|
||||
.andReturn()
|
||||
.response
|
||||
.contentAsString
|
||||
|
||||
val value = jacksonObjectMapper().readValue(content, object : TypeReference<List<Notification>>() {})
|
||||
|
||||
Assertions.assertThat(value.first().id).isEqualTo("65")
|
||||
Assertions.assertThat(value.last().id).isEqualTo("26")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun 結果が0件のときはページネーションのヘッダーがない() = runTest {
|
||||
val content = mockMvc
|
||||
.get("/api/v1/notifications?max_id=1") {
|
||||
with(
|
||||
SecurityMockMvcRequestPostProcessors.jwt()
|
||||
.jwt { it.claim("uid", "1") }.authorities(SimpleGrantedAuthority("SCOPE_read"))
|
||||
)
|
||||
}
|
||||
.asyncDispatch()
|
||||
.andExpect {
|
||||
header {
|
||||
doesNotExist("Link")
|
||||
}
|
||||
}
|
||||
.andReturn()
|
||||
.response
|
||||
.contentAsString
|
||||
|
||||
val value = jacksonObjectMapper().readValue(content, object : TypeReference<List<Notification>>() {})
|
||||
|
||||
Assertions.assertThat(value).size().isZero()
|
||||
}
|
||||
|
||||
@BeforeEach
|
||||
fun setUp() {
|
||||
mockMvc = MockMvcBuilders.webAppContextSetup(context)
|
||||
.apply<DefaultMockMvcBuilder>(SecurityMockMvcConfigurers.springSecurity())
|
||||
.build()
|
||||
}
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
@BeforeAll
|
||||
fun setupMongodb(
|
||||
@Autowired mongoMastodonNotificationRepository: MongoMastodonNotificationRepository
|
||||
) {
|
||||
|
||||
mongoMastodonNotificationRepository.deleteAll()
|
||||
|
||||
val notifications = (1..65).map {
|
||||
MastodonNotification(
|
||||
it.toLong(),
|
||||
1,
|
||||
NotificationType.follow,
|
||||
Instant.now(),
|
||||
2,
|
||||
null,
|
||||
null,
|
||||
null
|
||||
)
|
||||
}
|
||||
|
||||
mongoMastodonNotificationRepository.saveAll(notifications)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
@AfterAll
|
||||
fun dropDatabase(
|
||||
@Autowired flyway: Flyway,
|
||||
@Autowired mongodbMastodonNotificationRepository: MongoMastodonNotificationRepository
|
||||
) {
|
||||
flyway.clean()
|
||||
flyway.migrate()
|
||||
|
||||
mongodbMastodonNotificationRepository.deleteAll()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -24,7 +24,7 @@ spring:
|
|||
auto-index-creation: true
|
||||
host: localhost
|
||||
port: 27017
|
||||
database: hideout
|
||||
database: hideout-integration-test
|
||||
h2:
|
||||
console:
|
||||
enabled: true
|
||||
|
|
|
@ -0,0 +1,202 @@
|
|||
insert into posts (id, actor_id, overview, content, text, created_at, visibility, url, repost_id, reply_id, sensitive,
|
||||
ap_id, deleted)
|
||||
VALUES (1, 1, null, '<p>this is test</p>', 'this is test', 1706684146436, 0, 'https://example.com/users/1/posts/1',
|
||||
null, null, false, 'https://example.com/users/1/posts/1', false),
|
||||
(2, 1, null, '<p>this is test</p>', 'this is test', 1706684146436, 0, 'https://example.com/users/1/posts/2',
|
||||
null, 1, false, 'https://example.com/users/1/posts/2', false),
|
||||
(3, 1, null, '<p>this is test</p>', 'this is test', 1706684146436, 2, 'https://example.com/users/1/posts/3',
|
||||
null, null, false, 'https://example.com/users/1/posts/3', false),
|
||||
(4, 1, null, '<p>this is test</p>', 'this is test', 1706684146436, 0, 'https://example.com/users/1/posts/4',
|
||||
null, 3, false, 'https://example.com/users/1/posts/4', false),
|
||||
(5, 1, null, '<p>this is test</p>', 'this is test', 1706684146436, 0, 'https://example.com/users/1/posts/5',
|
||||
null, null, false, 'https://example.com/users/1/posts/5', false),
|
||||
(6, 1, null, '<p>this is test</p>', 'this is test', 1706684146436, 2, 'https://example.com/users/1/posts/6',
|
||||
null, null, false, 'https://example.com/users/1/posts/6', false),
|
||||
(7, 1, null, '<p>this is test</p>', 'this is test', 1706684146436, 0, 'https://example.com/users/1/posts/7',
|
||||
null, null, false, 'https://example.com/users/1/posts/7', false),
|
||||
(8, 1, null, '<p>this is test</p>', 'this is test', 1706684146436, 0, 'https://example.com/users/1/posts/8',
|
||||
null, 7, false, 'https://example.com/users/1/posts/8', false),
|
||||
(9, 1, null, '<p>this is test</p>', 'this is test', 1706684146436, 2, 'https://example.com/users/1/posts/9',
|
||||
null, null, false, 'https://example.com/users/1/posts/9', false),
|
||||
(10, 1, null, '<p>this is test</p>', 'this is test', 1706684146436, 0, 'https://example.com/users/1/posts/10',
|
||||
null, 9, false, 'https://example.com/users/1/posts/10', false),
|
||||
(11, 1, null, '<p>this is test</p>', 'this is test', 1706684146436, 0, 'https://example.com/users/1/posts/11',
|
||||
null, null, false, 'https://example.com/users/1/posts/11', false),
|
||||
(12, 1, null, '<p>this is test</p>', 'this is test', 1706684146436, 2, 'https://example.com/users/1/posts/12',
|
||||
null, null, false, 'https://example.com/users/1/posts/12', false),
|
||||
(13, 1, null, '<p>this is test</p>', 'this is test', 1706684146436, 0, 'https://example.com/users/1/posts/13',
|
||||
null, null, false, 'https://example.com/users/1/posts/13', false),
|
||||
(14, 1, null, '<p>this is test</p>', 'this is test', 1706684146436, 0, 'https://example.com/users/1/posts/14',
|
||||
null, 13, false, 'https://example.com/users/1/posts/14', false),
|
||||
(15, 1, null, '<p>this is test</p>', 'this is test', 1706684146436, 2, 'https://example.com/users/1/posts/15',
|
||||
null, null, false, 'https://example.com/users/1/posts/15', false),
|
||||
(16, 1, null, '<p>this is test</p>', 'this is test', 1706684146436, 0, 'https://example.com/users/1/posts/16',
|
||||
null, 15, false, 'https://example.com/users/1/posts/16', false),
|
||||
(17, 1, null, '<p>this is test</p>', 'this is test', 1706684146436, 0, 'https://example.com/users/1/posts/17',
|
||||
null, null, false, 'https://example.com/users/1/posts/17', false),
|
||||
(18, 1, null, '<p>this is test</p>', 'this is test', 1706684146436, 2, 'https://example.com/users/1/posts/18',
|
||||
null, null, false, 'https://example.com/users/1/posts/18', false),
|
||||
(19, 1, null, '<p>this is test</p>', 'this is test', 1706684146436, 0, 'https://example.com/users/1/posts/19',
|
||||
null, null, false, 'https://example.com/users/1/posts/19', false),
|
||||
(20, 1, null, '<p>this is test</p>', 'this is test', 1706684146436, 0, 'https://example.com/users/1/posts/20',
|
||||
null, 19, false, 'https://example.com/users/1/posts/20', false),
|
||||
(21, 1, null, '<p>this is test</p>', 'this is test', 1706684146436, 2, 'https://example.com/users/1/posts/21',
|
||||
null, null, false, 'https://example.com/users/1/posts/21', false),
|
||||
(22, 1, null, '<p>this is test</p>', 'this is test', 1706684146436, 0, 'https://example.com/users/1/posts/22',
|
||||
null, 21, false, 'https://example.com/users/1/posts/22', false),
|
||||
(23, 1, null, '<p>this is test</p>', 'this is test', 1706684146436, 0, 'https://example.com/users/1/posts/23',
|
||||
null, null, false, 'https://example.com/users/1/posts/23', false),
|
||||
(24, 1, null, '<p>this is test</p>', 'this is test', 1706684146436, 2, 'https://example.com/users/1/posts/24',
|
||||
null, null, false, 'https://example.com/users/1/posts/24', false),
|
||||
(25, 1, null, '<p>this is test</p>', 'this is test', 1706684146436, 0, 'https://example.com/users/1/posts/25',
|
||||
null, null, false, 'https://example.com/users/1/posts/25', false),
|
||||
(26, 1, null, '<p>this is test</p>', 'this is test', 1706684146436, 0, 'https://example.com/users/1/posts/26',
|
||||
null, 25, false, 'https://example.com/users/1/posts/26', false),
|
||||
(27, 1, null, '<p>this is test</p>', 'this is test', 1706684146436, 2, 'https://example.com/users/1/posts/27',
|
||||
null, null, false, 'https://example.com/users/1/posts/27', false),
|
||||
(28, 1, null, '<p>this is test</p>', 'this is test', 1706684146436, 0, 'https://example.com/users/1/posts/28',
|
||||
null, 27, false, 'https://example.com/users/1/posts/28', false),
|
||||
(29, 1, null, '<p>this is test</p>', 'this is test', 1706684146436, 0, 'https://example.com/users/1/posts/29',
|
||||
null, null, false, 'https://example.com/users/1/posts/29', false),
|
||||
(30, 1, null, '<p>this is test</p>', 'this is test', 1706684146436, 2, 'https://example.com/users/1/posts/30',
|
||||
null, null, false, 'https://example.com/users/1/posts/30', false),
|
||||
(31, 1, null, '<p>this is test</p>', 'this is test', 1706684146436, 0, 'https://example.com/users/1/posts/31',
|
||||
null, null, false, 'https://example.com/users/1/posts/31', false),
|
||||
(32, 1, null, '<p>this is test</p>', 'this is test', 1706684146436, 0, 'https://example.com/users/1/posts/32',
|
||||
null, 31, false, 'https://example.com/users/1/posts/32', false),
|
||||
(33, 1, null, '<p>this is test</p>', 'this is test', 1706684146436, 2, 'https://example.com/users/1/posts/33',
|
||||
null, null, false, 'https://example.com/users/1/posts/33', false),
|
||||
(34, 1, null, '<p>this is test</p>', 'this is test', 1706684146436, 0, 'https://example.com/users/1/posts/34',
|
||||
null, 33, false, 'https://example.com/users/1/posts/34', false),
|
||||
(35, 1, null, '<p>this is test</p>', 'this is test', 1706684146436, 0, 'https://example.com/users/1/posts/35',
|
||||
null, null, false, 'https://example.com/users/1/posts/35', false),
|
||||
(36, 1, null, '<p>this is test</p>', 'this is test', 1706684146436, 2, 'https://example.com/users/1/posts/36',
|
||||
null, null, false, 'https://example.com/users/1/posts/36', false),
|
||||
(37, 1, null, '<p>this is test</p>', 'this is test', 1706684146436, 0, 'https://example.com/users/1/posts/37',
|
||||
null, null, false, 'https://example.com/users/1/posts/37', false),
|
||||
(38, 1, null, '<p>this is test</p>', 'this is test', 1706684146436, 0, 'https://example.com/users/1/posts/38',
|
||||
null, 37, false, 'https://example.com/users/1/posts/38', false),
|
||||
(39, 1, null, '<p>this is test</p>', 'this is test', 1706684146436, 2, 'https://example.com/users/1/posts/39',
|
||||
null, null, false, 'https://example.com/users/1/posts/39', false),
|
||||
(40, 1, null, '<p>this is test</p>', 'this is test', 1706684146436, 0, 'https://example.com/users/1/posts/40',
|
||||
null, 39, false, 'https://example.com/users/1/posts/40', false),
|
||||
(41, 1, null, '<p>this is test</p>', 'this is test', 1706684146436, 0, 'https://example.com/users/1/posts/41',
|
||||
null, null, false, 'https://example.com/users/1/posts/41', false),
|
||||
(42, 1, null, '<p>this is test</p>', 'this is test', 1706684146436, 2, 'https://example.com/users/1/posts/42',
|
||||
null, null, false, 'https://example.com/users/1/posts/42', false),
|
||||
(43, 1, null, '<p>this is test</p>', 'this is test', 1706684146436, 0, 'https://example.com/users/1/posts/43',
|
||||
null, null, false, 'https://example.com/users/1/posts/43', false),
|
||||
(44, 1, null, '<p>this is test</p>', 'this is test', 1706684146436, 0, 'https://example.com/users/1/posts/44',
|
||||
null, 43, false, 'https://example.com/users/1/posts/44', false),
|
||||
(45, 1, null, '<p>this is test</p>', 'this is test', 1706684146436, 2, 'https://example.com/users/1/posts/45',
|
||||
null, null, false, 'https://example.com/users/1/posts/45', false),
|
||||
(46, 1, null, '<p>this is test</p>', 'this is test', 1706684146436, 0, 'https://example.com/users/1/posts/46',
|
||||
null, 45, false, 'https://example.com/users/1/posts/46', false),
|
||||
(47, 1, null, '<p>this is test</p>', 'this is test', 1706684146436, 0, 'https://example.com/users/1/posts/47',
|
||||
null, null, false, 'https://example.com/users/1/posts/47', false),
|
||||
(48, 1, null, '<p>this is test</p>', 'this is test', 1706684146436, 2, 'https://example.com/users/1/posts/48',
|
||||
null, null, false, 'https://example.com/users/1/posts/48', false),
|
||||
(49, 1, null, '<p>this is test</p>', 'this is test', 1706684146436, 0, 'https://example.com/users/1/posts/49',
|
||||
null, null, false, 'https://example.com/users/1/posts/49', false),
|
||||
(50, 1, null, '<p>this is test</p>', 'this is test', 1706684146436, 0, 'https://example.com/users/1/posts/50',
|
||||
null, 49, false, 'https://example.com/users/1/posts/50', false),
|
||||
(51, 1, null, '<p>this is test</p>', 'this is test', 1706684146436, 2, 'https://example.com/users/1/posts/51',
|
||||
null, null, false, 'https://example.com/users/1/posts/51', false),
|
||||
(52, 1, null, '<p>this is test</p>', 'this is test', 1706684146436, 0, 'https://example.com/users/1/posts/52',
|
||||
null, 51, false, 'https://example.com/users/1/posts/52', false),
|
||||
(53, 1, null, '<p>this is test</p>', 'this is test', 1706684146436, 0, 'https://example.com/users/1/posts/53',
|
||||
null, null, false, 'https://example.com/users/1/posts/53', false),
|
||||
(54, 1, null, '<p>this is test</p>', 'this is test', 1706684146436, 2, 'https://example.com/users/1/posts/54',
|
||||
null, null, false, 'https://example.com/users/1/posts/54', false),
|
||||
(55, 1, null, '<p>this is test</p>', 'this is test', 1706684146436, 0, 'https://example.com/users/1/posts/55',
|
||||
null, null, false, 'https://example.com/users/1/posts/55', false),
|
||||
(56, 1, null, '<p>this is test</p>', 'this is test', 1706684146436, 0, 'https://example.com/users/1/posts/56',
|
||||
null, 55, false, 'https://example.com/users/1/posts/56', false),
|
||||
(57, 1, null, '<p>this is test</p>', 'this is test', 1706684146436, 2, 'https://example.com/users/1/posts/57',
|
||||
null, null, false, 'https://example.com/users/1/posts/57', false),
|
||||
(58, 1, null, '<p>this is test</p>', 'this is test', 1706684146436, 0, 'https://example.com/users/1/posts/58',
|
||||
null, 57, false, 'https://example.com/users/1/posts/58', false),
|
||||
(59, 1, null, '<p>this is test</p>', 'this is test', 1706684146436, 0, 'https://example.com/users/1/posts/59',
|
||||
null, null, false, 'https://example.com/users/1/posts/59', false),
|
||||
(60, 1, null, '<p>this is test</p>', 'this is test', 1706684146436, 2, 'https://example.com/users/1/posts/60',
|
||||
null, null, false, 'https://example.com/users/1/posts/60', false),
|
||||
(61, 1, null, '<p>this is test</p>', 'this is test', 1706684146436, 0, 'https://example.com/users/1/posts/61',
|
||||
null, null, false, 'https://example.com/users/1/posts/61', false),
|
||||
(62, 1, null, '<p>this is test</p>', 'this is test', 1706684146436, 0, 'https://example.com/users/1/posts/62',
|
||||
null, 61, false, 'https://example.com/users/1/posts/62', false),
|
||||
(63, 1, null, '<p>this is test</p>', 'this is test', 1706684146436, 2, 'https://example.com/users/1/posts/63',
|
||||
null, null, false, 'https://example.com/users/1/posts/63', false),
|
||||
(64, 1, null, '<p>this is test</p>', 'this is test', 1706684146436, 0, 'https://example.com/users/1/posts/64',
|
||||
null, 63, false, 'https://example.com/users/1/posts/64', false),
|
||||
(65, 1, null, '<p>this is test</p>', 'this is test', 1706684146436, 0, 'https://example.com/users/1/posts/65',
|
||||
null, null, false, 'https://example.com/users/1/posts/65', false),
|
||||
(66, 1, null, '<p>this is test</p>', 'this is test', 1706684146436, 2, 'https://example.com/users/1/posts/66',
|
||||
null, null, false, 'https://example.com/users/1/posts/66', false),
|
||||
(67, 1, null, '<p>this is test</p>', 'this is test', 1706684146436, 0, 'https://example.com/users/1/posts/67',
|
||||
null, null, false, 'https://example.com/users/1/posts/67', false),
|
||||
(68, 1, null, '<p>this is test</p>', 'this is test', 1706684146436, 0, 'https://example.com/users/1/posts/68',
|
||||
null, 67, false, 'https://example.com/users/1/posts/68', false),
|
||||
(69, 1, null, '<p>this is test</p>', 'this is test', 1706684146436, 2, 'https://example.com/users/1/posts/69',
|
||||
null, null, false, 'https://example.com/users/1/posts/69', false),
|
||||
(70, 1, null, '<p>this is test</p>', 'this is test', 1706684146436, 0, 'https://example.com/users/1/posts/70',
|
||||
null, 69, false, 'https://example.com/users/1/posts/70', false),
|
||||
(71, 1, null, '<p>this is test</p>', 'this is test', 1706684146436, 0, 'https://example.com/users/1/posts/71',
|
||||
null, null, false, 'https://example.com/users/1/posts/71', false),
|
||||
(72, 1, null, '<p>this is test</p>', 'this is test', 1706684146436, 2, 'https://example.com/users/1/posts/72',
|
||||
null, null, false, 'https://example.com/users/1/posts/72', false),
|
||||
(73, 1, null, '<p>this is test</p>', 'this is test', 1706684146436, 0, 'https://example.com/users/1/posts/73',
|
||||
null, null, false, 'https://example.com/users/1/posts/73', false),
|
||||
(74, 1, null, '<p>this is test</p>', 'this is test', 1706684146436, 0, 'https://example.com/users/1/posts/74',
|
||||
null, 73, false, 'https://example.com/users/1/posts/74', false),
|
||||
(75, 1, null, '<p>this is test</p>', 'this is test', 1706684146436, 2, 'https://example.com/users/1/posts/75',
|
||||
null, null, false, 'https://example.com/users/1/posts/75', false),
|
||||
(76, 1, null, '<p>this is test</p>', 'this is test', 1706684146436, 0, 'https://example.com/users/1/posts/76',
|
||||
null, 75, false, 'https://example.com/users/1/posts/76', false),
|
||||
(77, 1, null, '<p>this is test</p>', 'this is test', 1706684146436, 0, 'https://example.com/users/1/posts/77',
|
||||
null, null, false, 'https://example.com/users/1/posts/77', false),
|
||||
(78, 1, null, '<p>this is test</p>', 'this is test', 1706684146436, 2, 'https://example.com/users/1/posts/78',
|
||||
null, null, false, 'https://example.com/users/1/posts/78', false),
|
||||
(79, 1, null, '<p>this is test</p>', 'this is test', 1706684146436, 0, 'https://example.com/users/1/posts/79',
|
||||
null, null, false, 'https://example.com/users/1/posts/79', false),
|
||||
(80, 1, null, '<p>this is test</p>', 'this is test', 1706684146436, 0, 'https://example.com/users/1/posts/80',
|
||||
null, 79, false, 'https://example.com/users/1/posts/80', false),
|
||||
(81, 1, null, '<p>this is test</p>', 'this is test', 1706684146436, 2, 'https://example.com/users/1/posts/81',
|
||||
null, null, false, 'https://example.com/users/1/posts/81', false),
|
||||
(82, 1, null, '<p>this is test</p>', 'this is test', 1706684146436, 0, 'https://example.com/users/1/posts/82',
|
||||
null, 81, false, 'https://example.com/users/1/posts/82', false),
|
||||
(83, 1, null, '<p>this is test</p>', 'this is test', 1706684146436, 0, 'https://example.com/users/1/posts/83',
|
||||
null, null, false, 'https://example.com/users/1/posts/83', false),
|
||||
(84, 1, null, '<p>this is test</p>', 'this is test', 1706684146436, 2, 'https://example.com/users/1/posts/84',
|
||||
null, null, false, 'https://example.com/users/1/posts/84', false),
|
||||
(85, 1, null, '<p>this is test</p>', 'this is test', 1706684146436, 0, 'https://example.com/users/1/posts/85',
|
||||
null, null, false, 'https://example.com/users/1/posts/85', false),
|
||||
(86, 1, null, '<p>this is test</p>', 'this is test', 1706684146436, 0, 'https://example.com/users/1/posts/86',
|
||||
null, 85, false, 'https://example.com/users/1/posts/86', false),
|
||||
(87, 1, null, '<p>this is test</p>', 'this is test', 1706684146436, 2, 'https://example.com/users/1/posts/87',
|
||||
null, null, false, 'https://example.com/users/1/posts/87', false),
|
||||
(88, 1, null, '<p>this is test</p>', 'this is test', 1706684146436, 0, 'https://example.com/users/1/posts/88',
|
||||
null, 87, false, 'https://example.com/users/1/posts/88', false),
|
||||
(89, 1, null, '<p>this is test</p>', 'this is test', 1706684146436, 0, 'https://example.com/users/1/posts/89',
|
||||
null, null, false, 'https://example.com/users/1/posts/89', false),
|
||||
(90, 1, null, '<p>this is test</p>', 'this is test', 1706684146436, 2, 'https://example.com/users/1/posts/90',
|
||||
null, null, false, 'https://example.com/users/1/posts/90', false),
|
||||
(91, 1, null, '<p>this is test</p>', 'this is test', 1706684146436, 0, 'https://example.com/users/1/posts/91',
|
||||
null, null, false, 'https://example.com/users/1/posts/91', false),
|
||||
(92, 1, null, '<p>this is test</p>', 'this is test', 1706684146436, 0, 'https://example.com/users/1/posts/92',
|
||||
null, 91, false, 'https://example.com/users/1/posts/92', false),
|
||||
(93, 1, null, '<p>this is test</p>', 'this is test', 1706684146436, 2, 'https://example.com/users/1/posts/93',
|
||||
null, null, false, 'https://example.com/users/1/posts/93', false),
|
||||
(94, 1, null, '<p>this is test</p>', 'this is test', 1706684146436, 0, 'https://example.com/users/1/posts/94',
|
||||
null, 93, false, 'https://example.com/users/1/posts/94', false),
|
||||
(95, 1, null, '<p>this is test</p>', 'this is test', 1706684146436, 0, 'https://example.com/users/1/posts/95',
|
||||
null, null, false, 'https://example.com/users/1/posts/95', false),
|
||||
(96, 1, null, '<p>this is test</p>', 'this is test', 1706684146436, 2, 'https://example.com/users/1/posts/96',
|
||||
null, null, false, 'https://example.com/users/1/posts/96', false),
|
||||
(97, 1, null, '<p>this is test</p>', 'this is test', 1706684146436, 0, 'https://example.com/users/1/posts/97',
|
||||
null, null, false, 'https://example.com/users/1/posts/97', false),
|
||||
(98, 1, null, '<p>this is test</p>', 'this is test', 1706684146436, 0, 'https://example.com/users/1/posts/98',
|
||||
null, 97, false, 'https://example.com/users/1/posts/98', false),
|
||||
(99, 1, null, '<p>this is test</p>', 'this is test', 1706684146436, 2, 'https://example.com/users/1/posts/99',
|
||||
null, null, false, 'https://example.com/users/1/posts/99', false),
|
||||
(100, 1, null, '<p>this is test</p>', 'this is test', 1706684146436, 0, 'https://example.com/users/1/posts/100',
|
||||
null, 99, false, 'https://example.com/users/1/posts/100', false);
|
|
@ -0,0 +1,66 @@
|
|||
insert into mastodon_notifications (id, user_id, type, created_at, account_id, status_id, report_id, relationship_serverance_event_id)
|
||||
values (1, 1, 'follow', current_timestamp, 2, null, null, null),
|
||||
(2, 1, 'follow', current_timestamp, 2, null, null, null),
|
||||
(3, 1, 'follow', current_timestamp, 2, null, null, null),
|
||||
(4, 1, 'follow', current_timestamp, 2, null, null, null),
|
||||
(5, 1, 'follow', current_timestamp, 2, null, null, null),
|
||||
(6, 1, 'follow', current_timestamp, 2, null, null, null),
|
||||
(7, 1, 'follow', current_timestamp, 2, null, null, null),
|
||||
(8, 1, 'follow', current_timestamp, 2, null, null, null),
|
||||
(9, 1, 'follow', current_timestamp, 2, null, null, null),
|
||||
(10, 1, 'follow', current_timestamp, 2, null, null, null),
|
||||
(11, 1, 'follow', current_timestamp, 2, null, null, null),
|
||||
(12, 1, 'follow', current_timestamp, 2, null, null, null),
|
||||
(13, 1, 'follow', current_timestamp, 2, null, null, null),
|
||||
(14, 1, 'follow', current_timestamp, 2, null, null, null),
|
||||
(15, 1, 'follow', current_timestamp, 2, null, null, null),
|
||||
(16, 1, 'follow', current_timestamp, 2, null, null, null),
|
||||
(17, 1, 'follow', current_timestamp, 2, null, null, null),
|
||||
(18, 1, 'follow', current_timestamp, 2, null, null, null),
|
||||
(19, 1, 'follow', current_timestamp, 2, null, null, null),
|
||||
(20, 1, 'follow', current_timestamp, 2, null, null, null),
|
||||
(21, 1, 'follow', current_timestamp, 2, null, null, null),
|
||||
(22, 1, 'follow', current_timestamp, 2, null, null, null),
|
||||
(23, 1, 'follow', current_timestamp, 2, null, null, null),
|
||||
(24, 1, 'follow', current_timestamp, 2, null, null, null),
|
||||
(25, 1, 'follow', current_timestamp, 2, null, null, null),
|
||||
(26, 1, 'follow', current_timestamp, 2, null, null, null),
|
||||
(27, 1, 'follow', current_timestamp, 2, null, null, null),
|
||||
(28, 1, 'follow', current_timestamp, 2, null, null, null),
|
||||
(29, 1, 'follow', current_timestamp, 2, null, null, null),
|
||||
(30, 1, 'follow', current_timestamp, 2, null, null, null),
|
||||
(31, 1, 'follow', current_timestamp, 2, null, null, null),
|
||||
(32, 1, 'follow', current_timestamp, 2, null, null, null),
|
||||
(33, 1, 'follow', current_timestamp, 2, null, null, null),
|
||||
(34, 1, 'follow', current_timestamp, 2, null, null, null),
|
||||
(35, 1, 'follow', current_timestamp, 2, null, null, null),
|
||||
(36, 1, 'follow', current_timestamp, 2, null, null, null),
|
||||
(37, 1, 'follow', current_timestamp, 2, null, null, null),
|
||||
(38, 1, 'follow', current_timestamp, 2, null, null, null),
|
||||
(39, 1, 'follow', current_timestamp, 2, null, null, null),
|
||||
(40, 1, 'follow', current_timestamp, 2, null, null, null),
|
||||
(41, 1, 'follow', current_timestamp, 2, null, null, null),
|
||||
(42, 1, 'follow', current_timestamp, 2, null, null, null),
|
||||
(43, 1, 'follow', current_timestamp, 2, null, null, null),
|
||||
(44, 1, 'follow', current_timestamp, 2, null, null, null),
|
||||
(45, 1, 'follow', current_timestamp, 2, null, null, null),
|
||||
(46, 1, 'follow', current_timestamp, 2, null, null, null),
|
||||
(47, 1, 'follow', current_timestamp, 2, null, null, null),
|
||||
(48, 1, 'follow', current_timestamp, 2, null, null, null),
|
||||
(49, 1, 'follow', current_timestamp, 2, null, null, null),
|
||||
(50, 1, 'follow', current_timestamp, 2, null, null, null),
|
||||
(51, 1, 'follow', current_timestamp, 2, null, null, null),
|
||||
(52, 1, 'follow', current_timestamp, 2, null, null, null),
|
||||
(53, 1, 'follow', current_timestamp, 2, null, null, null),
|
||||
(54, 1, 'follow', current_timestamp, 2, null, null, null),
|
||||
(55, 1, 'follow', current_timestamp, 2, null, null, null),
|
||||
(56, 1, 'follow', current_timestamp, 2, null, null, null),
|
||||
(57, 1, 'follow', current_timestamp, 2, null, null, null),
|
||||
(58, 1, 'follow', current_timestamp, 2, null, null, null),
|
||||
(59, 1, 'follow', current_timestamp, 2, null, null, null),
|
||||
(60, 1, 'follow', current_timestamp, 2, null, null, null),
|
||||
(61, 1, 'follow', current_timestamp, 2, null, null, null),
|
||||
(62, 1, 'follow', current_timestamp, 2, null, null, null),
|
||||
(63, 1, 'follow', current_timestamp, 2, null, null, null),
|
||||
(64, 1, 'follow', current_timestamp, 2, null, null, null),
|
||||
(65, 1, 'follow', current_timestamp, 2, null, null, null);
|
|
@ -0,0 +1,66 @@
|
|||
insert into notifications(id, type, user_id, source_actor_id, post_id, text, reaction_id, created_at)
|
||||
VALUES (1, 'follow', 1, 2, null, null, null, current_timestamp),
|
||||
(2, 'follow', 1, 2, null, null, null, current_timestamp),
|
||||
(3, 'follow', 1, 2, null, null, null, current_timestamp),
|
||||
(4, 'follow', 1, 2, null, null, null, current_timestamp),
|
||||
(5, 'follow', 1, 2, null, null, null, current_timestamp),
|
||||
(6, 'follow', 1, 2, null, null, null, current_timestamp),
|
||||
(7, 'follow', 1, 2, null, null, null, current_timestamp),
|
||||
(8, 'follow', 1, 2, null, null, null, current_timestamp),
|
||||
(9, 'follow', 1, 2, null, null, null, current_timestamp),
|
||||
(10, 'follow', 1, 2, null, null, null, current_timestamp),
|
||||
(11, 'follow', 1, 2, null, null, null, current_timestamp),
|
||||
(12, 'follow', 1, 2, null, null, null, current_timestamp),
|
||||
(13, 'follow', 1, 2, null, null, null, current_timestamp),
|
||||
(14, 'follow', 1, 2, null, null, null, current_timestamp),
|
||||
(15, 'follow', 1, 2, null, null, null, current_timestamp),
|
||||
(16, 'follow', 1, 2, null, null, null, current_timestamp),
|
||||
(17, 'follow', 1, 2, null, null, null, current_timestamp),
|
||||
(18, 'follow', 1, 2, null, null, null, current_timestamp),
|
||||
(19, 'follow', 1, 2, null, null, null, current_timestamp),
|
||||
(20, 'follow', 1, 2, null, null, null, current_timestamp),
|
||||
(21, 'follow', 1, 2, null, null, null, current_timestamp),
|
||||
(22, 'follow', 1, 2, null, null, null, current_timestamp),
|
||||
(23, 'follow', 1, 2, null, null, null, current_timestamp),
|
||||
(24, 'follow', 1, 2, null, null, null, current_timestamp),
|
||||
(25, 'follow', 1, 2, null, null, null, current_timestamp),
|
||||
(26, 'follow', 1, 2, null, null, null, current_timestamp),
|
||||
(27, 'follow', 1, 2, null, null, null, current_timestamp),
|
||||
(28, 'follow', 1, 2, null, null, null, current_timestamp),
|
||||
(29, 'follow', 1, 2, null, null, null, current_timestamp),
|
||||
(30, 'follow', 1, 2, null, null, null, current_timestamp),
|
||||
(31, 'follow', 1, 2, null, null, null, current_timestamp),
|
||||
(32, 'follow', 1, 2, null, null, null, current_timestamp),
|
||||
(33, 'follow', 1, 2, null, null, null, current_timestamp),
|
||||
(34, 'follow', 1, 2, null, null, null, current_timestamp),
|
||||
(35, 'follow', 1, 2, null, null, null, current_timestamp),
|
||||
(36, 'follow', 1, 2, null, null, null, current_timestamp),
|
||||
(37, 'follow', 1, 2, null, null, null, current_timestamp),
|
||||
(38, 'follow', 1, 2, null, null, null, current_timestamp),
|
||||
(39, 'follow', 1, 2, null, null, null, current_timestamp),
|
||||
(40, 'follow', 1, 2, null, null, null, current_timestamp),
|
||||
(41, 'follow', 1, 2, null, null, null, current_timestamp),
|
||||
(42, 'follow', 1, 2, null, null, null, current_timestamp),
|
||||
(43, 'follow', 1, 2, null, null, null, current_timestamp),
|
||||
(44, 'follow', 1, 2, null, null, null, current_timestamp),
|
||||
(45, 'follow', 1, 2, null, null, null, current_timestamp),
|
||||
(46, 'follow', 1, 2, null, null, null, current_timestamp),
|
||||
(47, 'follow', 1, 2, null, null, null, current_timestamp),
|
||||
(48, 'follow', 1, 2, null, null, null, current_timestamp),
|
||||
(49, 'follow', 1, 2, null, null, null, current_timestamp),
|
||||
(50, 'follow', 1, 2, null, null, null, current_timestamp),
|
||||
(51, 'follow', 1, 2, null, null, null, current_timestamp),
|
||||
(52, 'follow', 1, 2, null, null, null, current_timestamp),
|
||||
(53, 'follow', 1, 2, null, null, null, current_timestamp),
|
||||
(54, 'follow', 1, 2, null, null, null, current_timestamp),
|
||||
(55, 'follow', 1, 2, null, null, null, current_timestamp),
|
||||
(56, 'follow', 1, 2, null, null, null, current_timestamp),
|
||||
(57, 'follow', 1, 2, null, null, null, current_timestamp),
|
||||
(58, 'follow', 1, 2, null, null, null, current_timestamp),
|
||||
(59, 'follow', 1, 2, null, null, null, current_timestamp),
|
||||
(60, 'follow', 1, 2, null, null, null, current_timestamp),
|
||||
(61, 'follow', 1, 2, null, null, null, current_timestamp),
|
||||
(62, 'follow', 1, 2, null, null, null, current_timestamp),
|
||||
(63, 'follow', 1, 2, null, null, null, current_timestamp),
|
||||
(64, 'follow', 1, 2, null, null, null, current_timestamp),
|
||||
(65, 'follow', 1, 2, null, null, null, current_timestamp);
|
|
@ -52,11 +52,11 @@ open class Delete : Object, HasId, HasActor {
|
|||
|
||||
override fun toString(): String {
|
||||
return "Delete(" +
|
||||
"apObject=$apObject, " +
|
||||
"published='$published', " +
|
||||
"actor='$actor', " +
|
||||
"id='$id'" +
|
||||
")" +
|
||||
" ${super.toString()}"
|
||||
"apObject=$apObject, " +
|
||||
"published='$published', " +
|
||||
"actor='$actor', " +
|
||||
"id='$id'" +
|
||||
")" +
|
||||
" ${super.toString()}"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,12 +16,12 @@ open class Emoji(
|
|||
|
||||
override fun toString(): String {
|
||||
return "Emoji(" +
|
||||
"name='$name', " +
|
||||
"id='$id', " +
|
||||
"updated='$updated', " +
|
||||
"icon=$icon" +
|
||||
")" +
|
||||
" ${super.toString()}"
|
||||
"name='$name', " +
|
||||
"id='$id', " +
|
||||
"updated='$updated', " +
|
||||
"icon=$icon" +
|
||||
")" +
|
||||
" ${super.toString()}"
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
|
|
|
@ -36,10 +36,10 @@ open class Follow(
|
|||
|
||||
override fun toString(): String {
|
||||
return "Follow(" +
|
||||
"apObject='$apObject', " +
|
||||
"actor='$actor', " +
|
||||
"id=$id" +
|
||||
")" +
|
||||
" ${super.toString()}"
|
||||
"apObject='$apObject', " +
|
||||
"actor='$actor', " +
|
||||
"id=$id" +
|
||||
")" +
|
||||
" ${super.toString()}"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -62,17 +62,17 @@ constructor(
|
|||
|
||||
override fun toString(): String {
|
||||
return "Note(" +
|
||||
"id='$id', " +
|
||||
"attributedTo='$attributedTo', " +
|
||||
"content='$content', " +
|
||||
"published='$published', " +
|
||||
"to=$to, " +
|
||||
"cc=$cc, " +
|
||||
"sensitive=$sensitive, " +
|
||||
"inReplyTo=$inReplyTo, " +
|
||||
"attachment=$attachment, " +
|
||||
"tag=$tag" +
|
||||
")" +
|
||||
" ${super.toString()}"
|
||||
"id='$id', " +
|
||||
"attributedTo='$attributedTo', " +
|
||||
"content='$content', " +
|
||||
"published='$published', " +
|
||||
"to=$to, " +
|
||||
"cc=$cc, " +
|
||||
"sensitive=$sensitive, " +
|
||||
"inReplyTo=$inReplyTo, " +
|
||||
"attachment=$attachment, " +
|
||||
"tag=$tag" +
|
||||
")" +
|
||||
" ${super.toString()}"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,11 +40,11 @@ open class Undo(
|
|||
|
||||
override fun toString(): String {
|
||||
return "Undo(" +
|
||||
"actor='$actor', " +
|
||||
"id='$id', " +
|
||||
"apObject=$apObject, " +
|
||||
"published=$published" +
|
||||
")" +
|
||||
" ${super.toString()}"
|
||||
"actor='$actor', " +
|
||||
"id='$id', " +
|
||||
"apObject=$apObject, " +
|
||||
"published=$published" +
|
||||
")" +
|
||||
" ${super.toString()}"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
package dev.usbharu.hideout.application.infrastructure.exposed
|
||||
|
||||
import org.jetbrains.exposed.sql.*
|
||||
|
||||
fun <S> Query.withPagination(page: Page, exp: ExpressionWithColumnType<S>): PaginationList<ResultRow, S> {
|
||||
page.limit?.let { limit(it) }
|
||||
val resultRows = if (page.minId != null) {
|
||||
page.maxId?.let { andWhere { exp.less(it) } }
|
||||
andWhere { exp.greater(page.minId!!) }
|
||||
reversed()
|
||||
} else {
|
||||
page.maxId?.let { andWhere { exp.less(it) } }
|
||||
page.sinceId?.let { andWhere { exp.greater(it) } }
|
||||
orderBy(exp, SortOrder.DESC)
|
||||
toList()
|
||||
}
|
||||
|
||||
return PaginationList(resultRows, resultRows.firstOrNull()?.getOrNull(exp), resultRows.lastOrNull()?.getOrNull(exp))
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
package dev.usbharu.hideout.application.infrastructure.exposed
|
||||
|
||||
sealed class Page {
|
||||
abstract val maxId: Long?
|
||||
abstract val sinceId: Long?
|
||||
abstract val minId: Long?
|
||||
abstract val limit: Int?
|
||||
|
||||
data class PageByMaxId(
|
||||
override val maxId: Long?,
|
||||
override val sinceId: Long?,
|
||||
override val limit: Int?
|
||||
) : Page() {
|
||||
override val minId: Long? = null
|
||||
}
|
||||
|
||||
data class PageByMinId(
|
||||
override val maxId: Long?,
|
||||
override val minId: Long?,
|
||||
override val limit: Int?
|
||||
) : Page() {
|
||||
override val sinceId: Long? = null
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun of(
|
||||
maxId: Long? = null,
|
||||
sinceId: Long? = null,
|
||||
minId: Long? = null,
|
||||
limit: Int? = null
|
||||
): Page =
|
||||
if (minId != null) {
|
||||
PageByMinId(
|
||||
maxId,
|
||||
minId,
|
||||
limit
|
||||
)
|
||||
} else {
|
||||
PageByMaxId(
|
||||
maxId,
|
||||
sinceId,
|
||||
limit
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
package dev.usbharu.hideout.application.infrastructure.exposed
|
||||
|
||||
class PaginationList<T, ID>(list: List<T>, val next: ID?, val prev: ID?) : List<T> by list
|
||||
|
||||
fun <T, ID> PaginationList<T, ID>.toHttpHeader(
|
||||
nextBlock: (string: String) -> String,
|
||||
prevBlock: (string: String) -> String
|
||||
): String? {
|
||||
val mutableListOf = mutableListOf<String>()
|
||||
if (next != null) {
|
||||
mutableListOf.add("<${nextBlock(this.next.toString())}>; rel=\"next\"")
|
||||
}
|
||||
if (prev != null) {
|
||||
mutableListOf.add("<${prevBlock(this.prev.toString())}>; rel=\"prev\"")
|
||||
}
|
||||
|
||||
if (mutableListOf.isEmpty()) {
|
||||
return null
|
||||
}
|
||||
|
||||
return mutableListOf.joinToString(", ")
|
||||
}
|
|
@ -212,27 +212,27 @@ data class Actor private constructor(
|
|||
fun withLastPostAt(lastPostDate: Instant): Actor = this.copy(lastPostDate = lastPostDate)
|
||||
override fun toString(): String {
|
||||
return "Actor(" +
|
||||
"id=$id, " +
|
||||
"name='$name', " +
|
||||
"domain='$domain', " +
|
||||
"screenName='$screenName', " +
|
||||
"description='$description', " +
|
||||
"inbox='$inbox', " +
|
||||
"outbox='$outbox', " +
|
||||
"url='$url', " +
|
||||
"publicKey='$publicKey', " +
|
||||
"privateKey=$privateKey, " +
|
||||
"createdAt=$createdAt, " +
|
||||
"keyId='$keyId', " +
|
||||
"followers=$followers, " +
|
||||
"following=$following, " +
|
||||
"instance=$instance, " +
|
||||
"locked=$locked, " +
|
||||
"followersCount=$followersCount, " +
|
||||
"followingCount=$followingCount, " +
|
||||
"postsCount=$postsCount, " +
|
||||
"lastPostDate=$lastPostDate, " +
|
||||
"emojis=$emojis" +
|
||||
")"
|
||||
"id=$id, " +
|
||||
"name='$name', " +
|
||||
"domain='$domain', " +
|
||||
"screenName='$screenName', " +
|
||||
"description='$description', " +
|
||||
"inbox='$inbox', " +
|
||||
"outbox='$outbox', " +
|
||||
"url='$url', " +
|
||||
"publicKey='$publicKey', " +
|
||||
"privateKey=$privateKey, " +
|
||||
"createdAt=$createdAt, " +
|
||||
"keyId='$keyId', " +
|
||||
"followers=$followers, " +
|
||||
"following=$following, " +
|
||||
"instance=$instance, " +
|
||||
"locked=$locked, " +
|
||||
"followersCount=$followersCount, " +
|
||||
"followingCount=$followingCount, " +
|
||||
"postsCount=$postsCount, " +
|
||||
"lastPostDate=$lastPostDate, " +
|
||||
"emojis=$emojis" +
|
||||
")"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,9 +10,9 @@ sealed class Emoji {
|
|||
abstract fun id(): String
|
||||
override fun toString(): String {
|
||||
return "Emoji(" +
|
||||
"domain='$domain', " +
|
||||
"name='$name'" +
|
||||
")"
|
||||
"domain='$domain', " +
|
||||
"name='$name'" +
|
||||
")"
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
package dev.usbharu.hideout.core.domain.model.relationship
|
||||
|
||||
import dev.usbharu.hideout.application.infrastructure.exposed.Page
|
||||
import dev.usbharu.hideout.application.infrastructure.exposed.PaginationList
|
||||
|
||||
/**
|
||||
* [Relationship]の永続化
|
||||
*
|
||||
|
@ -33,22 +36,16 @@ interface RelationshipRepository {
|
|||
|
||||
suspend fun findByTargetIdAndFollowing(targetId: Long, following: Boolean): List<Relationship>
|
||||
|
||||
@Suppress("LongParameterList", "FunctionMaxLength")
|
||||
suspend fun findByTargetIdAndFollowRequestAndIgnoreFollowRequest(
|
||||
maxId: Long?,
|
||||
sinceId: Long?,
|
||||
limit: Int,
|
||||
targetId: Long,
|
||||
followRequest: Boolean,
|
||||
ignoreFollowRequest: Boolean
|
||||
): List<Relationship>
|
||||
ignoreFollowRequest: Boolean,
|
||||
page: Page.PageByMaxId
|
||||
): PaginationList<Relationship, Long>
|
||||
|
||||
@Suppress("FunctionMaxLength")
|
||||
suspend fun findByActorIdAntMutingAndMaxIdAndSinceId(
|
||||
suspend fun findByActorIdAndMuting(
|
||||
actorId: Long,
|
||||
muting: Boolean,
|
||||
maxId: Long?,
|
||||
sinceId: Long?,
|
||||
limit: Int
|
||||
): List<Relationship>
|
||||
page: Page.PageByMaxId
|
||||
): PaginationList<Relationship, Long>
|
||||
}
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
package dev.usbharu.hideout.core.domain.model.relationship
|
||||
|
||||
import dev.usbharu.hideout.application.infrastructure.exposed.Page
|
||||
import dev.usbharu.hideout.application.infrastructure.exposed.PaginationList
|
||||
import dev.usbharu.hideout.application.infrastructure.exposed.withPagination
|
||||
import dev.usbharu.hideout.core.infrastructure.exposedrepository.AbstractRepository
|
||||
import dev.usbharu.hideout.core.infrastructure.exposedrepository.Actors
|
||||
import org.jetbrains.exposed.dao.id.LongIdTable
|
||||
|
@ -74,49 +77,41 @@ class RelationshipRepositoryImpl : RelationshipRepository, AbstractRepository()
|
|||
}
|
||||
|
||||
override suspend fun findByTargetIdAndFollowRequestAndIgnoreFollowRequest(
|
||||
maxId: Long?,
|
||||
sinceId: Long?,
|
||||
limit: Int,
|
||||
targetId: Long,
|
||||
followRequest: Boolean,
|
||||
ignoreFollowRequest: Boolean
|
||||
): List<Relationship> = query {
|
||||
ignoreFollowRequest: Boolean,
|
||||
page: Page.PageByMaxId
|
||||
): PaginationList<Relationship, Long> = query {
|
||||
val query = Relationships.select {
|
||||
Relationships.targetActorId.eq(targetId).and(Relationships.followRequest.eq(followRequest))
|
||||
.and(Relationships.ignoreFollowRequestFromTarget.eq(ignoreFollowRequest))
|
||||
}.limit(limit)
|
||||
|
||||
if (maxId != null) {
|
||||
query.andWhere { Relationships.id lessEq maxId }
|
||||
}
|
||||
|
||||
if (sinceId != null) {
|
||||
query.andWhere { Relationships.id greaterEq sinceId }
|
||||
}
|
||||
val resultRowList = query.withPagination(page, Relationships.id)
|
||||
|
||||
return@query query.map { it.toRelationships() }
|
||||
return@query PaginationList(
|
||||
resultRowList.map { it.toRelationships() },
|
||||
resultRowList.next?.value,
|
||||
resultRowList.prev?.value
|
||||
)
|
||||
}
|
||||
|
||||
override suspend fun findByActorIdAntMutingAndMaxIdAndSinceId(
|
||||
override suspend fun findByActorIdAndMuting(
|
||||
actorId: Long,
|
||||
muting: Boolean,
|
||||
maxId: Long?,
|
||||
sinceId: Long?,
|
||||
limit: Int
|
||||
): List<Relationship> = query {
|
||||
page: Page.PageByMaxId
|
||||
): PaginationList<Relationship, Long> = query {
|
||||
val query = Relationships.select {
|
||||
Relationships.actorId.eq(actorId).and(Relationships.muting.eq(muting))
|
||||
}.limit(limit)
|
||||
|
||||
if (maxId != null) {
|
||||
query.andWhere { Relationships.id lessEq maxId }
|
||||
}
|
||||
|
||||
if (sinceId != null) {
|
||||
query.andWhere { Relationships.id greaterEq sinceId }
|
||||
}
|
||||
val resultRowList = query.withPagination(page, Relationships.id)
|
||||
|
||||
return@query query.map { it.toRelationships() }
|
||||
return@query PaginationList(
|
||||
resultRowList.map { it.toRelationships() },
|
||||
resultRowList.next?.value,
|
||||
resultRowList.prev?.value
|
||||
)
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
|
|
@ -41,10 +41,10 @@ class HttpSignatureUser(
|
|||
|
||||
override fun toString(): String {
|
||||
return "HttpSignatureUser(" +
|
||||
"domain='$domain', " +
|
||||
"id=$id" +
|
||||
")" +
|
||||
" ${super.toString()}"
|
||||
"domain='$domain', " +
|
||||
"id=$id" +
|
||||
")" +
|
||||
" ${super.toString()}"
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
|
|
@ -273,7 +273,7 @@ class ExposedOAuth2AuthorizationService(
|
|||
oidcTokenIssuedAt,
|
||||
oidcTokenExpiresAt,
|
||||
oidcTokenMetadata.getValue(OAuth2Authorization.Token.CLAIMS_METADATA_NAME)
|
||||
as MutableMap<String, Any>?
|
||||
as MutableMap<String, Any>?
|
||||
)
|
||||
|
||||
builder.token(oidcIdToken) { it.putAll(oidcTokenMetadata) }
|
||||
|
|
|
@ -28,9 +28,9 @@ class UserDetailsImpl(
|
|||
) : User(username, password, enabled, accountNonExpired, credentialsNonExpired, accountNonLocked, authorities) {
|
||||
override fun toString(): String {
|
||||
return "UserDetailsImpl(" +
|
||||
"id=$id" +
|
||||
")" +
|
||||
" ${super.toString()}"
|
||||
"id=$id" +
|
||||
")" +
|
||||
" ${super.toString()}"
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
|
|
|
@ -29,7 +29,7 @@ class MediaServiceImpl(
|
|||
val fileName = mediaRequest.file.name
|
||||
logger.info(
|
||||
"Media upload. filename:$fileName " +
|
||||
"contentType:${mediaRequest.file.contentType}"
|
||||
"contentType:${mediaRequest.file.contentType}"
|
||||
)
|
||||
|
||||
val tempFile = Files.createTempFile("hideout-tmp-file", ".tmp")
|
||||
|
|
|
@ -8,7 +8,7 @@ data class ImageMediaProcessorConfiguration(
|
|||
val thubnail: ImageMediaProcessorThumbnailConfiguration?,
|
||||
val supportedType: List<String>?,
|
||||
|
||||
)
|
||||
)
|
||||
|
||||
data class ImageMediaProcessorThumbnailConfiguration(
|
||||
val generate: Boolean,
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
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.withPagination
|
||||
import dev.usbharu.hideout.core.infrastructure.exposedrepository.Timelines
|
||||
import dev.usbharu.hideout.domain.mastodon.model.generated.Status
|
||||
import dev.usbharu.hideout.mastodon.interfaces.api.status.StatusQuery
|
||||
import dev.usbharu.hideout.mastodon.query.StatusQueryService
|
||||
import org.jetbrains.exposed.sql.SortOrder
|
||||
import org.jetbrains.exposed.sql.andWhere
|
||||
import org.jetbrains.exposed.sql.selectAll
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty
|
||||
|
@ -13,15 +15,13 @@ import org.springframework.stereotype.Service
|
|||
@Service
|
||||
@ConditionalOnProperty("hideout.use-mongodb", havingValue = "false", matchIfMissing = true)
|
||||
class ExposedGenerateTimelineService(private val statusQueryService: StatusQueryService) : GenerateTimelineService {
|
||||
|
||||
override suspend fun getTimeline(
|
||||
forUserId: Long?,
|
||||
localOnly: Boolean,
|
||||
mediaOnly: Boolean,
|
||||
maxId: Long?,
|
||||
minId: Long?,
|
||||
sinceId: Long?,
|
||||
limit: Int
|
||||
): List<Status> {
|
||||
page: Page
|
||||
): PaginationList<Status, Long> {
|
||||
val query = Timelines.selectAll()
|
||||
|
||||
if (forUserId != null) {
|
||||
|
@ -30,15 +30,7 @@ class ExposedGenerateTimelineService(private val statusQueryService: StatusQuery
|
|||
if (localOnly) {
|
||||
query.andWhere { Timelines.isLocal eq true }
|
||||
}
|
||||
if (maxId != null) {
|
||||
query.andWhere { Timelines.id lessEq maxId }
|
||||
}
|
||||
if (minId != null) {
|
||||
query.andWhere { Timelines.id greaterEq minId }
|
||||
}
|
||||
val result = query
|
||||
.limit(limit)
|
||||
.orderBy(Timelines.createdAt, SortOrder.DESC)
|
||||
val result = query.withPagination(page, Timelines.id)
|
||||
|
||||
val statusQueries = result.map {
|
||||
StatusQuery(
|
||||
|
@ -50,6 +42,11 @@ class ExposedGenerateTimelineService(private val statusQueryService: StatusQuery
|
|||
)
|
||||
}
|
||||
|
||||
return statusQueryService.findByPostIdsWithMediaIds(statusQueries)
|
||||
val findByPostIdsWithMediaIds = statusQueryService.findByPostIdsWithMediaIds(statusQueries)
|
||||
return PaginationList(
|
||||
findByPostIdsWithMediaIds,
|
||||
findByPostIdsWithMediaIds.lastOrNull()?.id?.toLongOrNull(),
|
||||
findByPostIdsWithMediaIds.firstOrNull()?.id?.toLongOrNull()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
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 org.springframework.stereotype.Service
|
||||
|
||||
@Service
|
||||
@Suppress("LongParameterList")
|
||||
interface GenerateTimelineService {
|
||||
|
||||
suspend fun getTimeline(
|
||||
forUserId: Long? = null,
|
||||
localOnly: Boolean = false,
|
||||
mediaOnly: Boolean = false,
|
||||
maxId: Long? = null,
|
||||
minId: Long? = null,
|
||||
sinceId: Long? = null,
|
||||
limit: Int = 20
|
||||
): List<Status>
|
||||
page: Page
|
||||
): PaginationList<Status, Long>
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
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.domain.mastodon.model.generated.Status
|
||||
import dev.usbharu.hideout.mastodon.interfaces.api.status.StatusQuery
|
||||
|
@ -18,15 +20,13 @@ class MongoGenerateTimelineService(
|
|||
private val mongoTemplate: MongoTemplate
|
||||
) :
|
||||
GenerateTimelineService {
|
||||
|
||||
override suspend fun getTimeline(
|
||||
forUserId: Long?,
|
||||
localOnly: Boolean,
|
||||
mediaOnly: Boolean,
|
||||
maxId: Long?,
|
||||
minId: Long?,
|
||||
sinceId: Long?,
|
||||
limit: Int
|
||||
): List<Status> {
|
||||
page: Page
|
||||
): PaginationList<Status, Long> {
|
||||
val query = Query()
|
||||
|
||||
if (forUserId != null) {
|
||||
|
@ -37,21 +37,23 @@ class MongoGenerateTimelineService(
|
|||
val criteria = Criteria.where("isLocal").`is`(true)
|
||||
query.addCriteria(criteria)
|
||||
}
|
||||
if (maxId != null) {
|
||||
val criteria = Criteria.where("postId").lt(maxId)
|
||||
query.addCriteria(criteria)
|
||||
}
|
||||
if (minId != null) {
|
||||
val criteria = Criteria.where("postId").gt(minId)
|
||||
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)) }
|
||||
}
|
||||
|
||||
query.limit(limit)
|
||||
page.limit?.let { query.limit(it) }
|
||||
|
||||
query.with(Sort.by(Sort.Direction.DESC, "createdAt"))
|
||||
|
||||
val timelines = mongoTemplate.find(query, Timeline::class.java)
|
||||
|
||||
return statusQueryService.findByPostIdsWithMediaIds(
|
||||
val statuses = statusQueryService.findByPostIdsWithMediaIds(
|
||||
timelines.map {
|
||||
StatusQuery(
|
||||
it.postId,
|
||||
|
@ -62,5 +64,10 @@ class MongoGenerateTimelineService(
|
|||
)
|
||||
}
|
||||
)
|
||||
return PaginationList(
|
||||
statuses,
|
||||
statuses.lastOrNull()?.id?.toLongOrNull(),
|
||||
statuses.firstOrNull()?.id?.toLongOrNull()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,20 +1,19 @@
|
|||
package dev.usbharu.hideout.mastodon.domain.model
|
||||
|
||||
import dev.usbharu.hideout.application.infrastructure.exposed.Page
|
||||
import dev.usbharu.hideout.application.infrastructure.exposed.PaginationList
|
||||
|
||||
interface MastodonNotificationRepository {
|
||||
suspend fun save(mastodonNotification: MastodonNotification): MastodonNotification
|
||||
suspend fun deleteById(id: Long)
|
||||
suspend fun findById(id: Long): MastodonNotification?
|
||||
|
||||
@Suppress("LongParameterList", "FunctionMaxLength")
|
||||
suspend fun findByUserIdAndMaxIdAndMinIdAndSinceIdAndInTypesAndInSourceActorId(
|
||||
suspend fun findByUserIdAndInTypesAndInSourceActorId(
|
||||
loginUser: Long,
|
||||
maxId: Long?,
|
||||
minId: Long?,
|
||||
sinceId: Long?,
|
||||
limit: Int,
|
||||
typesTmp: MutableList<NotificationType>,
|
||||
accountId: List<Long>
|
||||
): List<MastodonNotification>
|
||||
types: List<NotificationType>,
|
||||
accountId: List<Long>,
|
||||
page: Page
|
||||
): PaginationList<MastodonNotification, Long>
|
||||
|
||||
suspend fun deleteByUserId(userId: Long)
|
||||
suspend fun deleteByUserIdAndId(userId: Long, id: Long)
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
package dev.usbharu.hideout.mastodon.infrastructure.exposedquery
|
||||
|
||||
import dev.usbharu.hideout.application.infrastructure.exposed.Page
|
||||
import dev.usbharu.hideout.application.infrastructure.exposed.PaginationList
|
||||
import dev.usbharu.hideout.application.infrastructure.exposed.withPagination
|
||||
import dev.usbharu.hideout.core.domain.model.emoji.CustomEmoji
|
||||
import dev.usbharu.hideout.core.domain.model.media.toMediaAttachments
|
||||
import dev.usbharu.hideout.core.infrastructure.exposedrepository.*
|
||||
|
@ -54,32 +57,20 @@ class StatusQueryServiceImpl : StatusQueryService {
|
|||
|
||||
override suspend fun accountsStatus(
|
||||
accountId: Long,
|
||||
maxId: Long?,
|
||||
sinceId: Long?,
|
||||
minId: Long?,
|
||||
limit: Int,
|
||||
onlyMedia: Boolean,
|
||||
excludeReplies: Boolean,
|
||||
excludeReblogs: Boolean,
|
||||
pinned: Boolean,
|
||||
tagged: String?,
|
||||
includeFollowers: Boolean
|
||||
): List<Status> {
|
||||
includeFollowers: Boolean,
|
||||
page: Page
|
||||
): PaginationList<Status, Long> {
|
||||
val query = Posts
|
||||
.leftJoin(PostsMedia)
|
||||
.leftJoin(Actors)
|
||||
.leftJoin(Media)
|
||||
.select { Posts.actorId eq accountId }.limit(20)
|
||||
.select { Posts.actorId eq accountId }
|
||||
|
||||
if (maxId != null) {
|
||||
query.andWhere { Posts.id eq maxId }
|
||||
}
|
||||
if (sinceId != null) {
|
||||
query.andWhere { Posts.id eq sinceId }
|
||||
}
|
||||
if (minId != null) {
|
||||
query.andWhere { Posts.id eq minId }
|
||||
}
|
||||
if (onlyMedia) {
|
||||
query.andWhere { PostsMedia.mediaId.isNotNull() }
|
||||
}
|
||||
|
@ -95,7 +86,9 @@ class StatusQueryServiceImpl : StatusQueryService {
|
|||
query.andWhere { Posts.visibility inList listOf(public.ordinal, unlisted.ordinal) }
|
||||
}
|
||||
|
||||
val pairs = query.groupBy { it[Posts.id] }
|
||||
val pairs = query
|
||||
.withPagination(page, Posts.id)
|
||||
.groupBy { it[Posts.id] }
|
||||
.map { it.value }
|
||||
.map {
|
||||
toStatus(it.first()).copy(
|
||||
|
@ -105,7 +98,12 @@ class StatusQueryServiceImpl : StatusQueryService {
|
|||
) to it.first()[Posts.repostId]
|
||||
}
|
||||
|
||||
return resolveReplyAndRepost(pairs)
|
||||
val statuses = resolveReplyAndRepost(pairs)
|
||||
return PaginationList(
|
||||
statuses,
|
||||
statuses.firstOrNull()?.id?.toLongOrNull(),
|
||||
statuses.lastOrNull()?.id?.toLongOrNull()
|
||||
)
|
||||
}
|
||||
|
||||
override suspend fun findByPostId(id: Long): Status {
|
||||
|
@ -139,7 +137,9 @@ class StatusQueryServiceImpl : StatusQueryService {
|
|||
}
|
||||
.map {
|
||||
if (it.inReplyToId != null) {
|
||||
it.copy(inReplyToAccountId = statuses.find { (id) -> id == it.inReplyToId }?.id)
|
||||
println("statuses trace: $statuses")
|
||||
println("inReplyToId trace: ${it.inReplyToId}")
|
||||
it.copy(inReplyToAccountId = statuses.find { (id) -> id == it.inReplyToId }?.account?.id)
|
||||
} else {
|
||||
it
|
||||
}
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
package dev.usbharu.hideout.mastodon.infrastructure.exposedrepository
|
||||
|
||||
import dev.usbharu.hideout.application.infrastructure.exposed.Page
|
||||
import dev.usbharu.hideout.application.infrastructure.exposed.PaginationList
|
||||
import dev.usbharu.hideout.application.infrastructure.exposed.withPagination
|
||||
import dev.usbharu.hideout.core.infrastructure.exposedrepository.AbstractRepository
|
||||
import dev.usbharu.hideout.core.infrastructure.exposedrepository.Timelines
|
||||
import dev.usbharu.hideout.mastodon.domain.model.MastodonNotification
|
||||
import dev.usbharu.hideout.mastodon.domain.model.MastodonNotificationRepository
|
||||
import dev.usbharu.hideout.mastodon.domain.model.NotificationType
|
||||
|
@ -59,33 +61,18 @@ class ExposedMastodonNotificationRepository : MastodonNotificationRepository, Ab
|
|||
MastodonNotifications.select { MastodonNotifications.id eq id }.singleOrNull()?.toMastodonNotification()
|
||||
}
|
||||
|
||||
override suspend fun findByUserIdAndMaxIdAndMinIdAndSinceIdAndInTypesAndInSourceActorId(
|
||||
override suspend fun findByUserIdAndInTypesAndInSourceActorId(
|
||||
loginUser: Long,
|
||||
maxId: Long?,
|
||||
minId: Long?,
|
||||
sinceId: Long?,
|
||||
limit: Int,
|
||||
typesTmp: MutableList<NotificationType>,
|
||||
accountId: List<Long>
|
||||
): List<MastodonNotification> = query {
|
||||
types: List<NotificationType>,
|
||||
accountId: List<Long>,
|
||||
page: Page
|
||||
): PaginationList<MastodonNotification, Long> = query {
|
||||
val query = MastodonNotifications.select {
|
||||
MastodonNotifications.userId eq loginUser
|
||||
}
|
||||
val result = query.withPagination(page, MastodonNotifications.id)
|
||||
|
||||
if (maxId != null) {
|
||||
query.andWhere { MastodonNotifications.id lessEq maxId }
|
||||
}
|
||||
if (minId != null) {
|
||||
query.andWhere { MastodonNotifications.id greaterEq minId }
|
||||
}
|
||||
if (sinceId != null) {
|
||||
query.andWhere { MastodonNotifications.id greaterEq sinceId }
|
||||
}
|
||||
val result = query
|
||||
.limit(limit)
|
||||
.orderBy(Timelines.createdAt, SortOrder.DESC)
|
||||
|
||||
return@query result.map { it.toMastodonNotification() }
|
||||
return@query PaginationList(result.map { it.toMastodonNotification() }, result.next, result.prev)
|
||||
}
|
||||
|
||||
override suspend fun deleteByUserId(userId: Long) {
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package dev.usbharu.hideout.mastodon.infrastructure.mongorepository
|
||||
|
||||
import dev.usbharu.hideout.application.infrastructure.exposed.Page
|
||||
import dev.usbharu.hideout.application.infrastructure.exposed.PaginationList
|
||||
import dev.usbharu.hideout.mastodon.domain.model.MastodonNotification
|
||||
import dev.usbharu.hideout.mastodon.domain.model.MastodonNotificationRepository
|
||||
import dev.usbharu.hideout.mastodon.domain.model.NotificationType
|
||||
|
@ -26,35 +28,33 @@ class MongoMastodonNotificationRepositoryWrapper(
|
|||
override suspend fun findById(id: Long): MastodonNotification? =
|
||||
mongoMastodonNotificationRepository.findById(id).getOrNull()
|
||||
|
||||
override suspend fun findByUserIdAndMaxIdAndMinIdAndSinceIdAndInTypesAndInSourceActorId(
|
||||
override suspend fun findByUserIdAndInTypesAndInSourceActorId(
|
||||
loginUser: Long,
|
||||
maxId: Long?,
|
||||
minId: Long?,
|
||||
sinceId: Long?,
|
||||
limit: Int,
|
||||
typesTmp: MutableList<NotificationType>,
|
||||
accountId: List<Long>
|
||||
): List<MastodonNotification> {
|
||||
types: List<NotificationType>,
|
||||
accountId: List<Long>,
|
||||
page: Page
|
||||
): PaginationList<MastodonNotification, Long> {
|
||||
val query = Query()
|
||||
|
||||
if (maxId != null) {
|
||||
val criteria = Criteria.where("id").lte(maxId)
|
||||
query.addCriteria(criteria)
|
||||
page.limit?.let { query.limit(it) }
|
||||
|
||||
val mastodonNotifications = if (page.minId != null) {
|
||||
query.with(Sort.by(Sort.Direction.ASC, "id"))
|
||||
page.minId?.let { query.addCriteria(Criteria.where("id").gt(it)) }
|
||||
page.maxId?.let { query.addCriteria(Criteria.where("id").lt(it)) }
|
||||
mongoTemplate.find(query, MastodonNotification::class.java).reversed()
|
||||
} else {
|
||||
query.with(Sort.by(Sort.Direction.DESC, "id"))
|
||||
page.sinceId?.let { query.addCriteria(Criteria.where("id").gt(it)) }
|
||||
page.maxId?.let { query.addCriteria(Criteria.where("id").lt(it)) }
|
||||
mongoTemplate.find(query, MastodonNotification::class.java)
|
||||
}
|
||||
|
||||
if (minId != null) {
|
||||
val criteria = Criteria.where("id").gte(minId)
|
||||
query.addCriteria(criteria)
|
||||
}
|
||||
if (sinceId != null) {
|
||||
val criteria = Criteria.where("id").gte(sinceId)
|
||||
query.addCriteria(criteria)
|
||||
}
|
||||
|
||||
query.limit(limit)
|
||||
query.with(Sort.by(Sort.Direction.DESC, "createdAt"))
|
||||
|
||||
return mongoTemplate.find(query, MastodonNotification::class.java)
|
||||
return PaginationList(
|
||||
mastodonNotifications,
|
||||
mastodonNotifications.firstOrNull()?.id,
|
||||
mastodonNotifications.lastOrNull()?.id
|
||||
)
|
||||
}
|
||||
|
||||
override suspend fun deleteByUserId(userId: Long) {
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
package dev.usbharu.hideout.mastodon.interfaces.api.account
|
||||
|
||||
import dev.usbharu.hideout.application.config.ApplicationConfig
|
||||
import dev.usbharu.hideout.application.external.Transaction
|
||||
import dev.usbharu.hideout.application.infrastructure.exposed.Page
|
||||
import dev.usbharu.hideout.application.infrastructure.exposed.toHttpHeader
|
||||
import dev.usbharu.hideout.controller.mastodon.generated.AccountApi
|
||||
import dev.usbharu.hideout.core.infrastructure.springframework.security.LoginUserContextHolder
|
||||
import dev.usbharu.hideout.core.service.user.UserCreateDto
|
||||
|
@ -19,7 +22,8 @@ import java.net.URI
|
|||
class MastodonAccountApiController(
|
||||
private val accountApiService: AccountApiService,
|
||||
private val transaction: Transaction,
|
||||
private val loginUserContextHolder: LoginUserContextHolder
|
||||
private val loginUserContextHolder: LoginUserContextHolder,
|
||||
private val applicationConfig: ApplicationConfig
|
||||
) : AccountApi {
|
||||
|
||||
override suspend fun apiV1AccountsIdFollowPost(
|
||||
|
@ -68,20 +72,31 @@ class MastodonAccountApiController(
|
|||
tagged: String?
|
||||
): ResponseEntity<Flow<Status>> = runBlocking {
|
||||
val userid = loginUserContextHolder.getLoginUserId()
|
||||
val statusFlow = accountApiService.accountsStatuses(
|
||||
val statuses = accountApiService.accountsStatuses(
|
||||
userid = id.toLong(),
|
||||
maxId = maxId?.toLongOrNull(),
|
||||
sinceId = sinceId?.toLongOrNull(),
|
||||
minId = minId?.toLongOrNull(),
|
||||
limit = limit,
|
||||
onlyMedia = onlyMedia,
|
||||
excludeReplies = excludeReplies,
|
||||
excludeReblogs = excludeReblogs,
|
||||
pinned = pinned,
|
||||
tagged = tagged,
|
||||
loginUser = userid
|
||||
).asFlow()
|
||||
ResponseEntity.ok(statusFlow)
|
||||
loginUser = userid,
|
||||
page = Page.of(
|
||||
maxId?.toLongOrNull(),
|
||||
sinceId?.toLongOrNull(),
|
||||
minId?.toLongOrNull(),
|
||||
limit.coerceIn(0, 80) ?: 40
|
||||
)
|
||||
)
|
||||
val httpHeader = statuses.toHttpHeader(
|
||||
{ "${applicationConfig.url}/api/v1/accounts/$id/statuses?min_id=$it" },
|
||||
{ "${applicationConfig.url}/api/v1/accounts/$id/statuses?max_id=$it" },
|
||||
)
|
||||
|
||||
if (httpHeader != null) {
|
||||
return@runBlocking ResponseEntity.ok().header("Link", httpHeader).body(statuses.asFlow())
|
||||
}
|
||||
|
||||
ResponseEntity.ok(statuses.asFlow())
|
||||
}
|
||||
|
||||
override fun apiV1AccountsRelationshipsGet(
|
||||
|
@ -128,8 +143,7 @@ class MastodonAccountApiController(
|
|||
return ResponseEntity.ok(removeFromFollowers)
|
||||
}
|
||||
|
||||
override suspend fun apiV1AccountsUpdateCredentialsPatch(updateCredentials: UpdateCredentials?):
|
||||
ResponseEntity<Account> {
|
||||
override suspend fun apiV1AccountsUpdateCredentialsPatch(updateCredentials: UpdateCredentials?): ResponseEntity<Account> {
|
||||
val userid = loginUserContextHolder.getLoginUserId()
|
||||
|
||||
val removeFromFollowers = accountApiService.updateProfile(userid, updateCredentials)
|
||||
|
@ -157,10 +171,27 @@ class MastodonAccountApiController(
|
|||
runBlocking {
|
||||
val userid = loginUserContextHolder.getLoginUserId()
|
||||
|
||||
val accountFlow =
|
||||
accountApiService.followRequests(userid, maxId?.toLong(), sinceId?.toLong(), limit ?: 20, false)
|
||||
.asFlow()
|
||||
ResponseEntity.ok(accountFlow)
|
||||
val followRequests = accountApiService.followRequests(
|
||||
userid,
|
||||
false,
|
||||
Page.PageByMaxId(
|
||||
maxId?.toLongOrNull(),
|
||||
sinceId?.toLongOrNull(),
|
||||
limit?.coerceIn(0, 80) ?: 40
|
||||
)
|
||||
|
||||
)
|
||||
|
||||
val httpHeader = followRequests.toHttpHeader(
|
||||
{ "${applicationConfig.url}/api/v1/follow_requests?max_id=$it" },
|
||||
{ "${applicationConfig.url}/api/v1/follow_requests?min_id=$it" },
|
||||
)
|
||||
|
||||
if (httpHeader != null) {
|
||||
return@runBlocking ResponseEntity.ok().header("Link", httpHeader).body(followRequests.asFlow())
|
||||
}
|
||||
|
||||
ResponseEntity.ok(followRequests.asFlow())
|
||||
}
|
||||
|
||||
override suspend fun apiV1AccountsIdMutePost(id: String): ResponseEntity<Relationship> {
|
||||
|
@ -183,9 +214,21 @@ class MastodonAccountApiController(
|
|||
runBlocking {
|
||||
val userid = loginUserContextHolder.getLoginUserId()
|
||||
|
||||
val unmute =
|
||||
accountApiService.mutesAccount(userid, maxId?.toLong(), sinceId?.toLong(), limit ?: 20).asFlow()
|
||||
val mutes =
|
||||
accountApiService.mutesAccount(
|
||||
userid,
|
||||
Page.PageByMaxId(maxId?.toLongOrNull(), sinceId?.toLongOrNull(), limit?.coerceIn(0, 80) ?: 40)
|
||||
)
|
||||
|
||||
return@runBlocking ResponseEntity.ok(unmute)
|
||||
val httpHeader = mutes.toHttpHeader(
|
||||
{ "${applicationConfig.url}/api/v1/mutes?max_id=$it" },
|
||||
{ "${applicationConfig.url}/api/v1/mutes?since_id=$it" },
|
||||
)
|
||||
|
||||
if (httpHeader != null) {
|
||||
return@runBlocking ResponseEntity.ok().header("Link", httpHeader).body(mutes.asFlow())
|
||||
}
|
||||
|
||||
return@runBlocking ResponseEntity.ok(mutes.asFlow())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
package dev.usbharu.hideout.mastodon.interfaces.api.notification
|
||||
|
||||
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.NotificationsApi
|
||||
import dev.usbharu.hideout.core.infrastructure.springframework.security.LoginUserContextHolder
|
||||
import dev.usbharu.hideout.domain.mastodon.model.generated.Notification
|
||||
|
@ -14,7 +17,8 @@ import org.springframework.stereotype.Controller
|
|||
@Controller
|
||||
class MastodonNotificationApiController(
|
||||
private val loginUserContextHolder: LoginUserContextHolder,
|
||||
private val notificationApiService: NotificationApiService
|
||||
private val notificationApiService: NotificationApiService,
|
||||
private val applicationConfig: ApplicationConfig
|
||||
) : NotificationsApi {
|
||||
override suspend fun apiV1NotificationsClearPost(): ResponseEntity<Any> {
|
||||
notificationApiService.clearAll(loginUserContextHolder.getLoginUserId())
|
||||
|
@ -30,17 +34,27 @@ class MastodonNotificationApiController(
|
|||
excludeTypes: List<String>?,
|
||||
accountId: List<String>?
|
||||
): ResponseEntity<Flow<Notification>> = runBlocking {
|
||||
val notificationFlow = notificationApiService.notifications(
|
||||
val notifications = notificationApiService.notifications(
|
||||
loginUser = loginUserContextHolder.getLoginUserId(),
|
||||
maxId = maxId?.toLong(),
|
||||
minId = minId?.toLong(),
|
||||
sinceId = sinceId?.toLong(),
|
||||
limit = limit ?: 20,
|
||||
types = types.orEmpty().mapNotNull { NotificationType.parse(it) },
|
||||
excludeTypes = excludeTypes.orEmpty().mapNotNull { NotificationType.parse(it) },
|
||||
accountId = accountId.orEmpty().mapNotNull { it.toLongOrNull() }
|
||||
).asFlow()
|
||||
ResponseEntity.ok(notificationFlow)
|
||||
accountId = accountId.orEmpty().mapNotNull { it.toLongOrNull() },
|
||||
page = Page.of(
|
||||
maxId?.toLongOrNull(),
|
||||
sinceId?.toLongOrNull(),
|
||||
minId?.toLongOrNull(),
|
||||
limit?.coerceIn(0, 80) ?: 40
|
||||
)
|
||||
)
|
||||
|
||||
val httpHeader = notifications.toHttpHeader(
|
||||
{ "${applicationConfig.url}/api/v1/notifications?min_id=$it" },
|
||||
{ "${applicationConfig.url}/api/v1/notifications?max_id=$it" }
|
||||
) ?: return@runBlocking ResponseEntity.ok(
|
||||
notifications.asFlow()
|
||||
)
|
||||
|
||||
ResponseEntity.ok().header("Link", httpHeader).body(notifications.asFlow())
|
||||
}
|
||||
|
||||
override suspend fun apiV1NotificationsIdDismissPost(id: String): ResponseEntity<Any> {
|
||||
|
|
|
@ -66,16 +66,16 @@ class StatusesRequest {
|
|||
|
||||
override fun toString(): String {
|
||||
return "StatusesRequest(" +
|
||||
"status=$status, " +
|
||||
"media_ids=$media_ids, " +
|
||||
"poll=$poll, " +
|
||||
"in_reply_to_id=$in_reply_to_id, " +
|
||||
"sensitive=$sensitive, " +
|
||||
"spoiler_text=$spoiler_text, " +
|
||||
"visibility=$visibility, " +
|
||||
"language=$language, " +
|
||||
"scheduled_at=$scheduled_at" +
|
||||
")"
|
||||
"status=$status, " +
|
||||
"media_ids=$media_ids, " +
|
||||
"poll=$poll, " +
|
||||
"in_reply_to_id=$in_reply_to_id, " +
|
||||
"sensitive=$sensitive, " +
|
||||
"spoiler_text=$spoiler_text, " +
|
||||
"visibility=$visibility, " +
|
||||
"language=$language, " +
|
||||
"scheduled_at=$scheduled_at" +
|
||||
")"
|
||||
}
|
||||
|
||||
@Suppress("EnumNaming", "EnumEntryNameCase")
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
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.core.infrastructure.springframework.security.LoginUserContextHolder
|
||||
import dev.usbharu.hideout.domain.mastodon.model.generated.Status
|
||||
|
@ -14,7 +17,8 @@ import org.springframework.stereotype.Controller
|
|||
@Controller
|
||||
class MastodonTimelineApiController(
|
||||
private val timelineApiService: TimelineApiService,
|
||||
private val loginUserContextHolder: LoginUserContextHolder
|
||||
private val loginUserContextHolder: LoginUserContextHolder,
|
||||
private val applicationConfig: ApplicationConfig,
|
||||
) : TimelineApi {
|
||||
override fun apiV1TimelinesHomeGet(
|
||||
maxId: String?,
|
||||
|
@ -24,12 +28,22 @@ class MastodonTimelineApiController(
|
|||
): ResponseEntity<Flow<Status>> = runBlocking {
|
||||
val homeTimeline = timelineApiService.homeTimeline(
|
||||
userId = loginUserContextHolder.getLoginUserId(),
|
||||
maxId = maxId?.toLongOrNull(),
|
||||
minId = minId?.toLongOrNull(),
|
||||
sinceId = sinceId?.toLongOrNull(),
|
||||
limit = limit ?: 20
|
||||
page = Page.of(
|
||||
maxId = maxId?.toLongOrNull(),
|
||||
minId = minId?.toLongOrNull(),
|
||||
sinceId = sinceId?.toLongOrNull(),
|
||||
limit = limit?.coerceIn(0, 80) ?: 40
|
||||
)
|
||||
)
|
||||
ResponseEntity(homeTimeline.asFlow(), HttpStatus.OK)
|
||||
|
||||
val httpHeader = homeTimeline.toHttpHeader(
|
||||
{ "${applicationConfig.url}/api/v1/home?max_id=$it" },
|
||||
{ "${applicationConfig.url}/api/v1/home?min_id=$it" }
|
||||
) ?: return@runBlocking ResponseEntity(
|
||||
homeTimeline.asFlow(),
|
||||
HttpStatus.OK
|
||||
)
|
||||
ResponseEntity.ok().header("Link", httpHeader).body(homeTimeline.asFlow())
|
||||
}
|
||||
|
||||
override fun apiV1TimelinesPublicGet(
|
||||
|
@ -45,11 +59,21 @@ class MastodonTimelineApiController(
|
|||
localOnly = local ?: false,
|
||||
remoteOnly = remote ?: false,
|
||||
mediaOnly = onlyMedia ?: false,
|
||||
maxId = maxId?.toLongOrNull(),
|
||||
minId = minId?.toLongOrNull(),
|
||||
sinceId = sinceId?.toLongOrNull(),
|
||||
limit = limit ?: 20
|
||||
page = Page.of(
|
||||
maxId = maxId?.toLongOrNull(),
|
||||
minId = minId?.toLongOrNull(),
|
||||
sinceId = sinceId?.toLongOrNull(),
|
||||
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,5 +1,7 @@
|
|||
package dev.usbharu.hideout.mastodon.query
|
||||
|
||||
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.mastodon.interfaces.api.status.StatusQuery
|
||||
|
||||
|
@ -7,35 +9,17 @@ interface StatusQueryService {
|
|||
suspend fun findByPostIds(ids: List<Long>): List<Status>
|
||||
suspend fun findByPostIdsWithMediaIds(statusQueries: List<StatusQuery>): List<Status>
|
||||
|
||||
/**
|
||||
* アカウントの投稿一覧を取得します
|
||||
*
|
||||
* @param accountId 対象アカウントのid
|
||||
* @param maxId 投稿の最大id
|
||||
* @param sinceId 投稿の最小id
|
||||
* @param minId 不明
|
||||
* @param limit 投稿の最大件数
|
||||
* @param onlyMedia メディア付き投稿のみ
|
||||
* @param excludeReplies 返信を除外
|
||||
* @param excludeReblogs リブログを除外
|
||||
* @param pinned ピン止め投稿のみ
|
||||
* @param tagged タグ付き?
|
||||
* @param includeFollowers フォロワー限定投稿を含める
|
||||
*/
|
||||
@Suppress("LongParameterList")
|
||||
suspend fun accountsStatus(
|
||||
accountId: Long,
|
||||
maxId: Long? = null,
|
||||
sinceId: Long? = null,
|
||||
minId: Long? = null,
|
||||
limit: Int,
|
||||
onlyMedia: Boolean = false,
|
||||
excludeReplies: Boolean = false,
|
||||
excludeReblogs: Boolean = false,
|
||||
pinned: Boolean = false,
|
||||
tagged: String? = null,
|
||||
includeFollowers: Boolean = false
|
||||
): List<Status>
|
||||
tagged: String?,
|
||||
includeFollowers: Boolean = false,
|
||||
page: Page
|
||||
): PaginationList<Status, Long>
|
||||
|
||||
suspend fun findByPostId(id: Long): Status
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package dev.usbharu.hideout.mastodon.service.account
|
||||
|
||||
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.domain.model.relationship.RelationshipRepository
|
||||
import dev.usbharu.hideout.core.service.media.MediaService
|
||||
import dev.usbharu.hideout.core.service.relationship.RelationshipService
|
||||
|
@ -17,20 +19,18 @@ import kotlin.math.min
|
|||
@Service
|
||||
@Suppress("TooManyFunctions")
|
||||
interface AccountApiService {
|
||||
@Suppress("LongParameterList")
|
||||
|
||||
@Suppress("ongParameterList")
|
||||
suspend fun accountsStatuses(
|
||||
userid: Long,
|
||||
maxId: Long?,
|
||||
sinceId: Long?,
|
||||
minId: Long?,
|
||||
limit: Int,
|
||||
onlyMedia: Boolean,
|
||||
excludeReplies: Boolean,
|
||||
excludeReblogs: Boolean,
|
||||
pinned: Boolean,
|
||||
tagged: String?,
|
||||
loginUser: Long?
|
||||
): List<Status>
|
||||
loginUser: Long?,
|
||||
page: Page
|
||||
): PaginationList<Status, Long>
|
||||
|
||||
suspend fun verifyCredentials(userid: Long): CredentialAccount
|
||||
suspend fun registerAccount(userCreateDto: UserCreateDto): Unit
|
||||
|
@ -50,19 +50,18 @@ interface AccountApiService {
|
|||
suspend fun unfollow(userid: Long, target: Long): Relationship
|
||||
suspend fun removeFromFollowers(userid: Long, target: Long): Relationship
|
||||
suspend fun updateProfile(userid: Long, updateCredentials: UpdateCredentials?): Account
|
||||
|
||||
suspend fun followRequests(
|
||||
loginUser: Long,
|
||||
maxId: Long?,
|
||||
sinceId: Long?,
|
||||
limit: Int = 20,
|
||||
withIgnore: Boolean
|
||||
): List<Account>
|
||||
withIgnore: Boolean,
|
||||
pageByMaxId: Page.PageByMaxId
|
||||
): PaginationList<Account, Long>
|
||||
|
||||
suspend fun acceptFollowRequest(loginUser: Long, target: Long): Relationship
|
||||
suspend fun rejectFollowRequest(loginUser: Long, target: Long): Relationship
|
||||
suspend fun mute(userid: Long, target: Long): Relationship
|
||||
suspend fun unmute(userid: Long, target: Long): Relationship
|
||||
suspend fun mutesAccount(userid: Long, maxId: Long?, sinceId: Long?, limit: Int): List<Account>
|
||||
suspend fun mutesAccount(userid: Long, pageByMaxId: Page.PageByMaxId): PaginationList<Account, Long>
|
||||
}
|
||||
|
||||
@Service
|
||||
|
@ -76,21 +75,21 @@ class AccountApiServiceImpl(
|
|||
private val mediaService: MediaService
|
||||
) :
|
||||
AccountApiService {
|
||||
|
||||
override suspend fun accountsStatuses(
|
||||
userid: Long,
|
||||
maxId: Long?,
|
||||
sinceId: Long?,
|
||||
minId: Long?,
|
||||
limit: Int,
|
||||
onlyMedia: Boolean,
|
||||
excludeReplies: Boolean,
|
||||
excludeReblogs: Boolean,
|
||||
pinned: Boolean,
|
||||
tagged: String?,
|
||||
loginUser: Long?
|
||||
): List<Status> {
|
||||
loginUser: Long?,
|
||||
page: Page
|
||||
): PaginationList<Status, Long> {
|
||||
val canViewFollowers = if (loginUser == null) {
|
||||
false
|
||||
} else if (loginUser == userid) {
|
||||
true
|
||||
} else {
|
||||
transaction.transaction {
|
||||
isFollowing(loginUser, userid)
|
||||
|
@ -100,16 +99,13 @@ class AccountApiServiceImpl(
|
|||
return transaction.transaction {
|
||||
statusQueryService.accountsStatus(
|
||||
accountId = userid,
|
||||
maxId = maxId,
|
||||
sinceId = sinceId,
|
||||
minId = minId,
|
||||
limit = limit,
|
||||
onlyMedia = onlyMedia,
|
||||
excludeReplies = excludeReplies,
|
||||
excludeReblogs = excludeReblogs,
|
||||
pinned = pinned,
|
||||
tagged = tagged,
|
||||
includeFollowers = canViewFollowers
|
||||
includeFollowers = canViewFollowers,
|
||||
page = page
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -217,23 +213,19 @@ class AccountApiServiceImpl(
|
|||
|
||||
override suspend fun followRequests(
|
||||
loginUser: Long,
|
||||
maxId: Long?,
|
||||
sinceId: Long?,
|
||||
limit: Int,
|
||||
withIgnore: Boolean
|
||||
): List<Account> = transaction.transaction {
|
||||
val actorIdList = relationshipRepository
|
||||
.findByTargetIdAndFollowRequestAndIgnoreFollowRequest(
|
||||
maxId = maxId,
|
||||
sinceId = sinceId,
|
||||
limit = limit,
|
||||
targetId = loginUser,
|
||||
followRequest = true,
|
||||
ignoreFollowRequest = withIgnore
|
||||
withIgnore: Boolean,
|
||||
pageByMaxId: Page.PageByMaxId
|
||||
): PaginationList<Account, Long> = transaction.transaction {
|
||||
val request =
|
||||
relationshipRepository.findByTargetIdAndFollowRequestAndIgnoreFollowRequest(
|
||||
loginUser,
|
||||
true,
|
||||
withIgnore,
|
||||
pageByMaxId
|
||||
)
|
||||
.map { it.actorId }
|
||||
val actorIds = request.map { it.actorId }
|
||||
|
||||
return@transaction accountService.findByIds(actorIdList)
|
||||
return@transaction PaginationList(accountService.findByIds(actorIds), request.next, request.prev)
|
||||
}
|
||||
|
||||
override suspend fun acceptFollowRequest(loginUser: Long, target: Long): Relationship = transaction.transaction {
|
||||
|
@ -260,11 +252,14 @@ class AccountApiServiceImpl(
|
|||
return@transaction fetchRelationship(userid, target)
|
||||
}
|
||||
|
||||
override suspend fun mutesAccount(userid: Long, maxId: Long?, sinceId: Long?, limit: Int): List<Account> {
|
||||
val mutedAccounts =
|
||||
relationshipRepository.findByActorIdAntMutingAndMaxIdAndSinceId(userid, true, maxId, sinceId, limit)
|
||||
override suspend fun mutesAccount(userid: Long, pageByMaxId: Page.PageByMaxId): PaginationList<Account, Long> {
|
||||
val mutedAccounts = relationshipRepository.findByActorIdAndMuting(userid, true, pageByMaxId)
|
||||
|
||||
return accountService.findByIds(mutedAccounts.map { it.targetActorId })
|
||||
return PaginationList(
|
||||
accountService.findByIds(mutedAccounts.map { it.targetActorId }),
|
||||
mutedAccounts.next,
|
||||
mutedAccounts.prev
|
||||
)
|
||||
}
|
||||
|
||||
private fun from(account: Account): CredentialAccount {
|
||||
|
|
|
@ -19,7 +19,7 @@ class InstanceApiServiceImpl(private val applicationConfig: ApplicationConfig) :
|
|||
title = "Hideout Server",
|
||||
shortDescription = "Hideout test server",
|
||||
description = "This server is operated for testing of Hideout." +
|
||||
" We are not responsible for any events that occur when associating with this server",
|
||||
" We are not responsible for any events that occur when associating with this server",
|
||||
email = "i@usbharu.dev",
|
||||
version = "0.0.1",
|
||||
urls = V1InstanceUrls("wss://${url.host}"),
|
||||
|
|
|
@ -1,20 +1,19 @@
|
|||
package dev.usbharu.hideout.mastodon.service.notification
|
||||
|
||||
import dev.usbharu.hideout.application.infrastructure.exposed.Page
|
||||
import dev.usbharu.hideout.application.infrastructure.exposed.PaginationList
|
||||
import dev.usbharu.hideout.domain.mastodon.model.generated.Notification
|
||||
import dev.usbharu.hideout.mastodon.domain.model.NotificationType
|
||||
|
||||
interface NotificationApiService {
|
||||
@Suppress("LongParameterList")
|
||||
|
||||
suspend fun notifications(
|
||||
loginUser: Long,
|
||||
maxId: Long?,
|
||||
minId: Long?,
|
||||
sinceId: Long?,
|
||||
limit: Int,
|
||||
types: List<NotificationType>,
|
||||
excludeTypes: List<NotificationType>,
|
||||
accountId: List<Long>
|
||||
): List<Notification>
|
||||
accountId: List<Long>,
|
||||
page: Page
|
||||
): PaginationList<Notification, Long>
|
||||
|
||||
suspend fun fingById(loginUser: Long, notificationId: Long): Notification?
|
||||
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package dev.usbharu.hideout.mastodon.service.notification
|
||||
|
||||
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.domain.mastodon.model.generated.Notification
|
||||
import dev.usbharu.hideout.mastodon.domain.model.MastodonNotificationRepository
|
||||
import dev.usbharu.hideout.mastodon.domain.model.NotificationType
|
||||
|
@ -17,30 +19,25 @@ class NotificationApiServiceImpl(
|
|||
private val statusQueryService: StatusQueryService
|
||||
) :
|
||||
NotificationApiService {
|
||||
|
||||
override suspend fun notifications(
|
||||
loginUser: Long,
|
||||
maxId: Long?,
|
||||
minId: Long?,
|
||||
sinceId: Long?,
|
||||
limit: Int,
|
||||
types: List<NotificationType>,
|
||||
excludeTypes: List<NotificationType>,
|
||||
accountId: List<Long>
|
||||
): List<Notification> = transaction.transaction {
|
||||
accountId: List<Long>,
|
||||
page: Page
|
||||
): PaginationList<Notification, Long> = transaction.transaction {
|
||||
val typesTmp = mutableListOf<NotificationType>()
|
||||
|
||||
typesTmp.addAll(types)
|
||||
typesTmp.removeAll(excludeTypes)
|
||||
|
||||
val mastodonNotifications =
|
||||
mastodonNotificationRepository.findByUserIdAndMaxIdAndMinIdAndSinceIdAndInTypesAndInSourceActorId(
|
||||
mastodonNotificationRepository.findByUserIdAndInTypesAndInSourceActorId(
|
||||
loginUser,
|
||||
maxId,
|
||||
minId,
|
||||
sinceId,
|
||||
limit,
|
||||
typesTmp,
|
||||
accountId
|
||||
accountId,
|
||||
page
|
||||
)
|
||||
|
||||
val accounts = accountService.findByIds(
|
||||
|
@ -52,7 +49,7 @@ class NotificationApiServiceImpl(
|
|||
val statuses = statusQueryService.findByPostIds(mastodonNotifications.mapNotNull { it.statusId })
|
||||
.associateBy { it.id.toLong() }
|
||||
|
||||
mastodonNotifications.map {
|
||||
val notifications = mastodonNotifications.map {
|
||||
Notification(
|
||||
id = it.id.toString(),
|
||||
type = convertNotificationType(it.type),
|
||||
|
@ -63,6 +60,8 @@ class NotificationApiServiceImpl(
|
|||
relationshipSeveranceEvent = null
|
||||
)
|
||||
}
|
||||
|
||||
return@transaction PaginationList(notifications, mastodonNotifications.next, mastodonNotifications.prev)
|
||||
}
|
||||
|
||||
override suspend fun fingById(loginUser: Long, notificationId: Long): Notification? {
|
||||
|
|
|
@ -1,29 +1,26 @@
|
|||
package dev.usbharu.hideout.mastodon.service.timeline
|
||||
|
||||
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.domain.mastodon.model.generated.Status
|
||||
import org.springframework.stereotype.Service
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
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>
|
||||
page: Page
|
||||
): PaginationList<Status, Long>
|
||||
|
||||
suspend fun homeTimeline(
|
||||
userId: Long,
|
||||
maxId: Long?,
|
||||
minId: Long?,
|
||||
sinceId: Long?,
|
||||
limit: Int = 20
|
||||
): List<Status>
|
||||
page: Page
|
||||
): PaginationList<Status, Long>
|
||||
}
|
||||
|
||||
@Service
|
||||
|
@ -31,39 +28,18 @@ 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 = 0,
|
||||
localOnly = localOnly,
|
||||
mediaOnly = mediaOnly,
|
||||
maxId = maxId,
|
||||
minId = minId,
|
||||
sinceId = sinceId,
|
||||
limit = limit
|
||||
)
|
||||
page: Page
|
||||
): PaginationList<Status, Long> = transaction.transaction {
|
||||
return@transaction generateTimelineService.getTimeline(forUserId = 0, localOnly, mediaOnly, page)
|
||||
}
|
||||
|
||||
override suspend fun homeTimeline(
|
||||
userId: Long,
|
||||
maxId: Long?,
|
||||
minId: Long?,
|
||||
sinceId: Long?,
|
||||
limit: Int
|
||||
): List<Status> = transaction.transaction {
|
||||
generateTimelineService.getTimeline(
|
||||
forUserId = userId,
|
||||
maxId = maxId,
|
||||
minId = minId,
|
||||
sinceId = sinceId,
|
||||
limit = limit
|
||||
)
|
||||
}
|
||||
override suspend fun homeTimeline(userId: Long, page: Page): PaginationList<Status, Long> =
|
||||
transaction.transaction {
|
||||
return@transaction generateTimelineService.getTimeline(forUserId = userId, page = page)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,9 +7,9 @@ class LruCache<K, V>(private val maxSize: Int) : LinkedHashMap<K, V>(15, 0.75f,
|
|||
override fun removeEldestEntry(eldest: MutableMap.MutableEntry<K, V>?): Boolean = size > maxSize
|
||||
override fun toString(): String {
|
||||
return "LruCache(" +
|
||||
"maxSize=$maxSize" +
|
||||
")" +
|
||||
" ${super.toString()}"
|
||||
"maxSize=$maxSize" +
|
||||
")" +
|
||||
" ${super.toString()}"
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
|
|
@ -573,6 +573,7 @@ paths:
|
|||
required: false
|
||||
schema:
|
||||
type: integer
|
||||
nullable: true
|
||||
default: 20
|
||||
- in: query
|
||||
name: only_media
|
||||
|
@ -1051,7 +1052,6 @@ components:
|
|||
- group
|
||||
- discoverable
|
||||
- created_at
|
||||
- last_status_at
|
||||
- statuses_count
|
||||
- followers_count
|
||||
- followers_count
|
||||
|
@ -1279,6 +1279,7 @@ components:
|
|||
language:
|
||||
type: string
|
||||
nullable: true
|
||||
default: null
|
||||
text:
|
||||
type: string
|
||||
nullable: true
|
||||
|
@ -1316,11 +1317,7 @@ components:
|
|||
- favourites_count
|
||||
- replies_count
|
||||
- url
|
||||
- in_reply_to_id
|
||||
- in_reply_to_account_id
|
||||
- language
|
||||
- text
|
||||
- edited_at
|
||||
|
||||
MediaAttachment:
|
||||
type: object
|
||||
|
|
|
@ -0,0 +1,137 @@
|
|||
package dev.usbharu.hideout.application.infrastructure.exposed
|
||||
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.jetbrains.exposed.sql.*
|
||||
import org.jetbrains.exposed.sql.transactions.transaction
|
||||
import org.junit.jupiter.api.AfterEach
|
||||
import org.junit.jupiter.api.BeforeAll
|
||||
import org.junit.jupiter.api.BeforeEach
|
||||
import org.junit.jupiter.api.Test
|
||||
|
||||
class ExposedPaginationExtensionKtTest {
|
||||
|
||||
@BeforeEach
|
||||
fun setUp(): Unit = transaction {
|
||||
val map = (1..100).map { it to it.toString() }
|
||||
|
||||
ExposePaginationTestTable.batchInsert(map){
|
||||
this[ExposePaginationTestTable.id] = it.first.toLong()
|
||||
this[ExposePaginationTestTable.name] = it.second
|
||||
}
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
fun tearDown():Unit = transaction {
|
||||
ExposePaginationTestTable.deleteAll()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun パラメーター無しでの取得(): Unit = transaction {
|
||||
val pagination: PaginationList<ResultRow,Long> = ExposePaginationTestTable.selectAll().limit(20).withPagination(Page.of(), ExposePaginationTestTable.id)
|
||||
|
||||
assertThat(pagination.next).isEqualTo(100)
|
||||
assertThat(pagination.prev).isEqualTo(81)
|
||||
assertThat(pagination.first()[ExposePaginationTestTable.id]).isEqualTo(100)
|
||||
assertThat(pagination.last()[ExposePaginationTestTable.id]).isEqualTo(81)
|
||||
assertThat(pagination).size().isEqualTo(20)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun maxIdを指定して取得(): Unit = transaction {
|
||||
val pagination: PaginationList<ResultRow,Long> = ExposePaginationTestTable.selectAll().limit(20).withPagination(Page.of(maxId = 100), ExposePaginationTestTable.id)
|
||||
|
||||
assertThat(pagination.next).isEqualTo(99)
|
||||
assertThat(pagination.prev).isEqualTo(80)
|
||||
assertThat(pagination.first()[ExposePaginationTestTable.id]).isEqualTo(99)
|
||||
assertThat(pagination.last()[ExposePaginationTestTable.id]).isEqualTo(80)
|
||||
assertThat(pagination).size().isEqualTo(20)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun sinceIdを指定して取得(): Unit = transaction {
|
||||
val pagination: PaginationList<ResultRow,Long> = ExposePaginationTestTable.selectAll().limit(20).withPagination(Page.of(sinceId = 15), ExposePaginationTestTable.id)
|
||||
|
||||
assertThat(pagination.next).isEqualTo(100)
|
||||
assertThat(pagination.prev).isEqualTo(81)
|
||||
assertThat(pagination.first()[ExposePaginationTestTable.id]).isEqualTo(100)
|
||||
assertThat(pagination.last()[ExposePaginationTestTable.id]).isEqualTo(81)
|
||||
assertThat(pagination).size().isEqualTo(20)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun minIdを指定して取得():Unit = transaction {
|
||||
val pagination: PaginationList<ResultRow,Long> = ExposePaginationTestTable.selectAll().limit(20).withPagination(Page.of(minId = 45), ExposePaginationTestTable.id)
|
||||
|
||||
assertThat(pagination.next).isEqualTo(65)
|
||||
assertThat(pagination.prev).isEqualTo(46)
|
||||
assertThat(pagination.first()[ExposePaginationTestTable.id]).isEqualTo(65)
|
||||
assertThat(pagination.last()[ExposePaginationTestTable.id]).isEqualTo(46)
|
||||
assertThat(pagination).size().isEqualTo(20)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun maxIdとsinceIdを指定して取得(): Unit = transaction {
|
||||
val pagination: PaginationList<ResultRow,Long> = ExposePaginationTestTable.selectAll().limit(20).withPagination(Page.of(maxId = 45, sinceId = 34), ExposePaginationTestTable.id)
|
||||
|
||||
assertThat(pagination.next).isEqualTo(44)
|
||||
assertThat(pagination.prev).isEqualTo(35)
|
||||
assertThat(pagination.first()[ExposePaginationTestTable.id]).isEqualTo(44)
|
||||
assertThat(pagination.last()[ExposePaginationTestTable.id]).isEqualTo(35)
|
||||
assertThat(pagination).size().isEqualTo(10)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun maxIdとminIdを指定して取得():Unit = transaction {
|
||||
val pagination: PaginationList<ResultRow,Long> = ExposePaginationTestTable.selectAll().limit(20).withPagination(Page.of(maxId = 54, minId = 45), ExposePaginationTestTable.id)
|
||||
|
||||
assertThat(pagination.next).isEqualTo(53)
|
||||
assertThat(pagination.prev).isEqualTo(46)
|
||||
assertThat(pagination.first()[ExposePaginationTestTable.id]).isEqualTo(53)
|
||||
assertThat(pagination.last()[ExposePaginationTestTable.id]).isEqualTo(46)
|
||||
assertThat(pagination).size().isEqualTo(8)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun limitを指定して取得():Unit = transaction {
|
||||
val pagination: PaginationList<ResultRow,Long> = ExposePaginationTestTable.selectAll().withPagination(Page.of(limit = 30), ExposePaginationTestTable.id)
|
||||
assertThat(pagination).size().isEqualTo(30)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun 結果が0件の場合はprevとnextがnullになる():Unit = transaction {
|
||||
val pagination = ExposePaginationTestTable.select { ExposePaginationTestTable.id.isNull() }
|
||||
.withPagination(Page.of(), ExposePaginationTestTable.id)
|
||||
|
||||
assertThat(pagination).isEmpty()
|
||||
assertThat(pagination.next).isNull()
|
||||
assertThat(pagination.prev).isNull()
|
||||
}
|
||||
|
||||
object ExposePaginationTestTable : Table(){
|
||||
val id = long("id")
|
||||
val name = varchar("name",100)
|
||||
|
||||
override val primaryKey: PrimaryKey?
|
||||
get() = PrimaryKey(id)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private lateinit var database: Database
|
||||
|
||||
@JvmStatic
|
||||
@BeforeAll
|
||||
fun beforeAll(): Unit {
|
||||
database = Database.connect(
|
||||
url = "jdbc:h2:mem:test;MODE=POSTGRESQL;DB_CLOSE_DELAY=-1;CASE_INSENSITIVE_IDENTIFIERS=true;TRACE_LEVEL_FILE=4;",
|
||||
driver = "org.h2.Driver",
|
||||
user = "sa",
|
||||
password = ""
|
||||
)
|
||||
|
||||
transaction(database) {
|
||||
SchemaUtils.create(ExposePaginationTestTable)
|
||||
SchemaUtils.createMissingTablesAndColumns(ExposePaginationTestTable)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
package dev.usbharu.hideout.application.infrastructure.exposed
|
||||
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.junit.jupiter.api.Assertions.*
|
||||
import org.junit.jupiter.api.Test
|
||||
|
||||
class PageTest {
|
||||
@Test
|
||||
fun minIdが指定されているとsinceIdは無視される() {
|
||||
val page = Page.of(1, 2, 3, 4)
|
||||
|
||||
assertThat(page.maxId).isEqualTo(1)
|
||||
assertThat(page.sinceId).isNull()
|
||||
assertThat(page.minId).isEqualTo(3)
|
||||
assertThat(page.limit).isEqualTo(4)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun minIdがnullのときはsinceIdが使われる() {
|
||||
val page = Page.of(1, 2, null, 4)
|
||||
|
||||
assertThat(page.maxId).isEqualTo(1)
|
||||
assertThat(page.minId).isNull()
|
||||
assertThat(page.sinceId).isEqualTo(2)
|
||||
assertThat(page.limit).isEqualTo(4)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
package dev.usbharu.hideout.application.infrastructure.exposed
|
||||
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.junit.jupiter.api.Assertions.*
|
||||
import org.junit.jupiter.api.Test
|
||||
|
||||
class PaginationListKtTest {
|
||||
@Test
|
||||
fun `toHttpHeader nextとprevがnullでない場合両方作成される`() {
|
||||
val paginationList = PaginationList<String, Long>(emptyList(), 1, 2)
|
||||
|
||||
val httpHeader =
|
||||
paginationList.toHttpHeader({ "https://example.com?max_id=$it" }, { "https://example.com?min_id=$it" })
|
||||
|
||||
assertThat(httpHeader).isEqualTo("<https://example.com?max_id=1>; rel=\"next\", <https://example.com?min_id=2>; rel=\"prev\"")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `toHttpHeader nextがnullなら片方だけ作成される`() {
|
||||
val paginationList = PaginationList<String, Long>(emptyList(), 1,null)
|
||||
|
||||
val httpHeader =
|
||||
paginationList.toHttpHeader({ "https://example.com?max_id=$it" }, { "https://example.com?min_id=$it" })
|
||||
|
||||
assertThat(httpHeader).isEqualTo("<https://example.com?max_id=1>; rel=\"next\"")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `toHttpHeader prevがnullなら片方だけ作成される`() {
|
||||
val paginationList = PaginationList<String, Long>(emptyList(), null,2)
|
||||
|
||||
val httpHeader =
|
||||
paginationList.toHttpHeader({ "https://example.com?max_id=$it" }, { "https://example.com?min_id=$it" })
|
||||
|
||||
assertThat(httpHeader).isEqualTo("<https://example.com?min_id=2>; rel=\"prev\"")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `toHttpHeader 両方nullならnullが返ってくる`() {
|
||||
val paginationList = PaginationList<String, Long>(emptyList(), null, null)
|
||||
|
||||
|
||||
val httpHeader =
|
||||
paginationList.toHttpHeader({ "https://example.com?max_id=$it" }, { "https://example.com?min_id=$it" })
|
||||
|
||||
assertThat(httpHeader).isNull()
|
||||
}
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
package dev.usbharu.hideout.mastodon.interfaces.api.account
|
||||
|
||||
import dev.usbharu.hideout.application.config.ActivityPubConfig
|
||||
import dev.usbharu.hideout.application.config.ApplicationConfig
|
||||
import dev.usbharu.hideout.core.infrastructure.springframework.security.OAuth2JwtLoginUserContextHolder
|
||||
import dev.usbharu.hideout.domain.mastodon.model.generated.AccountSource
|
||||
import dev.usbharu.hideout.domain.mastodon.model.generated.CredentialAccount
|
||||
|
@ -26,6 +27,7 @@ import org.springframework.test.web.servlet.get
|
|||
import org.springframework.test.web.servlet.post
|
||||
import org.springframework.test.web.servlet.setup.MockMvcBuilders
|
||||
import utils.TestTransaction
|
||||
import java.net.URL
|
||||
|
||||
@ExtendWith(MockitoExtension::class)
|
||||
class MastodonAccountApiControllerTest {
|
||||
|
@ -41,6 +43,9 @@ class MastodonAccountApiControllerTest {
|
|||
@Mock
|
||||
private lateinit var accountApiService: AccountApiService
|
||||
|
||||
@Spy
|
||||
private val applicationConfig: ApplicationConfig = ApplicationConfig(URL("https://example.com"))
|
||||
|
||||
@InjectMocks
|
||||
private lateinit var mastodonAccountApiController: MastodonAccountApiController
|
||||
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package dev.usbharu.hideout.mastodon.interfaces.api.timeline
|
||||
|
||||
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
|
||||
import dev.usbharu.hideout.application.config.ApplicationConfig
|
||||
import dev.usbharu.hideout.application.infrastructure.exposed.PaginationList
|
||||
import dev.usbharu.hideout.core.infrastructure.springframework.security.OAuth2JwtLoginUserContextHolder
|
||||
import dev.usbharu.hideout.domain.mastodon.model.generated.Account
|
||||
import dev.usbharu.hideout.domain.mastodon.model.generated.Status
|
||||
|
@ -21,6 +23,7 @@ import org.springframework.test.web.servlet.MockMvc
|
|||
import org.springframework.test.web.servlet.get
|
||||
import org.springframework.test.web.servlet.post
|
||||
import org.springframework.test.web.servlet.setup.MockMvcBuilders
|
||||
import java.net.URL
|
||||
|
||||
@ExtendWith(MockitoExtension::class)
|
||||
class MastodonTimelineApiControllerTest {
|
||||
|
@ -31,6 +34,9 @@ class MastodonTimelineApiControllerTest {
|
|||
@Mock
|
||||
private lateinit var timelineApiService: TimelineApiService
|
||||
|
||||
@Spy
|
||||
private val applicationConfig: ApplicationConfig = ApplicationConfig(URL("https://example.com"))
|
||||
|
||||
@InjectMocks
|
||||
private lateinit var mastodonTimelineApiController: MastodonTimelineApiController
|
||||
|
||||
|
@ -41,107 +47,109 @@ class MastodonTimelineApiControllerTest {
|
|||
mockMvc = MockMvcBuilders.standaloneSetup(mastodonTimelineApiController).build()
|
||||
}
|
||||
|
||||
val statusList = listOf<Status>(
|
||||
Status(
|
||||
id = "",
|
||||
uri = "",
|
||||
createdAt = "",
|
||||
account = Account(
|
||||
val statusList = PaginationList<Status, Long>(
|
||||
listOf<Status>(
|
||||
Status(
|
||||
id = "",
|
||||
username = "",
|
||||
acct = "",
|
||||
url = "",
|
||||
displayName = "",
|
||||
note = "",
|
||||
avatar = "",
|
||||
avatarStatic = "",
|
||||
header = "",
|
||||
headerStatic = "",
|
||||
locked = false,
|
||||
fields = emptyList(),
|
||||
emojis = emptyList(),
|
||||
bot = false,
|
||||
group = false,
|
||||
discoverable = true,
|
||||
uri = "",
|
||||
createdAt = "",
|
||||
lastStatusAt = "",
|
||||
statusesCount = 0,
|
||||
followersCount = 0,
|
||||
noindex = false,
|
||||
moved = false,
|
||||
suspendex = false,
|
||||
limited = false,
|
||||
followingCount = 0
|
||||
),
|
||||
content = "",
|
||||
visibility = Status.Visibility.public,
|
||||
sensitive = false,
|
||||
spoilerText = "",
|
||||
mediaAttachments = emptyList(),
|
||||
mentions = emptyList(),
|
||||
tags = emptyList(),
|
||||
emojis = emptyList(),
|
||||
reblogsCount = 0,
|
||||
favouritesCount = 0,
|
||||
repliesCount = 0,
|
||||
url = "https://example.com",
|
||||
inReplyToId = null,
|
||||
inReplyToAccountId = null,
|
||||
language = "ja_JP",
|
||||
text = "Test",
|
||||
editedAt = null
|
||||
account = Account(
|
||||
id = "",
|
||||
username = "",
|
||||
acct = "",
|
||||
url = "",
|
||||
displayName = "",
|
||||
note = "",
|
||||
avatar = "",
|
||||
avatarStatic = "",
|
||||
header = "",
|
||||
headerStatic = "",
|
||||
locked = false,
|
||||
fields = emptyList(),
|
||||
emojis = emptyList(),
|
||||
bot = false,
|
||||
group = false,
|
||||
discoverable = true,
|
||||
createdAt = "",
|
||||
lastStatusAt = "",
|
||||
statusesCount = 0,
|
||||
followersCount = 0,
|
||||
noindex = false,
|
||||
moved = false,
|
||||
suspendex = false,
|
||||
limited = false,
|
||||
followingCount = 0
|
||||
),
|
||||
content = "",
|
||||
visibility = Status.Visibility.public,
|
||||
sensitive = false,
|
||||
spoilerText = "",
|
||||
mediaAttachments = emptyList(),
|
||||
mentions = emptyList(),
|
||||
tags = emptyList(),
|
||||
emojis = emptyList(),
|
||||
reblogsCount = 0,
|
||||
favouritesCount = 0,
|
||||
repliesCount = 0,
|
||||
url = "https://example.com",
|
||||
inReplyToId = null,
|
||||
inReplyToAccountId = null,
|
||||
language = "ja_JP",
|
||||
text = "Test",
|
||||
editedAt = null
|
||||
|
||||
),
|
||||
Status(
|
||||
id = "",
|
||||
uri = "",
|
||||
createdAt = "",
|
||||
account = Account(
|
||||
),
|
||||
Status(
|
||||
id = "",
|
||||
username = "",
|
||||
acct = "",
|
||||
url = "",
|
||||
displayName = "",
|
||||
note = "",
|
||||
avatar = "",
|
||||
avatarStatic = "",
|
||||
header = "",
|
||||
headerStatic = "",
|
||||
locked = false,
|
||||
fields = emptyList(),
|
||||
emojis = emptyList(),
|
||||
bot = false,
|
||||
group = false,
|
||||
discoverable = true,
|
||||
uri = "",
|
||||
createdAt = "",
|
||||
lastStatusAt = "",
|
||||
statusesCount = 0,
|
||||
followersCount = 0,
|
||||
noindex = false,
|
||||
moved = false,
|
||||
suspendex = false,
|
||||
limited = false,
|
||||
followingCount = 0
|
||||
),
|
||||
content = "",
|
||||
visibility = Status.Visibility.public,
|
||||
sensitive = false,
|
||||
spoilerText = "",
|
||||
mediaAttachments = emptyList(),
|
||||
mentions = emptyList(),
|
||||
tags = emptyList(),
|
||||
emojis = emptyList(),
|
||||
reblogsCount = 0,
|
||||
favouritesCount = 0,
|
||||
repliesCount = 0,
|
||||
url = "https://example.com",
|
||||
inReplyToId = null,
|
||||
inReplyToAccountId = null,
|
||||
language = "ja_JP",
|
||||
text = "Test",
|
||||
editedAt = null
|
||||
account = Account(
|
||||
id = "",
|
||||
username = "",
|
||||
acct = "",
|
||||
url = "",
|
||||
displayName = "",
|
||||
note = "",
|
||||
avatar = "",
|
||||
avatarStatic = "",
|
||||
header = "",
|
||||
headerStatic = "",
|
||||
locked = false,
|
||||
fields = emptyList(),
|
||||
emojis = emptyList(),
|
||||
bot = false,
|
||||
group = false,
|
||||
discoverable = true,
|
||||
createdAt = "",
|
||||
lastStatusAt = "",
|
||||
statusesCount = 0,
|
||||
followersCount = 0,
|
||||
noindex = false,
|
||||
moved = false,
|
||||
suspendex = false,
|
||||
limited = false,
|
||||
followingCount = 0
|
||||
),
|
||||
content = "",
|
||||
visibility = Status.Visibility.public,
|
||||
sensitive = false,
|
||||
spoilerText = "",
|
||||
mediaAttachments = emptyList(),
|
||||
mentions = emptyList(),
|
||||
tags = emptyList(),
|
||||
emojis = emptyList(),
|
||||
reblogsCount = 0,
|
||||
favouritesCount = 0,
|
||||
repliesCount = 0,
|
||||
url = "https://example.com",
|
||||
inReplyToId = null,
|
||||
inReplyToAccountId = null,
|
||||
language = "ja_JP",
|
||||
text = "Test",
|
||||
editedAt = null
|
||||
|
||||
)
|
||||
)
|
||||
), null, null
|
||||
)
|
||||
|
||||
@Test
|
||||
|
@ -156,10 +164,7 @@ class MastodonTimelineApiControllerTest {
|
|||
whenever(
|
||||
timelineApiService.homeTimeline(
|
||||
eq(1234),
|
||||
eq(123456),
|
||||
eq(54321),
|
||||
eq(1234567),
|
||||
eq(20)
|
||||
any()
|
||||
)
|
||||
).doReturn(statusList)
|
||||
|
||||
|
@ -183,10 +188,7 @@ class MastodonTimelineApiControllerTest {
|
|||
whenever(
|
||||
timelineApiService.homeTimeline(
|
||||
eq(1234),
|
||||
isNull(),
|
||||
isNull(),
|
||||
isNull(),
|
||||
eq(20)
|
||||
any()
|
||||
)
|
||||
).doReturn(statusList)
|
||||
|
||||
|
@ -213,10 +215,7 @@ class MastodonTimelineApiControllerTest {
|
|||
localOnly = eq(false),
|
||||
remoteOnly = eq(true),
|
||||
mediaOnly = eq(false),
|
||||
maxId = eq(1234),
|
||||
minId = eq(4321),
|
||||
sinceId = eq(12345),
|
||||
limit = eq(20)
|
||||
any()
|
||||
)
|
||||
).doAnswer {
|
||||
println(it.arguments.joinToString())
|
||||
|
@ -245,10 +244,7 @@ class MastodonTimelineApiControllerTest {
|
|||
localOnly = eq(false),
|
||||
remoteOnly = eq(false),
|
||||
mediaOnly = eq(false),
|
||||
maxId = isNull(),
|
||||
minId = isNull(),
|
||||
sinceId = isNull(),
|
||||
limit = eq(20)
|
||||
any()
|
||||
)
|
||||
).doAnswer {
|
||||
println(it.arguments.joinToString())
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package dev.usbharu.hideout.mastodon.service.account
|
||||
|
||||
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.domain.model.actor.ActorRepository
|
||||
import dev.usbharu.hideout.core.domain.model.relationship.RelationshipRepository
|
||||
import dev.usbharu.hideout.core.query.FollowerQueryService
|
||||
|
@ -48,63 +50,65 @@ class AccountApiServiceImplTest {
|
|||
|
||||
@Mock
|
||||
private lateinit var relationshipRepository: RelationshipRepository
|
||||
|
||||
|
||||
@Mock
|
||||
private lateinit var mediaService: MediaService
|
||||
|
||||
@InjectMocks
|
||||
private lateinit var accountApiServiceImpl: AccountApiServiceImpl
|
||||
|
||||
private val statusList = listOf(
|
||||
Status(
|
||||
id = "",
|
||||
uri = "",
|
||||
createdAt = "",
|
||||
account = Account(
|
||||
private val statusList = PaginationList<Status, Long>(
|
||||
listOf(
|
||||
Status(
|
||||
id = "",
|
||||
username = "",
|
||||
acct = "",
|
||||
url = "",
|
||||
displayName = "",
|
||||
note = "",
|
||||
avatar = "",
|
||||
avatarStatic = "",
|
||||
header = "",
|
||||
headerStatic = "",
|
||||
locked = false,
|
||||
fields = emptyList(),
|
||||
emojis = emptyList(),
|
||||
bot = false,
|
||||
group = false,
|
||||
discoverable = true,
|
||||
uri = "",
|
||||
createdAt = "",
|
||||
lastStatusAt = "",
|
||||
statusesCount = 0,
|
||||
followersCount = 0,
|
||||
noindex = false,
|
||||
moved = false,
|
||||
suspendex = false,
|
||||
limited = false,
|
||||
followingCount = 0
|
||||
),
|
||||
content = "",
|
||||
visibility = Status.Visibility.public,
|
||||
sensitive = false,
|
||||
spoilerText = "",
|
||||
mediaAttachments = emptyList(),
|
||||
mentions = emptyList(),
|
||||
tags = emptyList(),
|
||||
emojis = emptyList(),
|
||||
reblogsCount = 0,
|
||||
favouritesCount = 0,
|
||||
repliesCount = 0,
|
||||
url = "https://example.com",
|
||||
inReplyToId = null,
|
||||
inReplyToAccountId = null,
|
||||
language = "ja_JP",
|
||||
text = "Test",
|
||||
editedAt = null
|
||||
)
|
||||
account = Account(
|
||||
id = "",
|
||||
username = "",
|
||||
acct = "",
|
||||
url = "",
|
||||
displayName = "",
|
||||
note = "",
|
||||
avatar = "",
|
||||
avatarStatic = "",
|
||||
header = "",
|
||||
headerStatic = "",
|
||||
locked = false,
|
||||
fields = emptyList(),
|
||||
emojis = emptyList(),
|
||||
bot = false,
|
||||
group = false,
|
||||
discoverable = true,
|
||||
createdAt = "",
|
||||
lastStatusAt = "",
|
||||
statusesCount = 0,
|
||||
followersCount = 0,
|
||||
noindex = false,
|
||||
moved = false,
|
||||
suspendex = false,
|
||||
limited = false,
|
||||
followingCount = 0
|
||||
),
|
||||
content = "",
|
||||
visibility = Status.Visibility.public,
|
||||
sensitive = false,
|
||||
spoilerText = "",
|
||||
mediaAttachments = emptyList(),
|
||||
mentions = emptyList(),
|
||||
tags = emptyList(),
|
||||
emojis = emptyList(),
|
||||
reblogsCount = 0,
|
||||
favouritesCount = 0,
|
||||
repliesCount = 0,
|
||||
url = "https://example.com",
|
||||
inReplyToId = null,
|
||||
inReplyToAccountId = null,
|
||||
language = "ja_JP",
|
||||
text = "Test",
|
||||
editedAt = null
|
||||
)
|
||||
), null, null
|
||||
)
|
||||
|
||||
@Test
|
||||
|
@ -114,16 +118,13 @@ class AccountApiServiceImplTest {
|
|||
whenever(
|
||||
statusQueryService.accountsStatus(
|
||||
accountId = eq(userId),
|
||||
maxId = isNull(),
|
||||
sinceId = isNull(),
|
||||
minId = isNull(),
|
||||
limit = eq(20),
|
||||
onlyMedia = eq(false),
|
||||
excludeReplies = eq(false),
|
||||
excludeReblogs = eq(false),
|
||||
pinned = eq(false),
|
||||
tagged = isNull(),
|
||||
includeFollowers = eq(false)
|
||||
includeFollowers = eq(false),
|
||||
page = any()
|
||||
)
|
||||
).doReturn(
|
||||
statusList
|
||||
|
@ -132,16 +133,13 @@ class AccountApiServiceImplTest {
|
|||
|
||||
val accountsStatuses = accountApiServiceImpl.accountsStatuses(
|
||||
userid = userId,
|
||||
maxId = null,
|
||||
sinceId = null,
|
||||
minId = null,
|
||||
limit = 20,
|
||||
onlyMedia = false,
|
||||
excludeReplies = false,
|
||||
excludeReblogs = false,
|
||||
pinned = false,
|
||||
tagged = null,
|
||||
loginUser = null
|
||||
loginUser = null,
|
||||
Page.of()
|
||||
)
|
||||
|
||||
assertThat(accountsStatuses).hasSize(1)
|
||||
|
@ -156,31 +154,25 @@ class AccountApiServiceImplTest {
|
|||
whenever(
|
||||
statusQueryService.accountsStatus(
|
||||
accountId = eq(userId),
|
||||
maxId = isNull(),
|
||||
sinceId = isNull(),
|
||||
minId = isNull(),
|
||||
limit = eq(20),
|
||||
onlyMedia = eq(false),
|
||||
excludeReplies = eq(false),
|
||||
excludeReblogs = eq(false),
|
||||
pinned = eq(false),
|
||||
tagged = isNull(),
|
||||
includeFollowers = eq(false)
|
||||
includeFollowers = eq(false),
|
||||
page = any()
|
||||
)
|
||||
).doReturn(statusList)
|
||||
|
||||
val accountsStatuses = accountApiServiceImpl.accountsStatuses(
|
||||
userid = userId,
|
||||
maxId = null,
|
||||
sinceId = null,
|
||||
minId = null,
|
||||
limit = 20,
|
||||
onlyMedia = false,
|
||||
excludeReplies = false,
|
||||
excludeReblogs = false,
|
||||
pinned = false,
|
||||
tagged = null,
|
||||
loginUser = loginUser
|
||||
loginUser = loginUser,
|
||||
Page.of()
|
||||
)
|
||||
|
||||
assertThat(accountsStatuses).hasSize(1)
|
||||
|
@ -193,16 +185,13 @@ class AccountApiServiceImplTest {
|
|||
whenever(
|
||||
statusQueryService.accountsStatus(
|
||||
accountId = eq(userId),
|
||||
maxId = isNull(),
|
||||
sinceId = isNull(),
|
||||
minId = isNull(),
|
||||
limit = eq(20),
|
||||
onlyMedia = eq(false),
|
||||
excludeReplies = eq(false),
|
||||
excludeReblogs = eq(false),
|
||||
pinned = eq(false),
|
||||
tagged = isNull(),
|
||||
includeFollowers = eq(true)
|
||||
includeFollowers = eq(true),
|
||||
page = any()
|
||||
)
|
||||
).doReturn(statusList)
|
||||
|
||||
|
@ -221,16 +210,13 @@ class AccountApiServiceImplTest {
|
|||
|
||||
val accountsStatuses = accountApiServiceImpl.accountsStatuses(
|
||||
userid = userId,
|
||||
maxId = null,
|
||||
sinceId = null,
|
||||
minId = null,
|
||||
limit = 20,
|
||||
onlyMedia = false,
|
||||
excludeReplies = false,
|
||||
excludeReblogs = false,
|
||||
pinned = false,
|
||||
tagged = null,
|
||||
loginUser = loginUser
|
||||
loginUser = loginUser,
|
||||
Page.of()
|
||||
)
|
||||
|
||||
assertThat(accountsStatuses).hasSize(1)
|
||||
|
|
Loading…
Reference in New Issue