mirror of https://github.com/usbharu/Hideout.git
feat: ノートが正常に取得できなくなっていた問題を修正
This commit is contained in:
parent
67f9fbee47
commit
2d4fed7649
|
@ -78,6 +78,7 @@ fun Application.parent() {
|
|||
install(httpSignaturePlugin) {
|
||||
keyMap = KtorKeyMap(get())
|
||||
}
|
||||
expectSuccess = true
|
||||
}
|
||||
}
|
||||
single<IdGenerateService> { TwitterSnowflakeIdGenerateService }
|
||||
|
|
|
@ -4,7 +4,7 @@ import com.fasterxml.jackson.core.JsonParser
|
|||
import com.fasterxml.jackson.databind.DeserializationContext
|
||||
import com.fasterxml.jackson.databind.JsonDeserializer
|
||||
import com.fasterxml.jackson.databind.JsonNode
|
||||
import dev.usbharu.hideout.service.activitypub.ActivityVocabulary
|
||||
import dev.usbharu.hideout.service.activitypub.ExtendedActivityVocabulary
|
||||
|
||||
class ObjectDeserializer : JsonDeserializer<Object>() {
|
||||
override fun deserialize(p: JsonParser?, ctxt: DeserializationContext?): Object {
|
||||
|
@ -22,28 +22,78 @@ class ObjectDeserializer : JsonDeserializer<Object>() {
|
|||
val type = treeNode["type"]
|
||||
val activityType = if (type.isArray) {
|
||||
type.firstNotNullOf { jsonNode: JsonNode ->
|
||||
ActivityVocabulary.values().firstOrNull { it.name.equals(jsonNode.asText(), true) }
|
||||
ExtendedActivityVocabulary.values().firstOrNull { it.name.equals(jsonNode.asText(), true) }
|
||||
}
|
||||
} else if (type.isValueNode) {
|
||||
ActivityVocabulary.values().first { it.name.equals(type.asText(), true) }
|
||||
ExtendedActivityVocabulary.values().first { it.name.equals(type.asText(), true) }
|
||||
} else {
|
||||
TODO()
|
||||
}
|
||||
|
||||
return when (activityType) {
|
||||
ActivityVocabulary.Follow -> {
|
||||
ExtendedActivityVocabulary.Follow -> {
|
||||
val readValue = p.codec.treeToValue(treeNode, Follow::class.java)
|
||||
println(readValue)
|
||||
readValue
|
||||
}
|
||||
|
||||
ActivityVocabulary.Note -> {
|
||||
ExtendedActivityVocabulary.Note -> {
|
||||
p.codec.treeToValue(treeNode, Note::class.java)
|
||||
}
|
||||
|
||||
else -> {
|
||||
TODO("$activityType is not implementation")
|
||||
}
|
||||
ExtendedActivityVocabulary.Object -> p.codec.treeToValue(treeNode, Object::class.java)
|
||||
ExtendedActivityVocabulary.Link -> 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 {
|
||||
TODO()
|
||||
|
|
|
@ -44,10 +44,12 @@ 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) {
|
||||
header("Accept", ContentType.Application.Activity)
|
||||
header("Signature", "keyId=\"$username\",algorithm=\"rsa-sha256\",headers=\"(request-target) host date\"")
|
||||
username?.let {
|
||||
header("Signature", "keyId=\"$username\",algorithm=\"rsa-sha256\",headers=\"(request-target) host date\"")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -63,7 +63,9 @@ class PostRepositoryImpl(database: Database, private val idGenerateService: IdGe
|
|||
}
|
||||
|
||||
override suspend fun findOneById(id: Long, userId: Long?): Post? {
|
||||
TODO("Not yet implemented")
|
||||
return query {
|
||||
Posts.select { Posts.id eq id }.singleOrNull()?.toPost()
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun findByUrl(url: String): Post? {
|
||||
|
|
|
@ -5,4 +5,5 @@ 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
|
||||
}
|
||||
|
|
|
@ -33,19 +33,25 @@ class ReactionRepositoryImpl(private val database: Database, private val idGener
|
|||
it[id] = reaction.id
|
||||
it[emojiId] = reaction.emojiId
|
||||
it[postId] = reaction.postId
|
||||
it[userId] = 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.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 {
|
||||
|
@ -61,4 +67,8 @@ 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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,12 +16,14 @@ import org.koin.core.annotation.Single
|
|||
class ActivityPubLikeServiceImpl(private val reactionService: IReactionService,
|
||||
private val activityPubUserService: ActivityPubUserService,
|
||||
private val userService: IUserService,
|
||||
private val postService: IPostRepository) : ActivityPubLikeService {
|
||||
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"))
|
||||
|
|
|
@ -14,7 +14,7 @@ import dev.usbharu.hideout.repository.IPostRepository
|
|||
import dev.usbharu.hideout.service.job.JobQueueParentService
|
||||
import dev.usbharu.hideout.service.user.IUserService
|
||||
import io.ktor.client.*
|
||||
import io.ktor.client.call.*
|
||||
import io.ktor.client.statement.*
|
||||
import kjob.core.job.JobProps
|
||||
import org.koin.core.annotation.Single
|
||||
import org.slf4j.LoggerFactory
|
||||
|
@ -75,10 +75,9 @@ class ActivityPubNoteServiceImpl(
|
|||
return postToNote(post)
|
||||
}
|
||||
val response = httpClient.getAp(
|
||||
url,
|
||||
"$targetActor#pubkey"
|
||||
url, targetActor?.let { "$targetActor#pubkey" }
|
||||
)
|
||||
val note = response.body<Note>()
|
||||
val note = Config.configData.objectMapper.readValue<Note>(response.bodyAsText())
|
||||
return note(note, targetActor, url)
|
||||
}
|
||||
|
||||
|
|
|
@ -100,3 +100,65 @@ enum class ActivityVocabulary {
|
|||
Video,
|
||||
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
|
||||
}
|
||||
|
|
|
@ -7,12 +7,10 @@ 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) {
|
||||
reactionRepository.save(
|
||||
Reaction(
|
||||
reactionRepository.generateId(),
|
||||
0,
|
||||
postId, userId
|
||||
)
|
||||
)
|
||||
if (reactionRepository.reactionAlreadyExist(postId, userId, 0).not()) {
|
||||
reactionRepository.save(
|
||||
Reaction(reactionRepository.generateId(), 0, postId, userId)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue