feat: 受け取ったノートのEmojiを認識するように

This commit is contained in:
usbharu 2023-12-22 14:02:23 +09:00
parent 0a54bdfc15
commit 43033b6f4b
5 changed files with 145 additions and 21 deletions

View File

@ -1,6 +1,8 @@
package dev.usbharu.hideout.activitypub.domain.model
import com.fasterxml.jackson.databind.annotation.JsonDeserialize
import dev.usbharu.hideout.activitypub.domain.model.objects.Object
import dev.usbharu.hideout.activitypub.domain.model.objects.ObjectDeserializer
open class Note
@Suppress("LongParameterList")
@ -14,7 +16,9 @@ constructor(
val cc: List<String> = emptyList(),
val sensitive: Boolean = false,
val inReplyTo: String? = null,
val attachment: List<Document> = emptyList()
val attachment: List<Document> = emptyList(),
@JsonDeserialize(contentUsing = ObjectDeserializer::class)
val tag: List<Object> = emptyList()
) : Object(
type = add(type, "Note")
),
@ -36,6 +40,7 @@ constructor(
if (sensitive != other.sensitive) return false
if (inReplyTo != other.inReplyTo) return false
if (attachment != other.attachment) return false
if (tag != other.tag) return false
return true
}
@ -51,6 +56,7 @@ constructor(
result = 31 * result + sensitive.hashCode()
result = 31 * result + (inReplyTo?.hashCode() ?: 0)
result = 31 * result + attachment.hashCode()
result = 31 * result + tag.hashCode()
return result
}
@ -64,7 +70,8 @@ constructor(
"cc=$cc, " +
"sensitive=$sensitive, " +
"inReplyTo=$inReplyTo, " +
"attachment=$attachment" +
"attachment=$attachment, " +
"tag=$tag" +
")" +
" ${super.toString()}"
}

View File

@ -1,10 +1,12 @@
package dev.usbharu.hideout.activitypub.service.objects.note
import dev.usbharu.hideout.activitypub.domain.exception.FailedToGetActivityPubResourceException
import dev.usbharu.hideout.activitypub.domain.model.Emoji
import dev.usbharu.hideout.activitypub.domain.model.Note
import dev.usbharu.hideout.activitypub.query.NoteQueryService
import dev.usbharu.hideout.activitypub.service.common.APResourceResolveService
import dev.usbharu.hideout.activitypub.service.common.resolve
import dev.usbharu.hideout.activitypub.service.objects.emoji.EmojiService
import dev.usbharu.hideout.activitypub.service.objects.user.APUserService
import dev.usbharu.hideout.core.domain.model.post.Post
import dev.usbharu.hideout.core.domain.model.post.PostRepository
@ -32,7 +34,8 @@ class APNoteServiceImpl(
private val apResourceResolveService: APResourceResolveService,
private val postBuilder: Post.PostBuilder,
private val noteQueryService: NoteQueryService,
private val mediaService: MediaService
private val mediaService: MediaService,
private val emojiService: EmojiService
) : APNoteService {
@ -101,6 +104,16 @@ class APNoteServiceImpl(
postRepository.findByUrl(it)
}
val emojis = note.tag
.filterIsInstance<Emoji>()
.map {
emojiService.fetchEmoji(it).second
}
.map {
it.id
}
val mediaList = note.attachment.map {
mediaService.uploadRemoteMedia(
RemoteMedia(
@ -123,7 +136,8 @@ class APNoteServiceImpl(
replyId = reply?.id,
sensitive = note.sensitive,
apId = note.id,
mediaIds = mediaList
mediaIds = mediaList,
emojiIds = emojis
)
)
return note to createRemote

View File

@ -148,6 +148,6 @@ object PostsMedia : Table("posts_media") {
object PostsEmojis : Table("posts_emojis") {
val postId = long("post_id").references(Posts.id)
val emojiId = long("emoji_id").references(Posts.id)
val emojiId = long("emoji_id").references(CustomEmojis.id)
override val primaryKey: PrimaryKey = PrimaryKey(postId, emojiId)
}

View File

@ -3,6 +3,7 @@ package dev.usbharu.hideout.activitypub.domain.model
import com.fasterxml.jackson.module.kotlin.readValue
import dev.usbharu.hideout.activitypub.service.objects.note.APNoteServiceImpl.Companion.public
import dev.usbharu.hideout.application.config.ActivityPubConfig
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Test
@ -51,11 +52,7 @@ class NoteSerializeTest {
"attachment": [],
"sensitive": false,
"tag": [
{
"type": "Mention",
"href": "https://calckey.jp/users/9bu1xzwjyb",
"name": "@trapezial@calckey.jp"
}
]
}"""
@ -77,4 +74,105 @@ class NoteSerializeTest {
)
assertEquals(note, readValue)
}
@Test
fun 絵文字付きNoteのデシリアライズができる() {
val json = """{
"@context": [
"https://www.w3.org/ns/activitystreams",
"https://w3id.org/security/v1",
{
"manuallyApprovesFollowers": "as:manuallyApprovesFollowers",
"sensitive": "as:sensitive",
"Hashtag": "as:Hashtag",
"quoteUrl": "as:quoteUrl",
"toot": "http://joinmastodon.org/ns#",
"Emoji": "toot:Emoji",
"featured": "toot:featured",
"discoverable": "toot:discoverable",
"schema": "http://schema.org#",
"PropertyValue": "schema:PropertyValue",
"value": "schema:value",
"misskey": "https://misskey-hub.net/ns#",
"_misskey_content": "misskey:_misskey_content",
"_misskey_quote": "misskey:_misskey_quote",
"_misskey_reaction": "misskey:_misskey_reaction",
"_misskey_votes": "misskey:_misskey_votes",
"_misskey_summary": "misskey:_misskey_summary",
"isCat": "misskey:isCat",
"vcard": "http://www.w3.org/2006/vcard/ns#"
}
],
"id": "https://misskey.usbharu.dev/notes/9nj1omt1rn",
"type": "Note",
"attributedTo": "https://misskey.usbharu.dev/users/97ws8y3rj6",
"content": "<p>:oyasumi:</p>",
"_misskey_content": ":oyasumi:",
"source": {
"content": ":oyasumi:",
"mediaType": "text/x.misskeymarkdown"
},
"published": "2023-12-21T17:32:36.853Z",
"to": [
"https://www.w3.org/ns/activitystreams#Public"
],
"cc": [
"https://misskey.usbharu.dev/users/97ws8y3rj6/followers"
],
"inReplyTo": null,
"attachment": [],
"sensitive": false,
"tag": [
{
"id": "https://misskey.usbharu.dev/emojis/oyasumi",
"type": "Emoji",
"name": ":oyasumi:",
"updated": "2023-04-07T08:21:25.246Z",
"icon": {
"type": "Image",
"mediaType": "image/png",
"url": "https://s3misskey.usbharu.dev/misskey-minio/misskey-minio/data/cf8db710-1d70-4076-8a00-dbb28131096e.png"
}
}
]
}"""
val objectMapper = ActivityPubConfig().objectMapper()
val expected = Note(
type = emptyList(),
id = "https://misskey.usbharu.dev/notes/9nj1omt1rn",
attributedTo = "https://misskey.usbharu.dev/users/97ws8y3rj6",
content = "<p>\u200B:oyasumi:\u200B</p>",
published = "2023-12-21T17:32:36.853Z",
to = listOf("https://www.w3.org/ns/activitystreams#Public"),
cc = listOf("https://misskey.usbharu.dev/users/97ws8y3rj6/followers"),
sensitive = false,
inReplyTo = null,
attachment = emptyList(),
tag = listOf(
Emoji(
type = emptyList(),
name = ":oyasumi:",
id = "https://misskey.usbharu.dev/emojis/oyasumi",
updated = "2023-04-07T08:21:25.246Z",
icon = Image(
type = emptyList(),
mediaType = "image/png",
url = "https://s3misskey.usbharu.dev/misskey-minio/misskey-minio/data/cf8db710-1d70-4076-8a00-dbb28131096e.png"
)
)
)
)
expected.context = listOf(
"https://www.w3.org/ns/activitystreams",
"https://w3id.org/security/v1"
)
val note = objectMapper.readValue<Note>(json)
assertThat(note).isEqualTo(expected)
}
}

View File

@ -73,6 +73,7 @@ class APNoteServiceImplTest {
apResourceResolveService = mock(),
postBuilder = Post.PostBuilder(CharacterLimit()),
noteQueryService = noteQueryService,
mock(),
mock()
)
@ -142,7 +143,8 @@ class APNoteServiceImplTest {
apResourceResolveService = apResourceResolveService,
postBuilder = Post.PostBuilder(CharacterLimit()),
noteQueryService = noteQueryService,
mock()
mock(),
mock { }
)
val actual = apNoteServiceImpl.fetchNote(url)
@ -190,6 +192,7 @@ class APNoteServiceImplTest {
apResourceResolveService = apResourceResolveService,
postBuilder = Post.PostBuilder(CharacterLimit()),
noteQueryService = noteQueryService,
mock(),
mock()
)
@ -240,6 +243,7 @@ class APNoteServiceImplTest {
apResourceResolveService = mock(),
postBuilder = postBuilder,
noteQueryService = noteQueryService,
mock(),
mock()
)
@ -292,6 +296,7 @@ class APNoteServiceImplTest {
apResourceResolveService = mock(),
postBuilder = postBuilder,
noteQueryService = noteQueryService,
mock(),
mock()
)