mirror of https://github.com/usbharu/Hideout.git
Compare commits
No commits in common. "2b4b33fe8904b6bc662391f777045abaf90ee43e" and "f0dbb83c00bf0beeaa8e09653cfaeba2780d60f9" have entirely different histories.
2b4b33fe89
...
f0dbb83c00
|
@ -78,7 +78,6 @@ fun Application.parent() {
|
||||||
install(httpSignaturePlugin) {
|
install(httpSignaturePlugin) {
|
||||||
keyMap = KtorKeyMap(get())
|
keyMap = KtorKeyMap(get())
|
||||||
}
|
}
|
||||||
expectSuccess = true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
single<IdGenerateService> { TwitterSnowflakeIdGenerateService }
|
single<IdGenerateService> { TwitterSnowflakeIdGenerateService }
|
||||||
|
@ -108,12 +107,12 @@ fun Application.parent() {
|
||||||
inject<JwkProvider>().value,
|
inject<JwkProvider>().value,
|
||||||
)
|
)
|
||||||
configureRouting(
|
configureRouting(
|
||||||
httpSignatureVerifyService = inject<HttpSignatureVerifyService>().value,
|
httpSignatureVerifyService = inject<HttpSignatureVerifyService>().value,
|
||||||
activityPubService = inject<ActivityPubService>().value,
|
activityPubService = inject<ActivityPubService>().value,
|
||||||
userService = inject<IUserService>().value,
|
userService = inject<IUserService>().value,
|
||||||
activityPubUserService = inject<ActivityPubUserService>().value,
|
activityPubUserService = inject<ActivityPubUserService>().value,
|
||||||
postService = inject<IPostApiService>().value,
|
postService = inject<IPostApiService>().value,
|
||||||
userApiService = inject<IUserApiService>().value,
|
userApiService = inject<IUserApiService>().value,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,42 +0,0 @@
|
||||||
package dev.usbharu.hideout.domain.model.ap
|
|
||||||
|
|
||||||
open class Emoji : Object {
|
|
||||||
var updated: String? = null
|
|
||||||
var icon: Image? = null
|
|
||||||
|
|
||||||
protected constructor() : super()
|
|
||||||
constructor(
|
|
||||||
type: List<String>,
|
|
||||||
name: String?,
|
|
||||||
actor: String?,
|
|
||||||
id: String?,
|
|
||||||
updated: String?,
|
|
||||||
icon: Image?
|
|
||||||
) : super(
|
|
||||||
type = add(type, "Emoji"),
|
|
||||||
name = name,
|
|
||||||
actor = actor,
|
|
||||||
id = id
|
|
||||||
) {
|
|
||||||
this.updated = updated
|
|
||||||
this.icon = icon
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun equals(other: Any?): Boolean {
|
|
||||||
if (this === other) return true
|
|
||||||
if (other !is Emoji) return false
|
|
||||||
if (!super.equals(other)) return false
|
|
||||||
|
|
||||||
if (updated != other.updated) return false
|
|
||||||
return icon == other.icon
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun hashCode(): Int {
|
|
||||||
var result = super.hashCode()
|
|
||||||
result = 31 * result + (updated?.hashCode() ?: 0)
|
|
||||||
result = 31 * result + (icon?.hashCode() ?: 0)
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun toString(): String = "Emoji(updated=$updated, icon=$icon) ${super.toString()}"
|
|
||||||
}
|
|
|
@ -1,51 +0,0 @@
|
||||||
package dev.usbharu.hideout.domain.model.ap
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.annotation.JsonDeserialize
|
|
||||||
|
|
||||||
open class Like : Object {
|
|
||||||
var `object`: String? = null
|
|
||||||
var content: String? = null
|
|
||||||
|
|
||||||
@JsonDeserialize(contentUsing = ObjectDeserializer::class)
|
|
||||||
var tag: List<Object> = emptyList()
|
|
||||||
|
|
||||||
protected constructor() : super()
|
|
||||||
constructor(
|
|
||||||
type: List<String>,
|
|
||||||
name: String?,
|
|
||||||
actor: String?,
|
|
||||||
id: String?,
|
|
||||||
`object`: String?,
|
|
||||||
content: String?,
|
|
||||||
tag: List<Object>
|
|
||||||
) : super(
|
|
||||||
type = add(type, "Like"),
|
|
||||||
name = name,
|
|
||||||
actor = actor,
|
|
||||||
id = id
|
|
||||||
) {
|
|
||||||
this.`object` = `object`
|
|
||||||
this.content = content
|
|
||||||
this.tag = tag
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun equals(other: Any?): Boolean {
|
|
||||||
if (this === other) return true
|
|
||||||
if (other !is Like) return false
|
|
||||||
if (!super.equals(other)) return false
|
|
||||||
|
|
||||||
if (`object` != other.`object`) return false
|
|
||||||
if (content != other.content) return false
|
|
||||||
return tag == other.tag
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun hashCode(): Int {
|
|
||||||
var result = super.hashCode()
|
|
||||||
result = 31 * result + (`object`?.hashCode() ?: 0)
|
|
||||||
result = 31 * result + (content?.hashCode() ?: 0)
|
|
||||||
result = 31 * result + tag.hashCode()
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun toString(): String = "Like(`object`=$`object`, content=$content, tag=$tag) ${super.toString()}"
|
|
||||||
}
|
|
|
@ -4,7 +4,7 @@ import com.fasterxml.jackson.core.JsonParser
|
||||||
import com.fasterxml.jackson.databind.DeserializationContext
|
import com.fasterxml.jackson.databind.DeserializationContext
|
||||||
import com.fasterxml.jackson.databind.JsonDeserializer
|
import com.fasterxml.jackson.databind.JsonDeserializer
|
||||||
import com.fasterxml.jackson.databind.JsonNode
|
import com.fasterxml.jackson.databind.JsonNode
|
||||||
import dev.usbharu.hideout.service.activitypub.ExtendedActivityVocabulary
|
import dev.usbharu.hideout.service.activitypub.ActivityVocabulary
|
||||||
|
|
||||||
class ObjectDeserializer : JsonDeserializer<Object>() {
|
class ObjectDeserializer : JsonDeserializer<Object>() {
|
||||||
override fun deserialize(p: JsonParser?, ctxt: DeserializationContext?): Object {
|
override fun deserialize(p: JsonParser?, ctxt: DeserializationContext?): Object {
|
||||||
|
@ -22,78 +22,28 @@ class ObjectDeserializer : JsonDeserializer<Object>() {
|
||||||
val type = treeNode["type"]
|
val type = treeNode["type"]
|
||||||
val activityType = if (type.isArray) {
|
val activityType = if (type.isArray) {
|
||||||
type.firstNotNullOf { jsonNode: JsonNode ->
|
type.firstNotNullOf { jsonNode: JsonNode ->
|
||||||
ExtendedActivityVocabulary.values().firstOrNull { it.name.equals(jsonNode.asText(), true) }
|
ActivityVocabulary.values().firstOrNull { it.name.equals(jsonNode.asText(), true) }
|
||||||
}
|
}
|
||||||
} else if (type.isValueNode) {
|
} else if (type.isValueNode) {
|
||||||
ExtendedActivityVocabulary.values().first { it.name.equals(type.asText(), true) }
|
ActivityVocabulary.values().first { it.name.equals(type.asText(), true) }
|
||||||
} else {
|
} else {
|
||||||
TODO()
|
TODO()
|
||||||
}
|
}
|
||||||
|
|
||||||
return when (activityType) {
|
return when (activityType) {
|
||||||
ExtendedActivityVocabulary.Follow -> {
|
ActivityVocabulary.Follow -> {
|
||||||
val readValue = p.codec.treeToValue(treeNode, Follow::class.java)
|
val readValue = p.codec.treeToValue(treeNode, Follow::class.java)
|
||||||
println(readValue)
|
println(readValue)
|
||||||
readValue
|
readValue
|
||||||
}
|
}
|
||||||
|
|
||||||
ExtendedActivityVocabulary.Note -> {
|
ActivityVocabulary.Note -> {
|
||||||
p.codec.treeToValue(treeNode, Note::class.java)
|
p.codec.treeToValue(treeNode, Note::class.java)
|
||||||
}
|
}
|
||||||
|
|
||||||
ExtendedActivityVocabulary.Object -> p.codec.treeToValue(treeNode, Object::class.java)
|
else -> {
|
||||||
ExtendedActivityVocabulary.Link -> TODO()
|
TODO()
|
||||||
ExtendedActivityVocabulary.Activity -> TODO()
|
}
|
||||||
ExtendedActivityVocabulary.IntransitiveActivity -> TODO()
|
|
||||||
ExtendedActivityVocabulary.Collection -> TODO()
|
|
||||||
ExtendedActivityVocabulary.OrderedCollection -> TODO()
|
|
||||||
ExtendedActivityVocabulary.CollectionPage -> TODO()
|
|
||||||
ExtendedActivityVocabulary.OrderedCollectionPage -> TODO()
|
|
||||||
ExtendedActivityVocabulary.Accept -> p.codec.treeToValue(treeNode, Accept::class.java)
|
|
||||||
ExtendedActivityVocabulary.Add -> TODO()
|
|
||||||
ExtendedActivityVocabulary.Announce -> TODO()
|
|
||||||
ExtendedActivityVocabulary.Arrive -> TODO()
|
|
||||||
ExtendedActivityVocabulary.Block -> TODO()
|
|
||||||
ExtendedActivityVocabulary.Create -> p.codec.treeToValue(treeNode, Create::class.java)
|
|
||||||
ExtendedActivityVocabulary.Delete -> TODO()
|
|
||||||
ExtendedActivityVocabulary.Dislike -> TODO()
|
|
||||||
ExtendedActivityVocabulary.Flag -> TODO()
|
|
||||||
ExtendedActivityVocabulary.Ignore -> TODO()
|
|
||||||
ExtendedActivityVocabulary.Invite -> TODO()
|
|
||||||
ExtendedActivityVocabulary.Join -> TODO()
|
|
||||||
ExtendedActivityVocabulary.Leave -> TODO()
|
|
||||||
ExtendedActivityVocabulary.Like -> p.codec.treeToValue(treeNode, Like::class.java)
|
|
||||||
ExtendedActivityVocabulary.Listen -> TODO()
|
|
||||||
ExtendedActivityVocabulary.Move -> TODO()
|
|
||||||
ExtendedActivityVocabulary.Offer -> TODO()
|
|
||||||
ExtendedActivityVocabulary.Question -> TODO()
|
|
||||||
ExtendedActivityVocabulary.Reject -> TODO()
|
|
||||||
ExtendedActivityVocabulary.Read -> TODO()
|
|
||||||
ExtendedActivityVocabulary.Remove -> TODO()
|
|
||||||
ExtendedActivityVocabulary.TentativeReject -> TODO()
|
|
||||||
ExtendedActivityVocabulary.TentativeAccept -> TODO()
|
|
||||||
ExtendedActivityVocabulary.Travel -> TODO()
|
|
||||||
ExtendedActivityVocabulary.Undo -> p.codec.treeToValue(treeNode, Undo::class.java)
|
|
||||||
ExtendedActivityVocabulary.Update -> TODO()
|
|
||||||
ExtendedActivityVocabulary.View -> TODO()
|
|
||||||
ExtendedActivityVocabulary.Application -> TODO()
|
|
||||||
ExtendedActivityVocabulary.Group -> TODO()
|
|
||||||
ExtendedActivityVocabulary.Organization -> TODO()
|
|
||||||
ExtendedActivityVocabulary.Person -> p.codec.treeToValue(treeNode, Person::class.java)
|
|
||||||
ExtendedActivityVocabulary.Service -> TODO()
|
|
||||||
ExtendedActivityVocabulary.Article -> TODO()
|
|
||||||
ExtendedActivityVocabulary.Audio -> TODO()
|
|
||||||
ExtendedActivityVocabulary.Document -> TODO()
|
|
||||||
ExtendedActivityVocabulary.Event -> TODO()
|
|
||||||
ExtendedActivityVocabulary.Image -> p.codec.treeToValue(treeNode, Image::class.java)
|
|
||||||
ExtendedActivityVocabulary.Page -> TODO()
|
|
||||||
ExtendedActivityVocabulary.Place -> TODO()
|
|
||||||
ExtendedActivityVocabulary.Profile -> TODO()
|
|
||||||
ExtendedActivityVocabulary.Relationship -> TODO()
|
|
||||||
ExtendedActivityVocabulary.Tombstone -> TODO()
|
|
||||||
ExtendedActivityVocabulary.Video -> TODO()
|
|
||||||
ExtendedActivityVocabulary.Mention -> TODO()
|
|
||||||
ExtendedActivityVocabulary.Emoji -> p.codec.treeToValue(treeNode, Emoji::class.java)
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
TODO()
|
TODO()
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
package dev.usbharu.hideout.domain.model.hideout.entity
|
|
||||||
|
|
||||||
data class Reaction(val id: Long, val emojiId: Long, val postId: Long, val userId: Long)
|
|
|
@ -44,12 +44,10 @@ suspend fun HttpClient.postAp(urlString: String, username: String, jsonLd: JsonL
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun HttpClient.getAp(urlString: String, username: String?): HttpResponse {
|
suspend fun HttpClient.getAp(urlString: String, username: String): HttpResponse {
|
||||||
return this.get(urlString) {
|
return this.get(urlString) {
|
||||||
header("Accept", ContentType.Application.Activity)
|
header("Accept", ContentType.Application.Activity)
|
||||||
username?.let {
|
header("Signature", "keyId=\"$username\",algorithm=\"rsa-sha256\",headers=\"(request-target) host date\"")
|
||||||
header("Signature", "keyId=\"$username\",algorithm=\"rsa-sha256\",headers=\"(request-target) host date\"")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,12 +18,12 @@ import io.ktor.server.routing.*
|
||||||
|
|
||||||
@Suppress("LongParameterList")
|
@Suppress("LongParameterList")
|
||||||
fun Application.configureRouting(
|
fun Application.configureRouting(
|
||||||
httpSignatureVerifyService: HttpSignatureVerifyService,
|
httpSignatureVerifyService: HttpSignatureVerifyService,
|
||||||
activityPubService: ActivityPubService,
|
activityPubService: ActivityPubService,
|
||||||
userService: IUserService,
|
userService: IUserService,
|
||||||
activityPubUserService: ActivityPubUserService,
|
activityPubUserService: ActivityPubUserService,
|
||||||
postService: IPostApiService,
|
postService: IPostApiService,
|
||||||
userApiService: IUserApiService
|
userApiService: IUserApiService
|
||||||
) {
|
) {
|
||||||
install(AutoHeadResponse)
|
install(AutoHeadResponse)
|
||||||
routing {
|
routing {
|
||||||
|
|
|
@ -11,33 +11,33 @@ interface IPostRepository {
|
||||||
suspend fun findByUrl(url: String): Post?
|
suspend fun findByUrl(url: String): Post?
|
||||||
suspend fun delete(id: Long)
|
suspend fun delete(id: Long)
|
||||||
suspend fun findAll(
|
suspend fun findAll(
|
||||||
since: Instant?,
|
since: Instant?,
|
||||||
until: Instant?,
|
until: Instant?,
|
||||||
minId: Long?,
|
minId: Long?,
|
||||||
maxId: Long?,
|
maxId: Long?,
|
||||||
limit: Int?,
|
limit: Int?,
|
||||||
userId: Long?
|
userId: Long?
|
||||||
): List<Post>
|
): List<Post>
|
||||||
|
|
||||||
suspend fun findByUserNameAndDomain(
|
suspend fun findByUserNameAndDomain(
|
||||||
username: String,
|
username: String,
|
||||||
s: String,
|
s: String,
|
||||||
since: Instant?,
|
since: Instant?,
|
||||||
until: Instant?,
|
until: Instant?,
|
||||||
minId: Long?,
|
minId: Long?,
|
||||||
maxId: Long?,
|
maxId: Long?,
|
||||||
limit: Int?,
|
limit: Int?,
|
||||||
userId: Long?
|
userId: Long?
|
||||||
): List<Post>
|
): List<Post>
|
||||||
|
|
||||||
suspend fun findByUserId(
|
suspend fun findByUserId(
|
||||||
idOrNull: Long,
|
idOrNull: Long,
|
||||||
since: Instant?,
|
since: Instant?,
|
||||||
until: Instant?,
|
until: Instant?,
|
||||||
minId: Long?,
|
minId: Long?,
|
||||||
maxId: Long?,
|
maxId: Long?,
|
||||||
limit: Int?,
|
limit: Int?,
|
||||||
userId: Long?
|
userId: Long?
|
||||||
): List<Post>
|
): List<Post>
|
||||||
|
|
||||||
suspend fun findByApId(id: String): Post?
|
suspend fun findByApId(id: String): Post?
|
||||||
|
|
|
@ -63,9 +63,7 @@ class PostRepositoryImpl(database: Database, private val idGenerateService: IdGe
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun findOneById(id: Long, userId: Long?): Post? {
|
override suspend fun findOneById(id: Long, userId: Long?): Post? {
|
||||||
return query {
|
TODO("Not yet implemented")
|
||||||
Posts.select { Posts.id eq id }.singleOrNull()?.toPost()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun findByUrl(url: String): Post? {
|
override suspend fun findByUrl(url: String): Post? {
|
||||||
|
@ -81,37 +79,37 @@ class PostRepositoryImpl(database: Database, private val idGenerateService: IdGe
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun findAll(
|
override suspend fun findAll(
|
||||||
since: Instant?,
|
since: Instant?,
|
||||||
until: Instant?,
|
until: Instant?,
|
||||||
minId: Long?,
|
minId: Long?,
|
||||||
maxId: Long?,
|
maxId: Long?,
|
||||||
limit: Int?,
|
limit: Int?,
|
||||||
userId: Long?
|
userId: Long?
|
||||||
): List<Post> {
|
): List<Post> {
|
||||||
TODO("Not yet implemented")
|
TODO("Not yet implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun findByUserNameAndDomain(
|
override suspend fun findByUserNameAndDomain(
|
||||||
username: String,
|
username: String,
|
||||||
s: String,
|
s: String,
|
||||||
since: Instant?,
|
since: Instant?,
|
||||||
until: Instant?,
|
until: Instant?,
|
||||||
minId: Long?,
|
minId: Long?,
|
||||||
maxId: Long?,
|
maxId: Long?,
|
||||||
limit: Int?,
|
limit: Int?,
|
||||||
userId: Long?
|
userId: Long?
|
||||||
): List<Post> {
|
): List<Post> {
|
||||||
TODO("Not yet implemented")
|
TODO("Not yet implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun findByUserId(
|
override suspend fun findByUserId(
|
||||||
idOrNull: Long,
|
idOrNull: Long,
|
||||||
since: Instant?,
|
since: Instant?,
|
||||||
until: Instant?,
|
until: Instant?,
|
||||||
minId: Long?,
|
minId: Long?,
|
||||||
maxId: Long?,
|
maxId: Long?,
|
||||||
limit: Int?,
|
limit: Int?,
|
||||||
userId: Long?
|
userId: Long?
|
||||||
): List<Post> {
|
): List<Post> {
|
||||||
TODO("Not yet implemented")
|
TODO("Not yet implemented")
|
||||||
}
|
}
|
||||||
|
@ -140,16 +138,16 @@ object Posts : Table() {
|
||||||
|
|
||||||
fun ResultRow.toPost(): Post {
|
fun ResultRow.toPost(): Post {
|
||||||
return Post(
|
return Post(
|
||||||
id = this[Posts.id],
|
id = this[Posts.id],
|
||||||
userId = this[Posts.userId],
|
userId = this[Posts.userId],
|
||||||
overview = this[Posts.overview],
|
overview = this[Posts.overview],
|
||||||
text = this[Posts.text],
|
text = this[Posts.text],
|
||||||
createdAt = this[Posts.createdAt],
|
createdAt = this[Posts.createdAt],
|
||||||
visibility = Visibility.values().first { visibility -> visibility.ordinal == this[Posts.visibility] },
|
visibility = Visibility.values().first { visibility -> visibility.ordinal == this[Posts.visibility] },
|
||||||
url = this[Posts.url],
|
url = this[Posts.url],
|
||||||
repostId = this[Posts.repostId],
|
repostId = this[Posts.repostId],
|
||||||
replyId = this[Posts.replyId],
|
replyId = this[Posts.replyId],
|
||||||
sensitive = this[Posts.sensitive],
|
sensitive = this[Posts.sensitive],
|
||||||
apId = this[Posts.apId]
|
apId = this[Posts.apId]
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +0,0 @@
|
||||||
package dev.usbharu.hideout.repository
|
|
||||||
|
|
||||||
import dev.usbharu.hideout.domain.model.hideout.entity.Reaction
|
|
||||||
|
|
||||||
interface ReactionRepository {
|
|
||||||
suspend fun generateId(): Long
|
|
||||||
suspend fun save(reaction: Reaction): Reaction
|
|
||||||
suspend fun reactionAlreadyExist(postId: Long, userId: Long, emojiId: Long): Boolean
|
|
||||||
}
|
|
|
@ -1,79 +0,0 @@
|
||||||
package dev.usbharu.hideout.repository
|
|
||||||
|
|
||||||
import dev.usbharu.hideout.domain.model.hideout.entity.Reaction
|
|
||||||
import dev.usbharu.hideout.service.core.IdGenerateService
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import org.jetbrains.exposed.dao.id.LongIdTable
|
|
||||||
import org.jetbrains.exposed.sql.*
|
|
||||||
import org.jetbrains.exposed.sql.transactions.experimental.newSuspendedTransaction
|
|
||||||
import org.jetbrains.exposed.sql.transactions.transaction
|
|
||||||
import org.koin.core.annotation.Single
|
|
||||||
|
|
||||||
@Single
|
|
||||||
class ReactionRepositoryImpl(
|
|
||||||
private val database: Database,
|
|
||||||
private val idGenerateService: IdGenerateService
|
|
||||||
) : ReactionRepository {
|
|
||||||
|
|
||||||
init {
|
|
||||||
transaction(database) {
|
|
||||||
SchemaUtils.create(Reactions)
|
|
||||||
SchemaUtils.createMissingTablesAndColumns(Reactions)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Suppress("InjectDispatcher")
|
|
||||||
suspend fun <T> query(block: suspend () -> T): T =
|
|
||||||
newSuspendedTransaction(Dispatchers.IO) { block() }
|
|
||||||
|
|
||||||
override suspend fun generateId(): Long = idGenerateService.generateId()
|
|
||||||
|
|
||||||
override suspend fun save(reaction: Reaction): Reaction {
|
|
||||||
query {
|
|
||||||
if (Reactions.select { Reactions.id eq reaction.id }.empty()) {
|
|
||||||
Reactions.insert {
|
|
||||||
it[id] = reaction.id
|
|
||||||
it[emojiId] = reaction.emojiId
|
|
||||||
it[postId] = reaction.postId
|
|
||||||
it[userId] = reaction.userId
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Reactions.update({ Reactions.id eq reaction.id }) {
|
|
||||||
it[emojiId] = reaction.emojiId
|
|
||||||
it[postId] = reaction.postId
|
|
||||||
it[userId] = reaction.userId
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return reaction
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun reactionAlreadyExist(postId: Long, userId: Long, emojiId: Long): Boolean {
|
|
||||||
return query {
|
|
||||||
Reactions.select {
|
|
||||||
Reactions.postId.eq(postId).and(Reactions.userId.eq(userId)).and(
|
|
||||||
Reactions.emojiId.eq(emojiId)
|
|
||||||
)
|
|
||||||
}.empty().not()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun ResultRow.toReaction(): Reaction {
|
|
||||||
return Reaction(
|
|
||||||
this[Reactions.id].value,
|
|
||||||
this[Reactions.emojiId],
|
|
||||||
this[Reactions.postId],
|
|
||||||
this[Reactions.userId]
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
object Reactions : LongIdTable("reactions") {
|
|
||||||
val emojiId = long("emoji_id")
|
|
||||||
val postId = long("post_id").references(Posts.id)
|
|
||||||
val userId = long("user_id").references(Users.id)
|
|
||||||
|
|
||||||
init {
|
|
||||||
uniqueIndex(emojiId, postId, userId)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -51,14 +51,14 @@ fun Route.posts(postApiService: IPostApiService) {
|
||||||
get {
|
get {
|
||||||
val userId = call.principal<JWTPrincipal>()?.payload?.getClaim("uid")?.asLong()
|
val userId = call.principal<JWTPrincipal>()?.payload?.getClaim("uid")?.asLong()
|
||||||
val targetUserName = call.parameters["name"]
|
val targetUserName = call.parameters["name"]
|
||||||
?: throw ParameterNotExistException("Parameter(name='userName@domain') does not exist.")
|
?: throw ParameterNotExistException("Parameter(name='userName@domain') does not exist.")
|
||||||
val posts = postApiService.getByUser(targetUserName, userId = userId)
|
val posts = postApiService.getByUser(targetUserName, userId = userId)
|
||||||
call.respond(posts)
|
call.respond(posts)
|
||||||
}
|
}
|
||||||
get("/{id}") {
|
get("/{id}") {
|
||||||
val userId = call.principal<JWTPrincipal>()?.payload?.getClaim("uid")?.asLong()
|
val userId = call.principal<JWTPrincipal>()?.payload?.getClaim("uid")?.asLong()
|
||||||
val id = call.parameters["id"]?.toLong()
|
val id = call.parameters["id"]?.toLong()
|
||||||
?: throw ParameterNotExistException("Parameter(name='postsId' does not exist.")
|
?: throw ParameterNotExistException("Parameter(name='postsId' does not exist.")
|
||||||
val post = postApiService.getById(id, userId)
|
val post = postApiService.getById(id, userId)
|
||||||
call.respond(post)
|
call.respond(post)
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,9 +43,9 @@ fun Route.users(userService: IUserService, userApiService: IUserApiService) {
|
||||||
get {
|
get {
|
||||||
val userParameter = (
|
val userParameter = (
|
||||||
call.parameters["name"]
|
call.parameters["name"]
|
||||||
?: throw ParameterNotExistException(
|
?: throw ParameterNotExistException(
|
||||||
"Parameter(name='userName@domain') does not exist."
|
"Parameter(name='userName@domain') does not exist."
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
if (userParameter.toLongOrNull() != null) {
|
if (userParameter.toLongOrNull() != null) {
|
||||||
return@get call.respond(userApiService.findById(userParameter.toLong()))
|
return@get call.respond(userApiService.findById(userParameter.toLong()))
|
||||||
|
@ -93,9 +93,9 @@ fun Route.users(userService: IUserService, userApiService: IUserApiService) {
|
||||||
get {
|
get {
|
||||||
val userParameter = (
|
val userParameter = (
|
||||||
call.parameters["name"]
|
call.parameters["name"]
|
||||||
?: throw ParameterNotExistException(
|
?: throw ParameterNotExistException(
|
||||||
"Parameter(name='userName@domain') does not exist."
|
"Parameter(name='userName@domain') does not exist."
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
if (userParameter.toLongOrNull() != null) {
|
if (userParameter.toLongOrNull() != null) {
|
||||||
return@get call.respond(userApiService.findFollowings(userParameter.toLong()))
|
return@get call.respond(userApiService.findFollowings(userParameter.toLong()))
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
package dev.usbharu.hideout.service.activitypub
|
|
||||||
|
|
||||||
import dev.usbharu.hideout.domain.model.ActivityPubResponse
|
|
||||||
import dev.usbharu.hideout.domain.model.ap.Like
|
|
||||||
|
|
||||||
interface ActivityPubLikeService {
|
|
||||||
suspend fun receiveLike(like: Like): ActivityPubResponse
|
|
||||||
}
|
|
|
@ -1,40 +0,0 @@
|
||||||
package dev.usbharu.hideout.service.activitypub
|
|
||||||
|
|
||||||
import dev.usbharu.hideout.domain.model.ActivityPubResponse
|
|
||||||
import dev.usbharu.hideout.domain.model.ActivityPubStringResponse
|
|
||||||
import dev.usbharu.hideout.domain.model.ap.Like
|
|
||||||
import dev.usbharu.hideout.exception.PostNotFoundException
|
|
||||||
import dev.usbharu.hideout.exception.ap.IllegalActivityPubObjectException
|
|
||||||
import dev.usbharu.hideout.repository.IPostRepository
|
|
||||||
import dev.usbharu.hideout.service.reaction.IReactionService
|
|
||||||
import dev.usbharu.hideout.service.user.IUserService
|
|
||||||
import io.ktor.http.*
|
|
||||||
import org.koin.core.annotation.Single
|
|
||||||
|
|
||||||
@Single
|
|
||||||
class ActivityPubLikeServiceImpl(
|
|
||||||
private val reactionService: IReactionService,
|
|
||||||
private val activityPubUserService: ActivityPubUserService,
|
|
||||||
private val userService: IUserService,
|
|
||||||
private val postService: IPostRepository,
|
|
||||||
private val activityPubNoteService: ActivityPubNoteService
|
|
||||||
) : ActivityPubLikeService {
|
|
||||||
override suspend fun receiveLike(like: Like): ActivityPubResponse {
|
|
||||||
val actor = like.actor ?: throw IllegalActivityPubObjectException("actor is null")
|
|
||||||
val content = like.content ?: throw IllegalActivityPubObjectException("content is null")
|
|
||||||
like.`object` ?: throw IllegalActivityPubObjectException("object is null")
|
|
||||||
val person = activityPubUserService.fetchPerson(actor)
|
|
||||||
activityPubNoteService.fetchNote(like.`object`!!)
|
|
||||||
|
|
||||||
val user = userService.findByUrl(
|
|
||||||
person.url
|
|
||||||
?: throw IllegalActivityPubObjectException("actor is not found")
|
|
||||||
)
|
|
||||||
|
|
||||||
val post = postService.findByUrl(like.`object`!!)
|
|
||||||
?: throw PostNotFoundException("${like.`object`} was not found")
|
|
||||||
|
|
||||||
reactionService.receiveReaction(content, actor.substringAfter("://").substringBefore("/"), user.id, post.id)
|
|
||||||
return ActivityPubStringResponse(HttpStatusCode.OK, "")
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -14,7 +14,7 @@ import dev.usbharu.hideout.repository.IPostRepository
|
||||||
import dev.usbharu.hideout.service.job.JobQueueParentService
|
import dev.usbharu.hideout.service.job.JobQueueParentService
|
||||||
import dev.usbharu.hideout.service.user.IUserService
|
import dev.usbharu.hideout.service.user.IUserService
|
||||||
import io.ktor.client.*
|
import io.ktor.client.*
|
||||||
import io.ktor.client.statement.*
|
import io.ktor.client.call.*
|
||||||
import kjob.core.job.JobProps
|
import kjob.core.job.JobProps
|
||||||
import org.koin.core.annotation.Single
|
import org.koin.core.annotation.Single
|
||||||
import org.slf4j.LoggerFactory
|
import org.slf4j.LoggerFactory
|
||||||
|
@ -22,11 +22,11 @@ import java.time.Instant
|
||||||
|
|
||||||
@Single
|
@Single
|
||||||
class ActivityPubNoteServiceImpl(
|
class ActivityPubNoteServiceImpl(
|
||||||
private val httpClient: HttpClient,
|
private val httpClient: HttpClient,
|
||||||
private val jobQueueParentService: JobQueueParentService,
|
private val jobQueueParentService: JobQueueParentService,
|
||||||
private val userService: IUserService,
|
private val userService: IUserService,
|
||||||
private val postRepository: IPostRepository,
|
private val postRepository: IPostRepository,
|
||||||
private val activityPubUserService: ActivityPubUserService
|
private val activityPubUserService: ActivityPubUserService
|
||||||
) : ActivityPubNoteService {
|
) : ActivityPubNoteService {
|
||||||
|
|
||||||
private val logger = LoggerFactory.getLogger(this::class.java)
|
private val logger = LoggerFactory.getLogger(this::class.java)
|
||||||
|
@ -48,24 +48,24 @@ class ActivityPubNoteServiceImpl(
|
||||||
val actor = props[DeliverPostJob.actor]
|
val actor = props[DeliverPostJob.actor]
|
||||||
val postEntity = Config.configData.objectMapper.readValue<Post>(props[DeliverPostJob.post])
|
val postEntity = Config.configData.objectMapper.readValue<Post>(props[DeliverPostJob.post])
|
||||||
val note = Note(
|
val note = Note(
|
||||||
name = "Note",
|
name = "Note",
|
||||||
id = postEntity.url,
|
id = postEntity.url,
|
||||||
attributedTo = actor,
|
attributedTo = actor,
|
||||||
content = postEntity.text,
|
content = postEntity.text,
|
||||||
published = Instant.ofEpochMilli(postEntity.createdAt).toString(),
|
published = Instant.ofEpochMilli(postEntity.createdAt).toString(),
|
||||||
to = listOf(public, actor + "/follower")
|
to = listOf(public, actor + "/follower")
|
||||||
)
|
)
|
||||||
val inbox = props[DeliverPostJob.inbox]
|
val inbox = props[DeliverPostJob.inbox]
|
||||||
logger.debug("createNoteJob: actor={}, note={}, inbox={}", actor, postEntity, inbox)
|
logger.debug("createNoteJob: actor={}, note={}, inbox={}", actor, postEntity, inbox)
|
||||||
httpClient.postAp(
|
httpClient.postAp(
|
||||||
urlString = inbox,
|
urlString = inbox,
|
||||||
username = "$actor#pubkey",
|
username = "$actor#pubkey",
|
||||||
jsonLd = Create(
|
jsonLd = Create(
|
||||||
name = "Create Note",
|
name = "Create Note",
|
||||||
`object` = note,
|
`object` = note,
|
||||||
actor = note.attributedTo,
|
actor = note.attributedTo,
|
||||||
id = "${Config.configData.url}/create/note/${postEntity.id}"
|
id = "${Config.configData.url}/create/note/${postEntity.id}"
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,10 +75,10 @@ class ActivityPubNoteServiceImpl(
|
||||||
return postToNote(post)
|
return postToNote(post)
|
||||||
}
|
}
|
||||||
val response = httpClient.getAp(
|
val response = httpClient.getAp(
|
||||||
url,
|
url,
|
||||||
targetActor?.let { "$targetActor#pubkey" }
|
"$targetActor#pubkey"
|
||||||
)
|
)
|
||||||
val note = Config.configData.objectMapper.readValue<Note>(response.bodyAsText())
|
val note = response.body<Note>()
|
||||||
return note(note, targetActor, url)
|
return note(note, targetActor, url)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,44 +86,44 @@ class ActivityPubNoteServiceImpl(
|
||||||
val user = userService.findById(post.userId)
|
val user = userService.findById(post.userId)
|
||||||
val reply = post.replyId?.let { postRepository.findOneById(it) }
|
val reply = post.replyId?.let { postRepository.findOneById(it) }
|
||||||
return Note(
|
return Note(
|
||||||
name = "Post",
|
name = "Post",
|
||||||
id = post.apId,
|
id = post.apId,
|
||||||
attributedTo = user.url,
|
attributedTo = user.url,
|
||||||
content = post.text,
|
content = post.text,
|
||||||
published = Instant.ofEpochMilli(post.createdAt).toString(),
|
published = Instant.ofEpochMilli(post.createdAt).toString(),
|
||||||
to = listOf(public, user.url + "/follower"),
|
to = listOf(public, user.url + "/follower"),
|
||||||
sensitive = post.sensitive,
|
sensitive = post.sensitive,
|
||||||
cc = listOf(public, user.url + "/follower"),
|
cc = listOf(public, user.url + "/follower"),
|
||||||
inReplyTo = reply?.url
|
inReplyTo = reply?.url
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun ActivityPubNoteServiceImpl.note(
|
private suspend fun ActivityPubNoteServiceImpl.note(
|
||||||
note: Note,
|
note: Note,
|
||||||
targetActor: String?,
|
targetActor: String?,
|
||||||
url: String
|
url: String
|
||||||
): Note {
|
): Note {
|
||||||
val findByApId = postRepository.findByApId(url)
|
val findByApId = postRepository.findByApId(url)
|
||||||
if (findByApId != null) {
|
if (findByApId != null) {
|
||||||
return postToNote(findByApId)
|
return postToNote(findByApId)
|
||||||
}
|
}
|
||||||
val person = activityPubUserService.fetchPerson(
|
val person = activityPubUserService.fetchPerson(
|
||||||
note.attributedTo ?: throw IllegalActivityPubObjectException("note.attributedTo is null"),
|
note.attributedTo ?: throw IllegalActivityPubObjectException("note.attributedTo is null"),
|
||||||
targetActor
|
targetActor
|
||||||
)
|
)
|
||||||
val user =
|
val user =
|
||||||
userService.findByUrl(person.url ?: throw IllegalActivityPubObjectException("person.url is null"))
|
userService.findByUrl(person.url ?: throw IllegalActivityPubObjectException("person.url is null"))
|
||||||
|
|
||||||
val visibility =
|
val visibility =
|
||||||
if (note.to.contains(public) && note.cc.contains(public)) {
|
if (note.to.contains(public) && note.cc.contains(public)) {
|
||||||
Visibility.PUBLIC
|
Visibility.PUBLIC
|
||||||
} else if (note.to.find { it.endsWith("/followers") } != null && note.cc.contains(public)) {
|
} else if (note.to.find { it.endsWith("/followers") } != null && note.cc.contains(public)) {
|
||||||
Visibility.UNLISTED
|
Visibility.UNLISTED
|
||||||
} else if (note.to.find { it.endsWith("/followers") } != null) {
|
} else if (note.to.find { it.endsWith("/followers") } != null) {
|
||||||
Visibility.FOLLOWERS
|
Visibility.FOLLOWERS
|
||||||
} else {
|
} else {
|
||||||
Visibility.DIRECT
|
Visibility.DIRECT
|
||||||
}
|
}
|
||||||
|
|
||||||
val reply = note.inReplyTo?.let {
|
val reply = note.inReplyTo?.let {
|
||||||
fetchNote(it, targetActor)
|
fetchNote(it, targetActor)
|
||||||
|
@ -131,25 +131,25 @@ class ActivityPubNoteServiceImpl(
|
||||||
}
|
}
|
||||||
|
|
||||||
postRepository.save(
|
postRepository.save(
|
||||||
Post(
|
Post(
|
||||||
id = postRepository.generateId(),
|
id = postRepository.generateId(),
|
||||||
userId = user.id,
|
userId = user.id,
|
||||||
overview = null,
|
overview = null,
|
||||||
text = note.content.orEmpty(),
|
text = note.content.orEmpty(),
|
||||||
createdAt = Instant.parse(note.published).toEpochMilli(),
|
createdAt = Instant.parse(note.published).toEpochMilli(),
|
||||||
visibility = visibility,
|
visibility = visibility,
|
||||||
url = note.id ?: url,
|
url = note.id ?: url,
|
||||||
repostId = null,
|
repostId = null,
|
||||||
replyId = reply?.id,
|
replyId = reply?.id,
|
||||||
sensitive = note.sensitive,
|
sensitive = note.sensitive,
|
||||||
apId = note.id ?: url,
|
apId = note.id ?: url,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
return note
|
return note
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun fetchNote(note: Note, targetActor: String?): Note =
|
override suspend fun fetchNote(note: Note, targetActor: String?): Note =
|
||||||
note(note, targetActor, note.id ?: throw IllegalArgumentException("note.id is null"))
|
note(note, targetActor, note.id ?: throw IllegalArgumentException("note.id is null"))
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val public: String = "https://www.w3.org/ns/activitystreams#Public"
|
const val public: String = "https://www.w3.org/ns/activitystreams#Public"
|
||||||
|
|
|
@ -100,65 +100,3 @@ enum class ActivityVocabulary {
|
||||||
Video,
|
Video,
|
||||||
Mention,
|
Mention,
|
||||||
}
|
}
|
||||||
|
|
||||||
enum class ExtendedActivityVocabulary {
|
|
||||||
Object,
|
|
||||||
Link,
|
|
||||||
Activity,
|
|
||||||
IntransitiveActivity,
|
|
||||||
Collection,
|
|
||||||
OrderedCollection,
|
|
||||||
CollectionPage,
|
|
||||||
OrderedCollectionPage,
|
|
||||||
Accept,
|
|
||||||
Add,
|
|
||||||
Announce,
|
|
||||||
Arrive,
|
|
||||||
Block,
|
|
||||||
Create,
|
|
||||||
Delete,
|
|
||||||
Dislike,
|
|
||||||
Flag,
|
|
||||||
Follow,
|
|
||||||
Ignore,
|
|
||||||
Invite,
|
|
||||||
Join,
|
|
||||||
Leave,
|
|
||||||
Like,
|
|
||||||
Listen,
|
|
||||||
Move,
|
|
||||||
Offer,
|
|
||||||
Question,
|
|
||||||
Reject,
|
|
||||||
Read,
|
|
||||||
Remove,
|
|
||||||
TentativeReject,
|
|
||||||
TentativeAccept,
|
|
||||||
Travel,
|
|
||||||
Undo,
|
|
||||||
Update,
|
|
||||||
View,
|
|
||||||
Application,
|
|
||||||
Group,
|
|
||||||
Organization,
|
|
||||||
Person,
|
|
||||||
Service,
|
|
||||||
Article,
|
|
||||||
Audio,
|
|
||||||
Document,
|
|
||||||
Event,
|
|
||||||
Image,
|
|
||||||
Note,
|
|
||||||
Page,
|
|
||||||
Place,
|
|
||||||
Profile,
|
|
||||||
Relationship,
|
|
||||||
Tombstone,
|
|
||||||
Video,
|
|
||||||
Mention,
|
|
||||||
Emoji
|
|
||||||
}
|
|
||||||
|
|
||||||
enum class ExtendedVocabulary {
|
|
||||||
Emoji
|
|
||||||
}
|
|
||||||
|
|
|
@ -21,8 +21,7 @@ class ActivityPubServiceImpl(
|
||||||
private val activityPubNoteService: ActivityPubNoteService,
|
private val activityPubNoteService: ActivityPubNoteService,
|
||||||
private val activityPubUndoService: ActivityPubUndoService,
|
private val activityPubUndoService: ActivityPubUndoService,
|
||||||
private val activityPubAcceptService: ActivityPubAcceptService,
|
private val activityPubAcceptService: ActivityPubAcceptService,
|
||||||
private val activityPubCreateService: ActivityPubCreateService,
|
private val activityPubCreateService: ActivityPubCreateService
|
||||||
private val activityPubLikeService: ActivityPubLikeService
|
|
||||||
) : ActivityPubService {
|
) : ActivityPubService {
|
||||||
|
|
||||||
val logger: Logger = LoggerFactory.getLogger(this::class.java)
|
val logger: Logger = LoggerFactory.getLogger(this::class.java)
|
||||||
|
@ -54,7 +53,6 @@ class ActivityPubServiceImpl(
|
||||||
)
|
)
|
||||||
|
|
||||||
ActivityType.Create -> activityPubCreateService.receiveCreate(configData.objectMapper.readValue(json))
|
ActivityType.Create -> activityPubCreateService.receiveCreate(configData.objectMapper.readValue(json))
|
||||||
ActivityType.Like -> activityPubLikeService.receiveLike(configData.objectMapper.readValue(json))
|
|
||||||
ActivityType.Undo -> activityPubUndoService.receiveUndo(configData.objectMapper.readValue(json))
|
ActivityType.Undo -> activityPubUndoService.receiveUndo(configData.objectMapper.readValue(json))
|
||||||
|
|
||||||
else -> {
|
else -> {
|
||||||
|
|
|
@ -93,7 +93,7 @@ class ActivityPubUserServiceImpl(
|
||||||
RemoteUserCreateDto(
|
RemoteUserCreateDto(
|
||||||
name = person.preferredUsername
|
name = person.preferredUsername
|
||||||
?: throw IllegalActivityPubObjectException("preferredUsername is null"),
|
?: throw IllegalActivityPubObjectException("preferredUsername is null"),
|
||||||
domain = url.substringAfter("://").substringBefore("/"),
|
domain = url.substringAfter("://").substringBeforeLast("/"),
|
||||||
screenName = (person.name ?: person.preferredUsername)
|
screenName = (person.name ?: person.preferredUsername)
|
||||||
?: throw IllegalActivityPubObjectException("preferredUsername is null"),
|
?: throw IllegalActivityPubObjectException("preferredUsername is null"),
|
||||||
description = person.summary.orEmpty(),
|
description = person.summary.orEmpty(),
|
||||||
|
|
|
@ -3,26 +3,25 @@ package dev.usbharu.hideout.service.api
|
||||||
import dev.usbharu.hideout.domain.model.hideout.entity.Post
|
import dev.usbharu.hideout.domain.model.hideout.entity.Post
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
|
|
||||||
@Suppress("LongParameterList")
|
|
||||||
interface IPostApiService {
|
interface IPostApiService {
|
||||||
suspend fun createPost(postForm: dev.usbharu.hideout.domain.model.hideout.form.Post, userId: Long): Post
|
suspend fun createPost(postForm: dev.usbharu.hideout.domain.model.hideout.form.Post, userId: Long): Post
|
||||||
suspend fun getById(id: Long, userId: Long?): Post
|
suspend fun getById(id: Long, userId: Long?): Post
|
||||||
suspend fun getAll(
|
suspend fun getAll(
|
||||||
since: Instant? = null,
|
since: Instant? = null,
|
||||||
until: Instant? = null,
|
until: Instant? = null,
|
||||||
minId: Long? = null,
|
minId: Long? = null,
|
||||||
maxId: Long? = null,
|
maxId: Long? = null,
|
||||||
limit: Int? = null,
|
limit: Int? = null,
|
||||||
userId: Long? = null
|
userId: Long? = null
|
||||||
): List<Post>
|
): List<Post>
|
||||||
|
|
||||||
suspend fun getByUser(
|
suspend fun getByUser(
|
||||||
nameOrId: String,
|
nameOrId: String,
|
||||||
since: Instant? = null,
|
since: Instant? = null,
|
||||||
until: Instant? = null,
|
until: Instant? = null,
|
||||||
minId: Long? = null,
|
minId: Long? = null,
|
||||||
maxId: Long? = null,
|
maxId: Long? = null,
|
||||||
limit: Int? = null,
|
limit: Int? = null,
|
||||||
userId: Long? = null
|
userId: Long? = null
|
||||||
): List<Post>
|
): List<Post>
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,58 +13,58 @@ import dev.usbharu.hideout.domain.model.hideout.form.Post as FormPost
|
||||||
|
|
||||||
@Single
|
@Single
|
||||||
class PostApiServiceImpl(
|
class PostApiServiceImpl(
|
||||||
private val postService: IPostService,
|
private val postService: IPostService,
|
||||||
private val postRepository: IPostRepository
|
private val postRepository: IPostRepository
|
||||||
) : IPostApiService {
|
) : IPostApiService {
|
||||||
override suspend fun createPost(postForm: FormPost, userId: Long): Post {
|
override suspend fun createPost(postForm: FormPost, userId: Long): Post {
|
||||||
return postService.createLocal(
|
return postService.createLocal(
|
||||||
PostCreateDto(
|
PostCreateDto(
|
||||||
text = postForm.text,
|
text = postForm.text,
|
||||||
overview = postForm.overview,
|
overview = postForm.overview,
|
||||||
visibility = postForm.visibility,
|
visibility = postForm.visibility,
|
||||||
repostId = postForm.repostId,
|
repostId = postForm.repostId,
|
||||||
repolyId = postForm.replyId,
|
repolyId = postForm.replyId,
|
||||||
userId = userId
|
userId = userId
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun getById(id: Long, userId: Long?): Post {
|
override suspend fun getById(id: Long, userId: Long?): Post {
|
||||||
return postRepository.findOneById(id, userId)
|
return postRepository.findOneById(id, userId)
|
||||||
?: throw PostNotFoundException("$id was not found or is not authorized.")
|
?: throw PostNotFoundException("$id was not found or is not authorized.")
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun getAll(
|
override suspend fun getAll(
|
||||||
since: Instant?,
|
since: Instant?,
|
||||||
until: Instant?,
|
until: Instant?,
|
||||||
minId: Long?,
|
minId: Long?,
|
||||||
maxId: Long?,
|
maxId: Long?,
|
||||||
limit: Int?,
|
limit: Int?,
|
||||||
userId: Long?
|
userId: Long?
|
||||||
): List<Post> = postRepository.findAll(since, until, minId, maxId, limit, userId)
|
): List<Post> = postRepository.findAll(since, until, minId, maxId, limit, userId)
|
||||||
|
|
||||||
override suspend fun getByUser(
|
override suspend fun getByUser(
|
||||||
nameOrId: String,
|
nameOrId: String,
|
||||||
since: Instant?,
|
since: Instant?,
|
||||||
until: Instant?,
|
until: Instant?,
|
||||||
minId: Long?,
|
minId: Long?,
|
||||||
maxId: Long?,
|
maxId: Long?,
|
||||||
limit: Int?,
|
limit: Int?,
|
||||||
userId: Long?
|
userId: Long?
|
||||||
): List<Post> {
|
): List<Post> {
|
||||||
val idOrNull = nameOrId.toLongOrNull()
|
val idOrNull = nameOrId.toLongOrNull()
|
||||||
return if (idOrNull == null) {
|
return if (idOrNull == null) {
|
||||||
val acct = AcctUtil.parse(nameOrId)
|
val acct = AcctUtil.parse(nameOrId)
|
||||||
postRepository.findByUserNameAndDomain(
|
postRepository.findByUserNameAndDomain(
|
||||||
username = acct.username,
|
acct.username,
|
||||||
s = acct.domain
|
acct.domain
|
||||||
?: Config.configData.domain,
|
?: Config.configData.domain,
|
||||||
since = since,
|
since,
|
||||||
until = until,
|
until,
|
||||||
minId = minId,
|
minId,
|
||||||
maxId = maxId,
|
maxId,
|
||||||
limit = limit,
|
limit,
|
||||||
userId = userId
|
userId
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
postRepository.findByUserId(idOrNull, since, until, minId, maxId, limit, userId)
|
postRepository.findByUserId(idOrNull, since, until, minId, maxId, limit, userId)
|
||||||
|
|
|
@ -11,23 +11,23 @@ import java.time.Instant
|
||||||
|
|
||||||
@Single
|
@Single
|
||||||
class PostServiceImpl(
|
class PostServiceImpl(
|
||||||
private val postRepository: IPostRepository,
|
private val postRepository: IPostRepository,
|
||||||
private val userRepository: IUserRepository,
|
private val userRepository: IUserRepository,
|
||||||
private val activityPubNoteService: ActivityPubNoteService
|
private val activityPubNoteService: ActivityPubNoteService
|
||||||
) : IPostService {
|
) : IPostService {
|
||||||
override suspend fun createLocal(post: PostCreateDto): Post {
|
override suspend fun createLocal(post: PostCreateDto): Post {
|
||||||
val user = userRepository.findById(post.userId) ?: throw UserNotFoundException("${post.userId} was not found")
|
val user = userRepository.findById(post.userId) ?: throw UserNotFoundException("${post.userId} was not found")
|
||||||
val id = postRepository.generateId()
|
val id = postRepository.generateId()
|
||||||
val createPost = Post(
|
val createPost = Post(
|
||||||
id = id,
|
id = id,
|
||||||
userId = post.userId,
|
userId = post.userId,
|
||||||
overview = post.overview,
|
overview = post.overview,
|
||||||
text = post.text,
|
text = post.text,
|
||||||
createdAt = Instant.now().toEpochMilli(),
|
createdAt = Instant.now().toEpochMilli(),
|
||||||
visibility = post.visibility,
|
visibility = post.visibility,
|
||||||
url = "${user.url}/posts/$id",
|
url = "${user.url}/posts/$id",
|
||||||
repostId = null,
|
repostId = null,
|
||||||
replyId = null
|
replyId = null
|
||||||
)
|
)
|
||||||
activityPubNoteService.createNote(createPost)
|
activityPubNoteService.createNote(createPost)
|
||||||
return internalCreate(createPost)
|
return internalCreate(createPost)
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
package dev.usbharu.hideout.service.reaction
|
|
||||||
|
|
||||||
interface IReactionService {
|
|
||||||
suspend fun receiveReaction(name: String, domain: String, userId: Long, postId: Long)
|
|
||||||
}
|
|
|
@ -1,16 +0,0 @@
|
||||||
package dev.usbharu.hideout.service.reaction
|
|
||||||
|
|
||||||
import dev.usbharu.hideout.domain.model.hideout.entity.Reaction
|
|
||||||
import dev.usbharu.hideout.repository.ReactionRepository
|
|
||||||
import org.koin.core.annotation.Single
|
|
||||||
|
|
||||||
@Single
|
|
||||||
class ReactionServiceImpl(private val reactionRepository: ReactionRepository) : IReactionService {
|
|
||||||
override suspend fun receiveReaction(name: String, domain: String, userId: Long, postId: Long) {
|
|
||||||
if (reactionRepository.reactionAlreadyExist(postId, userId, 0).not()) {
|
|
||||||
reactionRepository.save(
|
|
||||||
Reaction(reactionRepository.generateId(), 0, postId, userId)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,335 +0,0 @@
|
||||||
openapi: 3.0.3
|
|
||||||
info:
|
|
||||||
title: Hideout API
|
|
||||||
description: Hideout API
|
|
||||||
version: 1.0.0
|
|
||||||
servers:
|
|
||||||
- url: 'https://test-hideout.usbharu.dev/api/internal/v1'
|
|
||||||
paths:
|
|
||||||
/posts:
|
|
||||||
get:
|
|
||||||
summary: 権限に応じて投稿一覧を返す
|
|
||||||
security:
|
|
||||||
- { }
|
|
||||||
- BearerAuth: [ ]
|
|
||||||
responses:
|
|
||||||
200:
|
|
||||||
description: 成功
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
type: array
|
|
||||||
items:
|
|
||||||
$ref: "#/components/schemas/Post"
|
|
||||||
401:
|
|
||||||
$ref: "#/components/responses/Unauthorized"
|
|
||||||
403:
|
|
||||||
$ref: "#/components/responses/Forbidden"
|
|
||||||
429:
|
|
||||||
$ref: "#/components/responses/TooManyRequests"
|
|
||||||
post:
|
|
||||||
summary: 投稿する
|
|
||||||
security:
|
|
||||||
- BearerAuth: [ ]
|
|
||||||
requestBody:
|
|
||||||
description: 投稿する内容
|
|
||||||
required: true
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
$ref: "#/components/schemas/Post"
|
|
||||||
responses:
|
|
||||||
200:
|
|
||||||
description: 成功
|
|
||||||
headers:
|
|
||||||
Location:
|
|
||||||
description: 作成した投稿のURL
|
|
||||||
schema:
|
|
||||||
type: string
|
|
||||||
format: uri
|
|
||||||
401:
|
|
||||||
$ref: "#/components/responses/Unauthorized"
|
|
||||||
429:
|
|
||||||
$ref: "#/components/responses/TooManyRequests"
|
|
||||||
/posts/{postId}:
|
|
||||||
get:
|
|
||||||
summary: 権限に応じてIDの投稿を返す
|
|
||||||
security:
|
|
||||||
- { }
|
|
||||||
- BearerAuth: [ ]
|
|
||||||
parameters:
|
|
||||||
- $ref: "#/components/parameters/postId"
|
|
||||||
responses:
|
|
||||||
200:
|
|
||||||
description: 成功
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
$ref: "#/components/schemas/Post"
|
|
||||||
401:
|
|
||||||
$ref: "#/components/responses/Unauthorized"
|
|
||||||
403:
|
|
||||||
$ref: "#/components/responses/Forbidden"
|
|
||||||
404:
|
|
||||||
$ref: "#/components/responses/NotFoundOrForbidden"
|
|
||||||
429:
|
|
||||||
$ref: "#/components/responses/TooManyRequests"
|
|
||||||
/users/{userName}/posts:
|
|
||||||
get:
|
|
||||||
summary: 権限に応じてユーザーの投稿一覧を返す
|
|
||||||
security:
|
|
||||||
- { }
|
|
||||||
- BearerAuth: [ ]
|
|
||||||
parameters:
|
|
||||||
- $ref: "#/components/parameters/userName"
|
|
||||||
responses:
|
|
||||||
200:
|
|
||||||
description: 成功
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
type: array
|
|
||||||
items:
|
|
||||||
$ref: "#/components/schemas/Post"
|
|
||||||
401:
|
|
||||||
$ref: "#/components/responses/Unauthorized"
|
|
||||||
403:
|
|
||||||
$ref: "#/components/responses/Forbidden"
|
|
||||||
429:
|
|
||||||
$ref: "#/components/responses/TooManyRequests"
|
|
||||||
|
|
||||||
/users/{userName}/posts/{postId}:
|
|
||||||
get:
|
|
||||||
summary: 権限に応じてIDの投稿を返す
|
|
||||||
description: userNameが間違っていても取得できます。
|
|
||||||
security:
|
|
||||||
- { }
|
|
||||||
- BearerAuth: [ ]
|
|
||||||
parameters:
|
|
||||||
- $ref: "#/components/parameters/userName"
|
|
||||||
- $ref: "#/components/parameters/postId"
|
|
||||||
responses:
|
|
||||||
200:
|
|
||||||
description: 成功
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
$ref: "#/components/schemas/Post"
|
|
||||||
401:
|
|
||||||
$ref: "#/components/responses/Unauthorized"
|
|
||||||
403:
|
|
||||||
$ref: "#/components/responses/Forbidden"
|
|
||||||
404:
|
|
||||||
$ref: "#/components/responses/NotFoundOrForbidden"
|
|
||||||
429:
|
|
||||||
$ref: "#/components/responses/TooManyRequests"
|
|
||||||
|
|
||||||
/users:
|
|
||||||
get:
|
|
||||||
summary: ユーザー一覧を返す
|
|
||||||
security:
|
|
||||||
- { }
|
|
||||||
responses:
|
|
||||||
200:
|
|
||||||
description: 成功
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
type: array
|
|
||||||
items:
|
|
||||||
$ref: "#/components/schemas/User"
|
|
||||||
|
|
||||||
post:
|
|
||||||
summary: ユーザーを作成する
|
|
||||||
security:
|
|
||||||
- { }
|
|
||||||
requestBody:
|
|
||||||
description: 作成するユーザーの詳細
|
|
||||||
required: true
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
type: object
|
|
||||||
properties:
|
|
||||||
username:
|
|
||||||
type: string
|
|
||||||
password:
|
|
||||||
type: string
|
|
||||||
responses:
|
|
||||||
201:
|
|
||||||
description: ユーザーが作成された
|
|
||||||
headers:
|
|
||||||
Location:
|
|
||||||
description: 作成されたユーザーのURL
|
|
||||||
schema:
|
|
||||||
type: string
|
|
||||||
format: url
|
|
||||||
400:
|
|
||||||
description: ユーザー名が既に仕様されている。またはリクエストが異常
|
|
||||||
|
|
||||||
/users/{userName}:
|
|
||||||
get:
|
|
||||||
summary: ユーザーの詳細を返す
|
|
||||||
security:
|
|
||||||
- { }
|
|
||||||
- BearerAuth: [ ]
|
|
||||||
parameters:
|
|
||||||
- $ref: "#/components/parameters/userName"
|
|
||||||
responses:
|
|
||||||
200:
|
|
||||||
description: 成功
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
$ref: "#/components/schemas/User"
|
|
||||||
404:
|
|
||||||
$ref: "#/components/responses/NotFound"
|
|
||||||
|
|
||||||
/users/{userName}/followers:
|
|
||||||
get:
|
|
||||||
summary: ユーザーのフォロワー一覧を返す
|
|
||||||
parameters:
|
|
||||||
- $ref: "#/components/parameters/userName"
|
|
||||||
responses:
|
|
||||||
200:
|
|
||||||
description: 成功
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
type: array
|
|
||||||
items:
|
|
||||||
$ref: "#/components/schemas/User"
|
|
||||||
post:
|
|
||||||
summary: ユーザーをフォローする
|
|
||||||
security:
|
|
||||||
- BearerAuth: [ ]
|
|
||||||
parameters:
|
|
||||||
- $ref: "#/components/parameters/userName"
|
|
||||||
responses:
|
|
||||||
200:
|
|
||||||
description: 成功
|
|
||||||
202:
|
|
||||||
description: 受け付けられたが完了していない
|
|
||||||
401:
|
|
||||||
$ref: "#/components/responses/Unauthorized"
|
|
||||||
404:
|
|
||||||
$ref: "#/components/responses/NotFound"
|
|
||||||
|
|
||||||
/users/{userName}/following:
|
|
||||||
get:
|
|
||||||
summary: ユーザーのフォロイー一覧を返す
|
|
||||||
parameters:
|
|
||||||
- $ref: "#/components/parameters/userName"
|
|
||||||
responses:
|
|
||||||
200:
|
|
||||||
description: 成功
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
type: array
|
|
||||||
items:
|
|
||||||
$ref: "#/components/schemas/User"
|
|
||||||
|
|
||||||
components:
|
|
||||||
responses:
|
|
||||||
Unauthorized:
|
|
||||||
description: トークンが無効
|
|
||||||
Forbidden:
|
|
||||||
description: 権限がない
|
|
||||||
NotFoundOrForbidden:
|
|
||||||
description: 存在しないか権限がない
|
|
||||||
NotFound:
|
|
||||||
description: 存在しない
|
|
||||||
TooManyRequests:
|
|
||||||
description: レートリミット
|
|
||||||
|
|
||||||
parameters:
|
|
||||||
postId:
|
|
||||||
name: postId
|
|
||||||
in: path
|
|
||||||
description: 投稿ID
|
|
||||||
required: true
|
|
||||||
schema:
|
|
||||||
type: integer
|
|
||||||
format: int64
|
|
||||||
userName:
|
|
||||||
name: userName
|
|
||||||
in: path
|
|
||||||
description: ユーザーIDまたはAcctなど @name@domain name@domain name
|
|
||||||
required: true
|
|
||||||
schema:
|
|
||||||
type: string
|
|
||||||
|
|
||||||
schemas:
|
|
||||||
User:
|
|
||||||
type: object
|
|
||||||
properties:
|
|
||||||
id:
|
|
||||||
type: number
|
|
||||||
format: int64
|
|
||||||
readOnly: true
|
|
||||||
name:
|
|
||||||
type: string
|
|
||||||
domain:
|
|
||||||
type: string
|
|
||||||
readOnly: true
|
|
||||||
screenName:
|
|
||||||
type: string
|
|
||||||
description:
|
|
||||||
type: string
|
|
||||||
url:
|
|
||||||
type: string
|
|
||||||
readOnly: true
|
|
||||||
createdAt:
|
|
||||||
type: number
|
|
||||||
readOnly: true
|
|
||||||
Post:
|
|
||||||
type: object
|
|
||||||
properties:
|
|
||||||
id:
|
|
||||||
type: integer
|
|
||||||
format: int64
|
|
||||||
readOnly: true
|
|
||||||
userId:
|
|
||||||
type: integer
|
|
||||||
format: int64
|
|
||||||
readOnly: true
|
|
||||||
overview:
|
|
||||||
type: string
|
|
||||||
text:
|
|
||||||
type: string
|
|
||||||
createdAt:
|
|
||||||
type: integer
|
|
||||||
format: int64
|
|
||||||
readOnly: true
|
|
||||||
visibility:
|
|
||||||
type: string
|
|
||||||
enum:
|
|
||||||
- public
|
|
||||||
- unlisted
|
|
||||||
- followers
|
|
||||||
- direct
|
|
||||||
url:
|
|
||||||
type: string
|
|
||||||
format: uri
|
|
||||||
readOnly: true
|
|
||||||
repostId:
|
|
||||||
type: integer
|
|
||||||
format: int64
|
|
||||||
readOnly: true
|
|
||||||
replyId:
|
|
||||||
type: integer
|
|
||||||
format: int64
|
|
||||||
readOnly: true
|
|
||||||
sensitive:
|
|
||||||
type: boolean
|
|
||||||
apId:
|
|
||||||
type: string
|
|
||||||
format: url
|
|
||||||
readOnly: true
|
|
||||||
|
|
||||||
|
|
||||||
securitySchemes:
|
|
||||||
BearerAuth:
|
|
||||||
type: http
|
|
||||||
scheme: bearer
|
|
|
@ -41,24 +41,24 @@ class PostsTest {
|
||||||
createdAt = Instant.now().toEpochMilli(),
|
createdAt = Instant.now().toEpochMilli(),
|
||||||
url = "https://example.com/posts/1"
|
url = "https://example.com/posts/1"
|
||||||
),
|
),
|
||||||
Post(
|
Post(
|
||||||
id = 123456,
|
id = 123456,
|
||||||
userId = 4322,
|
userId = 4322,
|
||||||
text = "test2",
|
text = "test2",
|
||||||
visibility = Visibility.PUBLIC,
|
visibility = Visibility.PUBLIC,
|
||||||
createdAt = Instant.now().toEpochMilli(),
|
createdAt = Instant.now().toEpochMilli(),
|
||||||
url = "https://example.com/posts/2"
|
url = "https://example.com/posts/2"
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
val postService = mock<IPostApiService> {
|
val postService = mock<IPostApiService> {
|
||||||
onBlocking {
|
onBlocking {
|
||||||
getAll(
|
getAll(
|
||||||
since = anyOrNull(),
|
since = anyOrNull(),
|
||||||
until = anyOrNull(),
|
until = anyOrNull(),
|
||||||
minId = anyOrNull(),
|
minId = anyOrNull(),
|
||||||
maxId = anyOrNull(),
|
maxId = anyOrNull(),
|
||||||
limit = anyOrNull(),
|
limit = anyOrNull(),
|
||||||
userId = isNull()
|
userId = isNull()
|
||||||
)
|
)
|
||||||
} doReturn posts
|
} doReturn posts
|
||||||
}
|
}
|
||||||
|
@ -120,12 +120,12 @@ class PostsTest {
|
||||||
val postService = mock<IPostApiService> {
|
val postService = mock<IPostApiService> {
|
||||||
onBlocking {
|
onBlocking {
|
||||||
getAll(
|
getAll(
|
||||||
since = anyOrNull(),
|
since = anyOrNull(),
|
||||||
until = anyOrNull(),
|
until = anyOrNull(),
|
||||||
minId = anyOrNull(),
|
minId = anyOrNull(),
|
||||||
maxId = anyOrNull(),
|
maxId = anyOrNull(),
|
||||||
limit = anyOrNull(),
|
limit = anyOrNull(),
|
||||||
userId = isNotNull()
|
userId = isNotNull()
|
||||||
)
|
)
|
||||||
} doReturn posts
|
} doReturn posts
|
||||||
}
|
}
|
||||||
|
@ -157,12 +157,12 @@ class PostsTest {
|
||||||
config = ApplicationConfig("empty.conf")
|
config = ApplicationConfig("empty.conf")
|
||||||
}
|
}
|
||||||
val post = Post(
|
val post = Post(
|
||||||
12345,
|
12345,
|
||||||
1234,
|
1234,
|
||||||
text = "aaa",
|
text = "aaa",
|
||||||
visibility = Visibility.PUBLIC,
|
visibility = Visibility.PUBLIC,
|
||||||
createdAt = Instant.now().toEpochMilli(),
|
createdAt = Instant.now().toEpochMilli(),
|
||||||
url = "https://example.com/posts/1"
|
url = "https://example.com/posts/1"
|
||||||
)
|
)
|
||||||
val postService = mock<IPostApiService> {
|
val postService = mock<IPostApiService> {
|
||||||
onBlocking { getById(any(), anyOrNull()) } doReturn post
|
onBlocking { getById(any(), anyOrNull()) } doReturn post
|
||||||
|
@ -188,12 +188,12 @@ class PostsTest {
|
||||||
config = ApplicationConfig("empty.conf")
|
config = ApplicationConfig("empty.conf")
|
||||||
}
|
}
|
||||||
val post = Post(
|
val post = Post(
|
||||||
12345,
|
12345,
|
||||||
1234,
|
1234,
|
||||||
text = "aaa",
|
text = "aaa",
|
||||||
visibility = Visibility.FOLLOWERS,
|
visibility = Visibility.FOLLOWERS,
|
||||||
createdAt = Instant.now().toEpochMilli(),
|
createdAt = Instant.now().toEpochMilli(),
|
||||||
url = "https://example.com/posts/1"
|
url = "https://example.com/posts/1"
|
||||||
)
|
)
|
||||||
val postService = mock<IPostApiService> {
|
val postService = mock<IPostApiService> {
|
||||||
onBlocking { getById(any(), isNotNull()) } doReturn post
|
onBlocking { getById(any(), isNotNull()) } doReturn post
|
||||||
|
@ -243,13 +243,13 @@ class PostsTest {
|
||||||
val argument = it.getArgument<dev.usbharu.hideout.domain.model.hideout.form.Post>(0)
|
val argument = it.getArgument<dev.usbharu.hideout.domain.model.hideout.form.Post>(0)
|
||||||
val userId = it.getArgument<Long>(1)
|
val userId = it.getArgument<Long>(1)
|
||||||
Post(
|
Post(
|
||||||
123L,
|
123L,
|
||||||
userId,
|
userId,
|
||||||
null,
|
null,
|
||||||
argument.text,
|
argument.text,
|
||||||
Instant.now().toEpochMilli(),
|
Instant.now().toEpochMilli(),
|
||||||
Visibility.PUBLIC,
|
Visibility.PUBLIC,
|
||||||
"https://example.com"
|
"https://example.com"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -299,25 +299,25 @@ class PostsTest {
|
||||||
createdAt = Instant.now().toEpochMilli(),
|
createdAt = Instant.now().toEpochMilli(),
|
||||||
url = "https://example.com/posts/1"
|
url = "https://example.com/posts/1"
|
||||||
),
|
),
|
||||||
Post(
|
Post(
|
||||||
id = 123456,
|
id = 123456,
|
||||||
userId = 1,
|
userId = 1,
|
||||||
text = "test2",
|
text = "test2",
|
||||||
visibility = Visibility.PUBLIC,
|
visibility = Visibility.PUBLIC,
|
||||||
createdAt = Instant.now().toEpochMilli(),
|
createdAt = Instant.now().toEpochMilli(),
|
||||||
url = "https://example.com/posts/2"
|
url = "https://example.com/posts/2"
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
val postService = mock<IPostApiService> {
|
val postService = mock<IPostApiService> {
|
||||||
onBlocking {
|
onBlocking {
|
||||||
getByUser(
|
getByUser(
|
||||||
nameOrId = any(),
|
nameOrId = any(),
|
||||||
since = anyOrNull(),
|
since = anyOrNull(),
|
||||||
until = anyOrNull(),
|
until = anyOrNull(),
|
||||||
minId = anyOrNull(),
|
minId = anyOrNull(),
|
||||||
maxId = anyOrNull(),
|
maxId = anyOrNull(),
|
||||||
limit = anyOrNull(),
|
limit = anyOrNull(),
|
||||||
userId = anyOrNull()
|
userId = anyOrNull()
|
||||||
)
|
)
|
||||||
} doReturn posts
|
} doReturn posts
|
||||||
}
|
}
|
||||||
|
@ -351,25 +351,25 @@ class PostsTest {
|
||||||
createdAt = Instant.now().toEpochMilli(),
|
createdAt = Instant.now().toEpochMilli(),
|
||||||
url = "https://example.com/posts/1"
|
url = "https://example.com/posts/1"
|
||||||
),
|
),
|
||||||
Post(
|
Post(
|
||||||
id = 123456,
|
id = 123456,
|
||||||
userId = 1,
|
userId = 1,
|
||||||
text = "test2",
|
text = "test2",
|
||||||
visibility = Visibility.PUBLIC,
|
visibility = Visibility.PUBLIC,
|
||||||
createdAt = Instant.now().toEpochMilli(),
|
createdAt = Instant.now().toEpochMilli(),
|
||||||
url = "https://example.com/posts/2"
|
url = "https://example.com/posts/2"
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
val postService = mock<IPostApiService> {
|
val postService = mock<IPostApiService> {
|
||||||
onBlocking {
|
onBlocking {
|
||||||
getByUser(
|
getByUser(
|
||||||
nameOrId = eq("test1"),
|
nameOrId = eq("test1"),
|
||||||
since = anyOrNull(),
|
since = anyOrNull(),
|
||||||
until = anyOrNull(),
|
until = anyOrNull(),
|
||||||
minId = anyOrNull(),
|
minId = anyOrNull(),
|
||||||
maxId = anyOrNull(),
|
maxId = anyOrNull(),
|
||||||
limit = anyOrNull(),
|
limit = anyOrNull(),
|
||||||
userId = anyOrNull()
|
userId = anyOrNull()
|
||||||
)
|
)
|
||||||
} doReturn posts
|
} doReturn posts
|
||||||
}
|
}
|
||||||
|
@ -403,25 +403,25 @@ class PostsTest {
|
||||||
createdAt = Instant.now().toEpochMilli(),
|
createdAt = Instant.now().toEpochMilli(),
|
||||||
url = "https://example.com/posts/1"
|
url = "https://example.com/posts/1"
|
||||||
),
|
),
|
||||||
Post(
|
Post(
|
||||||
id = 123456,
|
id = 123456,
|
||||||
userId = 1,
|
userId = 1,
|
||||||
text = "test2",
|
text = "test2",
|
||||||
visibility = Visibility.PUBLIC,
|
visibility = Visibility.PUBLIC,
|
||||||
createdAt = Instant.now().toEpochMilli(),
|
createdAt = Instant.now().toEpochMilli(),
|
||||||
url = "https://example.com/posts/2"
|
url = "https://example.com/posts/2"
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
val postService = mock<IPostApiService> {
|
val postService = mock<IPostApiService> {
|
||||||
onBlocking {
|
onBlocking {
|
||||||
getByUser(
|
getByUser(
|
||||||
nameOrId = eq("test1@example.com"),
|
nameOrId = eq("test1@example.com"),
|
||||||
since = anyOrNull(),
|
since = anyOrNull(),
|
||||||
until = anyOrNull(),
|
until = anyOrNull(),
|
||||||
minId = anyOrNull(),
|
minId = anyOrNull(),
|
||||||
maxId = anyOrNull(),
|
maxId = anyOrNull(),
|
||||||
limit = anyOrNull(),
|
limit = anyOrNull(),
|
||||||
userId = anyOrNull()
|
userId = anyOrNull()
|
||||||
)
|
)
|
||||||
} doReturn posts
|
} doReturn posts
|
||||||
}
|
}
|
||||||
|
@ -455,25 +455,25 @@ class PostsTest {
|
||||||
createdAt = Instant.now().toEpochMilli(),
|
createdAt = Instant.now().toEpochMilli(),
|
||||||
url = "https://example.com/posts/1"
|
url = "https://example.com/posts/1"
|
||||||
),
|
),
|
||||||
Post(
|
Post(
|
||||||
id = 123456,
|
id = 123456,
|
||||||
userId = 1,
|
userId = 1,
|
||||||
text = "test2",
|
text = "test2",
|
||||||
visibility = Visibility.PUBLIC,
|
visibility = Visibility.PUBLIC,
|
||||||
createdAt = Instant.now().toEpochMilli(),
|
createdAt = Instant.now().toEpochMilli(),
|
||||||
url = "https://example.com/posts/2"
|
url = "https://example.com/posts/2"
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
val postService = mock<IPostApiService> {
|
val postService = mock<IPostApiService> {
|
||||||
onBlocking {
|
onBlocking {
|
||||||
getByUser(
|
getByUser(
|
||||||
nameOrId = eq("@test1@example.com"),
|
nameOrId = eq("@test1@example.com"),
|
||||||
since = anyOrNull(),
|
since = anyOrNull(),
|
||||||
until = anyOrNull(),
|
until = anyOrNull(),
|
||||||
minId = anyOrNull(),
|
minId = anyOrNull(),
|
||||||
maxId = anyOrNull(),
|
maxId = anyOrNull(),
|
||||||
limit = anyOrNull(),
|
limit = anyOrNull(),
|
||||||
userId = anyOrNull()
|
userId = anyOrNull()
|
||||||
)
|
)
|
||||||
} doReturn posts
|
} doReturn posts
|
||||||
}
|
}
|
||||||
|
@ -499,12 +499,12 @@ class PostsTest {
|
||||||
config = ApplicationConfig("empty.conf")
|
config = ApplicationConfig("empty.conf")
|
||||||
}
|
}
|
||||||
val post = Post(
|
val post = Post(
|
||||||
id = 123456,
|
id = 123456,
|
||||||
userId = 1,
|
userId = 1,
|
||||||
text = "test2",
|
text = "test2",
|
||||||
visibility = Visibility.PUBLIC,
|
visibility = Visibility.PUBLIC,
|
||||||
createdAt = Instant.now().toEpochMilli(),
|
createdAt = Instant.now().toEpochMilli(),
|
||||||
url = "https://example.com/posts/2"
|
url = "https://example.com/posts/2"
|
||||||
)
|
)
|
||||||
val postService = mock<IPostApiService> {
|
val postService = mock<IPostApiService> {
|
||||||
onBlocking { getById(eq(12345L), anyOrNull()) } doReturn post
|
onBlocking { getById(eq(12345L), anyOrNull()) } doReturn post
|
||||||
|
@ -531,12 +531,12 @@ class PostsTest {
|
||||||
config = ApplicationConfig("empty.conf")
|
config = ApplicationConfig("empty.conf")
|
||||||
}
|
}
|
||||||
val post = Post(
|
val post = Post(
|
||||||
id = 123456,
|
id = 123456,
|
||||||
userId = 1,
|
userId = 1,
|
||||||
text = "test2",
|
text = "test2",
|
||||||
visibility = Visibility.PUBLIC,
|
visibility = Visibility.PUBLIC,
|
||||||
createdAt = Instant.now().toEpochMilli(),
|
createdAt = Instant.now().toEpochMilli(),
|
||||||
url = "https://example.com/posts/2"
|
url = "https://example.com/posts/2"
|
||||||
)
|
)
|
||||||
val postService = mock<IPostApiService> {
|
val postService = mock<IPostApiService> {
|
||||||
onBlocking { getById(eq(12345L), anyOrNull()) } doReturn post
|
onBlocking { getById(eq(12345L), anyOrNull()) } doReturn post
|
||||||
|
@ -563,12 +563,12 @@ class PostsTest {
|
||||||
config = ApplicationConfig("empty.conf")
|
config = ApplicationConfig("empty.conf")
|
||||||
}
|
}
|
||||||
val post = Post(
|
val post = Post(
|
||||||
id = 123456,
|
id = 123456,
|
||||||
userId = 1,
|
userId = 1,
|
||||||
text = "test2",
|
text = "test2",
|
||||||
visibility = Visibility.PUBLIC,
|
visibility = Visibility.PUBLIC,
|
||||||
createdAt = Instant.now().toEpochMilli(),
|
createdAt = Instant.now().toEpochMilli(),
|
||||||
url = "https://example.com/posts/2"
|
url = "https://example.com/posts/2"
|
||||||
)
|
)
|
||||||
val postService = mock<IPostApiService> {
|
val postService = mock<IPostApiService> {
|
||||||
onBlocking { getById(eq(12345L), anyOrNull()) } doReturn post
|
onBlocking { getById(eq(12345L), anyOrNull()) } doReturn post
|
||||||
|
@ -595,12 +595,12 @@ class PostsTest {
|
||||||
config = ApplicationConfig("empty.conf")
|
config = ApplicationConfig("empty.conf")
|
||||||
}
|
}
|
||||||
val post = Post(
|
val post = Post(
|
||||||
id = 123456,
|
id = 123456,
|
||||||
userId = 1,
|
userId = 1,
|
||||||
text = "test2",
|
text = "test2",
|
||||||
visibility = Visibility.PUBLIC,
|
visibility = Visibility.PUBLIC,
|
||||||
createdAt = Instant.now().toEpochMilli(),
|
createdAt = Instant.now().toEpochMilli(),
|
||||||
url = "https://example.com/posts/2"
|
url = "https://example.com/posts/2"
|
||||||
)
|
)
|
||||||
val postService = mock<IPostApiService> {
|
val postService = mock<IPostApiService> {
|
||||||
onBlocking { getById(eq(12345L), anyOrNull()) } doReturn post
|
onBlocking { getById(eq(12345L), anyOrNull()) } doReturn post
|
||||||
|
|
Loading…
Reference in New Issue