mirror of https://github.com/usbharu/Hideout.git
feat: 受け取ったノートのEmojiを認識するように
This commit is contained in:
parent
0a54bdfc15
commit
43033b6f4b
|
@ -1,6 +1,8 @@
|
||||||
package dev.usbharu.hideout.activitypub.domain.model
|
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.Object
|
||||||
|
import dev.usbharu.hideout.activitypub.domain.model.objects.ObjectDeserializer
|
||||||
|
|
||||||
open class Note
|
open class Note
|
||||||
@Suppress("LongParameterList")
|
@Suppress("LongParameterList")
|
||||||
|
@ -14,7 +16,9 @@ constructor(
|
||||||
val cc: List<String> = emptyList(),
|
val cc: List<String> = emptyList(),
|
||||||
val sensitive: Boolean = false,
|
val sensitive: Boolean = false,
|
||||||
val inReplyTo: String? = null,
|
val inReplyTo: String? = null,
|
||||||
val attachment: List<Document> = emptyList()
|
val attachment: List<Document> = emptyList(),
|
||||||
|
@JsonDeserialize(contentUsing = ObjectDeserializer::class)
|
||||||
|
val tag: List<Object> = emptyList()
|
||||||
) : Object(
|
) : Object(
|
||||||
type = add(type, "Note")
|
type = add(type, "Note")
|
||||||
),
|
),
|
||||||
|
@ -36,6 +40,7 @@ constructor(
|
||||||
if (sensitive != other.sensitive) return false
|
if (sensitive != other.sensitive) return false
|
||||||
if (inReplyTo != other.inReplyTo) return false
|
if (inReplyTo != other.inReplyTo) return false
|
||||||
if (attachment != other.attachment) return false
|
if (attachment != other.attachment) return false
|
||||||
|
if (tag != other.tag) return false
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
@ -51,6 +56,7 @@ constructor(
|
||||||
result = 31 * result + sensitive.hashCode()
|
result = 31 * result + sensitive.hashCode()
|
||||||
result = 31 * result + (inReplyTo?.hashCode() ?: 0)
|
result = 31 * result + (inReplyTo?.hashCode() ?: 0)
|
||||||
result = 31 * result + attachment.hashCode()
|
result = 31 * result + attachment.hashCode()
|
||||||
|
result = 31 * result + tag.hashCode()
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,7 +70,8 @@ constructor(
|
||||||
"cc=$cc, " +
|
"cc=$cc, " +
|
||||||
"sensitive=$sensitive, " +
|
"sensitive=$sensitive, " +
|
||||||
"inReplyTo=$inReplyTo, " +
|
"inReplyTo=$inReplyTo, " +
|
||||||
"attachment=$attachment" +
|
"attachment=$attachment, " +
|
||||||
|
"tag=$tag" +
|
||||||
")" +
|
")" +
|
||||||
" ${super.toString()}"
|
" ${super.toString()}"
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
package dev.usbharu.hideout.activitypub.service.objects.note
|
package dev.usbharu.hideout.activitypub.service.objects.note
|
||||||
|
|
||||||
import dev.usbharu.hideout.activitypub.domain.exception.FailedToGetActivityPubResourceException
|
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.domain.model.Note
|
||||||
import dev.usbharu.hideout.activitypub.query.NoteQueryService
|
import dev.usbharu.hideout.activitypub.query.NoteQueryService
|
||||||
import dev.usbharu.hideout.activitypub.service.common.APResourceResolveService
|
import dev.usbharu.hideout.activitypub.service.common.APResourceResolveService
|
||||||
import dev.usbharu.hideout.activitypub.service.common.resolve
|
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.activitypub.service.objects.user.APUserService
|
||||||
import dev.usbharu.hideout.core.domain.model.post.Post
|
import dev.usbharu.hideout.core.domain.model.post.Post
|
||||||
import dev.usbharu.hideout.core.domain.model.post.PostRepository
|
import dev.usbharu.hideout.core.domain.model.post.PostRepository
|
||||||
|
@ -32,7 +34,8 @@ class APNoteServiceImpl(
|
||||||
private val apResourceResolveService: APResourceResolveService,
|
private val apResourceResolveService: APResourceResolveService,
|
||||||
private val postBuilder: Post.PostBuilder,
|
private val postBuilder: Post.PostBuilder,
|
||||||
private val noteQueryService: NoteQueryService,
|
private val noteQueryService: NoteQueryService,
|
||||||
private val mediaService: MediaService
|
private val mediaService: MediaService,
|
||||||
|
private val emojiService: EmojiService
|
||||||
|
|
||||||
) : APNoteService {
|
) : APNoteService {
|
||||||
|
|
||||||
|
@ -101,6 +104,16 @@ class APNoteServiceImpl(
|
||||||
postRepository.findByUrl(it)
|
postRepository.findByUrl(it)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val emojis = note.tag
|
||||||
|
.filterIsInstance<Emoji>()
|
||||||
|
.map {
|
||||||
|
emojiService.fetchEmoji(it).second
|
||||||
|
}
|
||||||
|
.map {
|
||||||
|
it.id
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
val mediaList = note.attachment.map {
|
val mediaList = note.attachment.map {
|
||||||
mediaService.uploadRemoteMedia(
|
mediaService.uploadRemoteMedia(
|
||||||
RemoteMedia(
|
RemoteMedia(
|
||||||
|
@ -123,7 +136,8 @@ class APNoteServiceImpl(
|
||||||
replyId = reply?.id,
|
replyId = reply?.id,
|
||||||
sensitive = note.sensitive,
|
sensitive = note.sensitive,
|
||||||
apId = note.id,
|
apId = note.id,
|
||||||
mediaIds = mediaList
|
mediaIds = mediaList,
|
||||||
|
emojiIds = emojis
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
return note to createRemote
|
return note to createRemote
|
||||||
|
|
|
@ -148,6 +148,6 @@ object PostsMedia : Table("posts_media") {
|
||||||
|
|
||||||
object PostsEmojis : Table("posts_emojis") {
|
object PostsEmojis : Table("posts_emojis") {
|
||||||
val postId = long("post_id").references(Posts.id)
|
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)
|
override val primaryKey: PrimaryKey = PrimaryKey(postId, emojiId)
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ package dev.usbharu.hideout.activitypub.domain.model
|
||||||
import com.fasterxml.jackson.module.kotlin.readValue
|
import com.fasterxml.jackson.module.kotlin.readValue
|
||||||
import dev.usbharu.hideout.activitypub.service.objects.note.APNoteServiceImpl.Companion.public
|
import dev.usbharu.hideout.activitypub.service.objects.note.APNoteServiceImpl.Companion.public
|
||||||
import dev.usbharu.hideout.application.config.ActivityPubConfig
|
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.Assertions.assertEquals
|
||||||
import org.junit.jupiter.api.Test
|
import org.junit.jupiter.api.Test
|
||||||
|
|
||||||
|
@ -51,11 +52,7 @@ class NoteSerializeTest {
|
||||||
"attachment": [],
|
"attachment": [],
|
||||||
"sensitive": false,
|
"sensitive": false,
|
||||||
"tag": [
|
"tag": [
|
||||||
{
|
|
||||||
"type": "Mention",
|
|
||||||
"href": "https://calckey.jp/users/9bu1xzwjyb",
|
|
||||||
"name": "@trapezial@calckey.jp"
|
|
||||||
}
|
|
||||||
]
|
]
|
||||||
}"""
|
}"""
|
||||||
|
|
||||||
|
@ -77,4 +74,105 @@ class NoteSerializeTest {
|
||||||
)
|
)
|
||||||
assertEquals(note, readValue)
|
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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,6 +73,7 @@ class APNoteServiceImplTest {
|
||||||
apResourceResolveService = mock(),
|
apResourceResolveService = mock(),
|
||||||
postBuilder = Post.PostBuilder(CharacterLimit()),
|
postBuilder = Post.PostBuilder(CharacterLimit()),
|
||||||
noteQueryService = noteQueryService,
|
noteQueryService = noteQueryService,
|
||||||
|
mock(),
|
||||||
mock()
|
mock()
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -142,7 +143,8 @@ class APNoteServiceImplTest {
|
||||||
apResourceResolveService = apResourceResolveService,
|
apResourceResolveService = apResourceResolveService,
|
||||||
postBuilder = Post.PostBuilder(CharacterLimit()),
|
postBuilder = Post.PostBuilder(CharacterLimit()),
|
||||||
noteQueryService = noteQueryService,
|
noteQueryService = noteQueryService,
|
||||||
mock()
|
mock(),
|
||||||
|
mock { }
|
||||||
)
|
)
|
||||||
|
|
||||||
val actual = apNoteServiceImpl.fetchNote(url)
|
val actual = apNoteServiceImpl.fetchNote(url)
|
||||||
|
@ -190,6 +192,7 @@ class APNoteServiceImplTest {
|
||||||
apResourceResolveService = apResourceResolveService,
|
apResourceResolveService = apResourceResolveService,
|
||||||
postBuilder = Post.PostBuilder(CharacterLimit()),
|
postBuilder = Post.PostBuilder(CharacterLimit()),
|
||||||
noteQueryService = noteQueryService,
|
noteQueryService = noteQueryService,
|
||||||
|
mock(),
|
||||||
mock()
|
mock()
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -240,6 +243,7 @@ class APNoteServiceImplTest {
|
||||||
apResourceResolveService = mock(),
|
apResourceResolveService = mock(),
|
||||||
postBuilder = postBuilder,
|
postBuilder = postBuilder,
|
||||||
noteQueryService = noteQueryService,
|
noteQueryService = noteQueryService,
|
||||||
|
mock(),
|
||||||
mock()
|
mock()
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -292,6 +296,7 @@ class APNoteServiceImplTest {
|
||||||
apResourceResolveService = mock(),
|
apResourceResolveService = mock(),
|
||||||
postBuilder = postBuilder,
|
postBuilder = postBuilder,
|
||||||
noteQueryService = noteQueryService,
|
noteQueryService = noteQueryService,
|
||||||
|
mock(),
|
||||||
mock()
|
mock()
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue