Merge pull request #170 from usbharu/feature/null-safe-ap-pojo

Feature/null safe ap pojo
This commit is contained in:
usbharu 2023-11-28 12:44:32 +09:00 committed by GitHub
commit 38bd655653
73 changed files with 559 additions and 517 deletions

View File

@ -1,5 +1,7 @@
package dev.usbharu.hideout.activitypub.domain.exception package dev.usbharu.hideout.activitypub.domain.exception
import java.io.Serial
class FailedProcessException : RuntimeException { class FailedProcessException : RuntimeException {
constructor() : super() constructor() : super()
constructor(message: String?) : super(message) constructor(message: String?) : super(message)
@ -11,4 +13,9 @@ class FailedProcessException : RuntimeException {
enableSuppression, enableSuppression,
writableStackTrace writableStackTrace
) )
companion object {
@Serial
private const val serialVersionUID: Long = -1305337651143409144L
}
} }

View File

@ -1,10 +1,16 @@
package dev.usbharu.hideout.activitypub.domain.exception package dev.usbharu.hideout.activitypub.domain.exception
import dev.usbharu.hideout.core.domain.exception.FailedToGetResourcesException import dev.usbharu.hideout.core.domain.exception.FailedToGetResourcesException
import java.io.Serial
class FailedToGetActivityPubResourceException : FailedToGetResourcesException { class FailedToGetActivityPubResourceException : FailedToGetResourcesException {
constructor() : super() constructor() : super()
constructor(s: String?) : super(s) constructor(s: String?) : super(s)
constructor(message: String?, cause: Throwable?) : super(message, cause) constructor(message: String?, cause: Throwable?) : super(message, cause)
constructor(cause: Throwable?) : super(cause) constructor(cause: Throwable?) : super(cause)
companion object {
@Serial
private const val serialVersionUID: Long = 6420233106776818052L
}
} }

View File

@ -1,5 +1,7 @@
package dev.usbharu.hideout.activitypub.domain.exception package dev.usbharu.hideout.activitypub.domain.exception
import java.io.Serial
class HttpSignatureUnauthorizedException : RuntimeException { class HttpSignatureUnauthorizedException : RuntimeException {
constructor() : super() constructor() : super()
constructor(message: String?) : super(message) constructor(message: String?) : super(message)
@ -11,4 +13,9 @@ class HttpSignatureUnauthorizedException : RuntimeException {
enableSuppression, enableSuppression,
writableStackTrace writableStackTrace
) )
companion object {
@Serial
private const val serialVersionUID: Long = -6449793151674654501L
}
} }

View File

@ -1,41 +1,52 @@
package dev.usbharu.hideout.activitypub.domain.model package dev.usbharu.hideout.activitypub.domain.model
import com.fasterxml.jackson.annotation.JsonCreator
import com.fasterxml.jackson.annotation.JsonProperty
import com.fasterxml.jackson.databind.annotation.JsonDeserialize 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 import dev.usbharu.hideout.activitypub.domain.model.objects.ObjectDeserializer
open class Accept : Object { open class Accept @JsonCreator constructor(
type: List<String> = emptyList(),
override val name: String,
@JsonDeserialize(using = ObjectDeserializer::class) @JsonDeserialize(using = ObjectDeserializer::class)
@Suppress("VariableNaming") @JsonProperty("object")
var `object`: Object? = null val apObject: Object,
override val actor: String
protected constructor() ) : Object(
constructor( type = add(type, "Accept")
type: List<String> = emptyList(), ),
name: String, HasActor,
`object`: Object?, HasName {
actor: String?
) : super(
type = add(type, "Accept"),
name = name,
actor = actor
) {
this.`object` = `object`
}
override fun toString(): String = "Accept(`object`=$`object`) ${super.toString()}"
override fun equals(other: Any?): Boolean { override fun equals(other: Any?): Boolean {
if (this === other) return true if (this === other) return true
if (other !is Accept) return false if (javaClass != other?.javaClass) return false
if (!super.equals(other)) return false if (!super.equals(other)) return false
return `object` == other.`object` other as Accept
if (name != other.name) return false
if (apObject != other.apObject) return false
if (actor != other.actor) return false
return true
} }
override fun hashCode(): Int { override fun hashCode(): Int {
var result = super.hashCode() var result = super.hashCode()
result = 31 * result + (`object`?.hashCode() ?: 0) result = 31 * result + name.hashCode()
result = 31 * result + apObject.hashCode()
result = 31 * result + actor.hashCode()
return result return result
} }
override fun toString(): String {
return "Accept(" +
"name='$name', " +
"apObject=$apObject, " +
"actor='$actor'" +
")" +
" ${super.toString()}"
}
} }

View File

@ -1,49 +1,64 @@
package dev.usbharu.hideout.activitypub.domain.model package dev.usbharu.hideout.activitypub.domain.model
import com.fasterxml.jackson.annotation.JsonProperty
import com.fasterxml.jackson.databind.annotation.JsonDeserialize 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 import dev.usbharu.hideout.activitypub.domain.model.objects.ObjectDeserializer
open class Create : Object { open class Create(
type: List<String> = emptyList(),
override val name: String,
@JsonDeserialize(using = ObjectDeserializer::class) @JsonDeserialize(using = ObjectDeserializer::class)
@Suppress("VariableNaming") @JsonProperty("object")
var `object`: Object? = null val apObject: Object,
var to: List<String> = emptyList() override val actor: String,
var cc: List<String> = emptyList() override val id: String,
val to: List<String> = emptyList(),
protected constructor() : super() val cc: List<String> = emptyList()
constructor( ) : Object(
type: List<String> = emptyList(), type = add(type, "Create")
name: String? = null, ),
`object`: Object?, HasId,
actor: String? = null, HasName,
id: String? = null, HasActor {
to: List<String> = emptyList(),
cc: List<String> = emptyList()
) : super(
type = add(type, "Create"),
name = name,
actor = actor,
id = id
) {
this.`object` = `object`
this.to = to
this.cc = cc
}
override fun equals(other: Any?): Boolean { override fun equals(other: Any?): Boolean {
if (this === other) return true if (this === other) return true
if (other !is Create) return false if (javaClass != other?.javaClass) return false
if (!super.equals(other)) return false if (!super.equals(other)) return false
return `object` == other.`object` other as Create
if (name != other.name) return false
if (apObject != other.apObject) return false
if (actor != other.actor) return false
if (id != other.id) return false
if (to != other.to) return false
if (cc != other.cc) return false
return true
} }
override fun hashCode(): Int { override fun hashCode(): Int {
var result = super.hashCode() var result = super.hashCode()
result = 31 * result + (`object`?.hashCode() ?: 0) result = 31 * result + name.hashCode()
result = 31 * result + apObject.hashCode()
result = 31 * result + actor.hashCode()
result = 31 * result + id.hashCode()
result = 31 * result + to.hashCode()
result = 31 * result + cc.hashCode()
return result return result
} }
override fun toString(): String = "Create(`object`=$`object`) ${super.toString()}" override fun toString(): String {
return "Create(" +
"name='$name', " +
"apObject=$apObject, " +
"actor='$actor', " +
"id='$id', " +
"to=$to, " +
"cc=$cc" +
")" +
" ${super.toString()}"
}
} }

View File

@ -1,46 +1,55 @@
package dev.usbharu.hideout.activitypub.domain.model package dev.usbharu.hideout.activitypub.domain.model
import com.fasterxml.jackson.annotation.JsonProperty
import com.fasterxml.jackson.databind.annotation.JsonDeserialize 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 import dev.usbharu.hideout.activitypub.domain.model.objects.ObjectDeserializer
open class Delete : Object { open class Delete : Object, HasId, HasActor {
@JsonDeserialize(using = ObjectDeserializer::class) @JsonDeserialize(using = ObjectDeserializer::class)
@Suppress("VariableNaming") @JsonProperty("object")
var `object`: Object? = null val apObject: Object
var published: String? = null val published: String
override val actor: String
override val id: String
constructor( constructor(
type: List<String> = emptyList(), type: List<String> = emptyList(),
name: String? = "Delete",
actor: String, actor: String,
id: String, id: String,
`object`: Object, `object`: Object,
published: String? published: String
) : super(add(type, "Delete"), name, actor, id) { ) : super(add(type, "Delete")) {
this.`object` = `object` this.apObject = `object`
this.published = published this.published = published
this.actor = actor
this.id = id
} }
protected constructor() : super()
override fun equals(other: Any?): Boolean { override fun equals(other: Any?): Boolean {
if (this === other) return true if (this === other) return true
if (other !is Delete) return false if (javaClass != other?.javaClass) return false
if (!super.equals(other)) return false if (!super.equals(other)) return false
if (`object` != other.`object`) return false other as Delete
if (apObject != other.apObject) return false
if (published != other.published) return false if (published != other.published) return false
if (actor != other.actor) return false
if (id != other.id) return false
return true return true
} }
override fun hashCode(): Int { override fun hashCode(): Int {
var result = super.hashCode() var result = super.hashCode()
result = 31 * result + (`object`?.hashCode() ?: 0) result = 31 * result + (apObject?.hashCode() ?: 0)
result = 31 * result + (published?.hashCode() ?: 0) result = 31 * result + (published?.hashCode() ?: 0)
result = 31 * result + actor.hashCode()
result = 31 * result + id.hashCode()
return result return result
} }
override fun toString(): String = "Delete(`object`=$`object`, published=$published) ${super.toString()}" override fun toString(): String =
"Delete(`object`=$apObject, published=$published, actor='$actor', id='$id') ${super.toString()}"
} }

View File

@ -2,44 +2,37 @@ package dev.usbharu.hideout.activitypub.domain.model
import dev.usbharu.hideout.activitypub.domain.model.objects.Object import dev.usbharu.hideout.activitypub.domain.model.objects.Object
open class Document : Object { open class Document(
type: List<String> = emptyList(),
var mediaType: String? = null override val name: String = "",
var url: String? = null val mediaType: String,
val url: String
protected constructor() : super() ) : Object(
constructor( type = add(type, "Document")
type: List<String> = emptyList(), ),
name: String? = null, HasName {
mediaType: String,
url: String
) : super(
type = add(type, "Document"),
name = name,
actor = null,
id = null
) {
this.mediaType = mediaType
this.url = url
}
override fun equals(other: Any?): Boolean { override fun equals(other: Any?): Boolean {
if (this === other) return true if (this === other) return true
if (other !is Document) return false if (javaClass != other?.javaClass) return false
if (!super.equals(other)) return false if (!super.equals(other)) return false
other as Document
if (mediaType != other.mediaType) return false if (mediaType != other.mediaType) return false
if (url != other.url) return false if (url != other.url) return false
if (name != other.name) return false
return true return true
} }
override fun hashCode(): Int { override fun hashCode(): Int {
var result = super.hashCode() var result = super.hashCode()
result = 31 * result + (mediaType?.hashCode() ?: 0) result = 31 * result + mediaType.hashCode()
result = 31 * result + (url?.hashCode() ?: 0) result = 31 * result + url.hashCode()
result = 31 * result + name.hashCode()
return result return result
} }
override fun toString(): String = "Document(mediaType=$mediaType, url=$url) ${super.toString()}" override fun toString(): String = "Document(mediaType=$mediaType, url=$url, name='$name') ${super.toString()}"
} }

View File

@ -2,27 +2,17 @@ package dev.usbharu.hideout.activitypub.domain.model
import dev.usbharu.hideout.activitypub.domain.model.objects.Object import dev.usbharu.hideout.activitypub.domain.model.objects.Object
open class Emoji : Object { open class Emoji(
var updated: String? = null type: List<String>,
var icon: Image? = null override val name: String,
override val id: String,
protected constructor() : super() val updated: String,
constructor( val icon: Image
type: List<String>, ) : Object(
name: String?, type = add(type, "Emoji")
actor: String?, ),
id: String?, HasName,
updated: String?, HasId {
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 { override fun equals(other: Any?): Boolean {
if (this === other) return true if (this === other) return true
@ -35,8 +25,8 @@ open class Emoji : Object {
override fun hashCode(): Int { override fun hashCode(): Int {
var result = super.hashCode() var result = super.hashCode()
result = 31 * result + (updated?.hashCode() ?: 0) result = 31 * result + updated.hashCode()
result = 31 * result + (icon?.hashCode() ?: 0) result = 31 * result + icon.hashCode()
return result return result
} }

View File

@ -1,38 +1,36 @@
package dev.usbharu.hideout.activitypub.domain.model package dev.usbharu.hideout.activitypub.domain.model
import com.fasterxml.jackson.annotation.JsonProperty
import dev.usbharu.hideout.activitypub.domain.model.objects.Object import dev.usbharu.hideout.activitypub.domain.model.objects.Object
open class Follow : Object { open class Follow(
@Suppress("VariableNaming") type: List<String> = emptyList(),
var `object`: String? = null @JsonProperty("object") val apObject: String,
override val actor: String
protected constructor() : super() ) : Object(
constructor( type = add(type, "Follow")
type: List<String> = emptyList(), ),
name: String?, HasActor {
`object`: String?,
actor: String?
) : super(
type = add(type, "Follow"),
name = name,
actor = actor
) {
this.`object` = `object`
}
override fun equals(other: Any?): Boolean { override fun equals(other: Any?): Boolean {
if (this === other) return true if (this === other) return true
if (other !is Follow) return false if (javaClass != other?.javaClass) return false
if (!super.equals(other)) return false if (!super.equals(other)) return false
return `object` == other.`object` other as Follow
if (apObject != other.apObject) return false
if (actor != other.actor) return false
return true
} }
override fun hashCode(): Int { override fun hashCode(): Int {
var result = super.hashCode() var result = super.hashCode()
result = 31 * result + (`object`?.hashCode() ?: 0) result = 31 * result + apObject.hashCode()
result = 31 * result + actor.hashCode()
return result return result
} }
override fun toString(): String = "Follow(`object`=$`object`) ${super.toString()}" override fun toString(): String = "Follow(`object`=$apObject, actor='$actor') ${super.toString()}"
} }

View File

@ -0,0 +1,5 @@
package dev.usbharu.hideout.activitypub.domain.model
interface HasActor {
val actor: String
}

View File

@ -0,0 +1,5 @@
package dev.usbharu.hideout.activitypub.domain.model
interface HasId {
val id: String
}

View File

@ -0,0 +1,5 @@
package dev.usbharu.hideout.activitypub.domain.model
interface HasName {
val name: String
}

View File

@ -2,32 +2,33 @@ package dev.usbharu.hideout.activitypub.domain.model
import dev.usbharu.hideout.activitypub.domain.model.objects.Object import dev.usbharu.hideout.activitypub.domain.model.objects.Object
open class Image : Object { open class Image(
private var mediaType: String? = null type: List<String> = emptyList(),
private var url: String? = null val mediaType: String,
val url: String
protected constructor() : super() ) : Object(
constructor(type: List<String> = emptyList(), name: String, mediaType: String?, url: String?) : super( add(type, "Image")
add(type, "Image"), ) {
name
) {
this.mediaType = mediaType
this.url = url
}
override fun equals(other: Any?): Boolean { override fun equals(other: Any?): Boolean {
if (this === other) return true if (this === other) return true
if (other !is Image) return false if (javaClass != other?.javaClass) return false
if (!super.equals(other)) return false if (!super.equals(other)) return false
other as Image
if (mediaType != other.mediaType) return false if (mediaType != other.mediaType) return false
return url == other.url if (url != other.url) return false
return true
} }
override fun hashCode(): Int { override fun hashCode(): Int {
var result = super.hashCode() var result = super.hashCode()
result = 31 * result + (mediaType?.hashCode() ?: 0) result = 31 * result + mediaType.hashCode()
result = 31 * result + (url?.hashCode() ?: 0) result = 31 * result + url.hashCode()
return result return result
} }
override fun toString(): String = "Image(mediaType=$mediaType, url=$url) ${super.toString()}"
} }

View File

@ -2,41 +2,37 @@ package dev.usbharu.hideout.activitypub.domain.model
import dev.usbharu.hideout.activitypub.domain.model.objects.Object import dev.usbharu.hideout.activitypub.domain.model.objects.Object
open class Key : Object { open class Key(
var owner: String? = null type: List<String>,
var publicKeyPem: String? = null override val id: String,
val owner: String,
protected constructor() : super() val publicKeyPem: String
constructor( ) : Object(
type: List<String>, type = add(list = type, type = "Key")
name: String, ),
id: String, HasId {
owner: String?,
publicKeyPem: String?
) : super(
type = add(list = type, type = "Key"),
name = name,
id = id
) {
this.owner = owner
this.publicKeyPem = publicKeyPem
}
override fun equals(other: Any?): Boolean { override fun equals(other: Any?): Boolean {
if (this === other) return true if (this === other) return true
if (other !is Key) return false if (javaClass != other?.javaClass) return false
if (!super.equals(other)) return false if (!super.equals(other)) return false
other as Key
if (owner != other.owner) return false if (owner != other.owner) return false
return publicKeyPem == other.publicKeyPem if (publicKeyPem != other.publicKeyPem) return false
if (id != other.id) return false
return true
} }
override fun hashCode(): Int { override fun hashCode(): Int {
var result = super.hashCode() var result = super.hashCode()
result = 31 * result + (owner?.hashCode() ?: 0) result = 31 * result + owner.hashCode()
result = 31 * result + (publicKeyPem?.hashCode() ?: 0) result = 31 * result + publicKeyPem.hashCode()
result = 31 * result + id.hashCode()
return result return result
} }
override fun toString(): String = "Key(owner=$owner, publicKeyPem=$publicKeyPem) ${super.toString()}" override fun toString(): String = "Key(owner=$owner, publicKeyPem=$publicKeyPem, id='$id') ${super.toString()}"
} }

View File

@ -1,54 +1,57 @@
package dev.usbharu.hideout.activitypub.domain.model package dev.usbharu.hideout.activitypub.domain.model
import com.fasterxml.jackson.annotation.JsonProperty
import com.fasterxml.jackson.databind.annotation.JsonDeserialize 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 import dev.usbharu.hideout.activitypub.domain.model.objects.ObjectDeserializer
open class Like : Object { open class Like(
@Suppress("VariableNaming") type: List<String> = emptyList(),
var `object`: String? = null override val actor: String,
var content: String? = null override val id: String,
@JsonProperty("object") val apObject: String,
@JsonDeserialize(contentUsing = ObjectDeserializer::class) val content: String,
var tag: List<Object> = emptyList() @JsonDeserialize(contentUsing = ObjectDeserializer::class) val tag: List<Object> = emptyList()
) : Object(
protected constructor() : super() type = add(type, "Like")
constructor( ),
type: List<String> = emptyList(), HasId,
name: String?, HasActor {
actor: String?,
id: String?,
`object`: String?,
content: String?,
tag: List<Object> = emptyList()
) : 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 { override fun equals(other: Any?): Boolean {
if (this === other) return true if (this === other) return true
if (other !is Like) return false if (javaClass != other?.javaClass) return false
if (!super.equals(other)) return false if (!super.equals(other)) return false
if (`object` != other.`object`) return false other as Like
if (actor != other.actor) return false
if (id != other.id) return false
if (apObject != other.apObject) return false
if (content != other.content) return false if (content != other.content) return false
return tag == other.tag if (tag != other.tag) return false
return true
} }
override fun hashCode(): Int { override fun hashCode(): Int {
var result = super.hashCode() var result = super.hashCode()
result = 31 * result + (`object`?.hashCode() ?: 0) result = 31 * result + actor.hashCode()
result = 31 * result + (content?.hashCode() ?: 0) result = 31 * result + id.hashCode()
result = 31 * result + apObject.hashCode()
result = 31 * result + content.hashCode()
result = 31 * result + tag.hashCode() result = 31 * result + tag.hashCode()
return result return result
} }
override fun toString(): String = "Like(`object`=$`object`, content=$content, tag=$tag) ${super.toString()}" override fun toString(): String {
return "Like(" +
"actor='$actor', " +
"id='$id', " +
"apObject='$apObject', " +
"content='$content', " +
"tag=$tag" +
")" +
" ${super.toString()}"
}
} }

View File

@ -2,79 +2,70 @@ package dev.usbharu.hideout.activitypub.domain.model
import dev.usbharu.hideout.activitypub.domain.model.objects.Object import dev.usbharu.hideout.activitypub.domain.model.objects.Object
open class Note : Object { open class Note
var attributedTo: String? = null @Suppress("LongParameterList")
var attachment: List<Document> = emptyList() constructor(
var content: String? = null type: List<String> = emptyList(),
var published: String? = null override val id: String,
var to: List<String> = emptyList() val attributedTo: String,
var cc: List<String> = emptyList() val content: String,
var sensitive: Boolean = false val published: String,
var inReplyTo: String? = null val to: List<String> = emptyList(),
val cc: List<String> = emptyList(),
protected constructor() : super() val sensitive: Boolean = false,
val inReplyTo: String? = null,
@Suppress("LongParameterList") val attachment: List<Document> = emptyList()
constructor( ) : Object(
type: List<String> = emptyList(), type = add(type, "Note")
name: String, ),
id: String?, HasId {
attributedTo: String?,
content: String?,
published: String?,
to: List<String> = emptyList(),
cc: List<String> = emptyList(),
sensitive: Boolean = false,
inReplyTo: String? = null,
attachment: List<Document> = emptyList()
) : super(
type = add(type, "Note"),
name = name,
id = id
) {
this.attributedTo = attributedTo
this.content = content
this.published = published
this.to = to
this.cc = cc
this.sensitive = sensitive
this.inReplyTo = inReplyTo
this.attachment = attachment
}
override fun equals(other: Any?): Boolean { override fun equals(other: Any?): Boolean {
if (this === other) return true if (this === other) return true
if (other !is Note) return false if (javaClass != other?.javaClass) return false
if (!super.equals(other)) return false if (!super.equals(other)) return false
other as Note
if (id != other.id) return false
if (attributedTo != other.attributedTo) return false if (attributedTo != other.attributedTo) return false
if (attachment != other.attachment) return false
if (content != other.content) return false if (content != other.content) return false
if (published != other.published) return false if (published != other.published) return false
if (to != other.to) return false if (to != other.to) return false
if (cc != other.cc) return false if (cc != other.cc) return false
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
return true return true
} }
override fun hashCode(): Int { override fun hashCode(): Int {
var result = super.hashCode() var result = super.hashCode()
result = 31 * result + (attributedTo?.hashCode() ?: 0) result = 31 * result + id.hashCode()
result = 31 * result + attachment.hashCode() result = 31 * result + attributedTo.hashCode()
result = 31 * result + (content?.hashCode() ?: 0) result = 31 * result + content.hashCode()
result = 31 * result + (published?.hashCode() ?: 0) result = 31 * result + published.hashCode()
result = 31 * result + to.hashCode() result = 31 * result + to.hashCode()
result = 31 * result + cc.hashCode() result = 31 * result + cc.hashCode()
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()
return result return result
} }
override fun toString(): String { override fun toString(): String {
return "Note(attributedTo=$attributedTo, attachment=$attachment, " + return "Note(" +
"content=$content, published=$published, to=$to, cc=$cc, sensitive=$sensitive," + "id='$id', " +
" inReplyTo=$inReplyTo) ${super.toString()}" "attributedTo='$attributedTo', " +
"content='$content', " +
"published='$published', " +
"to=$to, " +
"cc=$cc, " +
"sensitive=$sensitive, " +
"inReplyTo=$inReplyTo, " +
"attachment=$attachment" +
")" +
" ${super.toString()}"
} }
} }

View File

@ -2,47 +2,23 @@ package dev.usbharu.hideout.activitypub.domain.model
import dev.usbharu.hideout.activitypub.domain.model.objects.Object import dev.usbharu.hideout.activitypub.domain.model.objects.Object
open class Person : Object { open class Person
var preferredUsername: String? = null @Suppress("LongParameterList")
var summary: String? = null constructor(
var inbox: String? = null type: List<String> = emptyList(),
var outbox: String? = null override val name: String,
var url: String? = null override val id: String,
private var icon: Image? = null var preferredUsername: String?,
var publicKey: Key? = null var summary: String?,
var endpoints: Map<String, String> = emptyMap() var inbox: String,
var following: String? = null var outbox: String,
var followers: String? = null var url: String,
private var icon: Image?,
protected constructor() : super() var publicKey: Key?,
var endpoints: Map<String, String> = emptyMap(),
@Suppress("LongParameterList") var followers: String?,
constructor( var following: String?
type: List<String> = emptyList(), ) : Object(add(type, "Person")), HasId, HasName {
name: String,
id: String?,
preferredUsername: String?,
summary: String?,
inbox: String?,
outbox: String?,
url: String?,
icon: Image?,
publicKey: Key?,
endpoints: Map<String, String> = emptyMap(),
followers: String?,
following: String?
) : super(add(type, "Person"), name, id = id) {
this.preferredUsername = preferredUsername
this.summary = summary
this.inbox = inbox
this.outbox = outbox
this.url = url
this.icon = icon
this.publicKey = publicKey
this.endpoints = endpoints
this.followers = followers
this.following = following
}
override fun equals(other: Any?): Boolean { override fun equals(other: Any?): Boolean {
if (this === other) return true if (this === other) return true
@ -65,9 +41,9 @@ open class Person : Object {
var result = super.hashCode() var result = super.hashCode()
result = 31 * result + (preferredUsername?.hashCode() ?: 0) result = 31 * result + (preferredUsername?.hashCode() ?: 0)
result = 31 * result + (summary?.hashCode() ?: 0) result = 31 * result + (summary?.hashCode() ?: 0)
result = 31 * result + (inbox?.hashCode() ?: 0) result = 31 * result + inbox.hashCode()
result = 31 * result + (outbox?.hashCode() ?: 0) result = 31 * result + outbox.hashCode()
result = 31 * result + (url?.hashCode() ?: 0) result = 31 * result + url.hashCode()
result = 31 * result + (icon?.hashCode() ?: 0) result = 31 * result + (icon?.hashCode() ?: 0)
result = 31 * result + (publicKey?.hashCode() ?: 0) result = 31 * result + (publicKey?.hashCode() ?: 0)
result = 31 * result + endpoints.hashCode() result = 31 * result + endpoints.hashCode()

View File

@ -2,11 +2,24 @@ package dev.usbharu.hideout.activitypub.domain.model
import dev.usbharu.hideout.activitypub.domain.model.objects.Object import dev.usbharu.hideout.activitypub.domain.model.objects.Object
open class Tombstone : Object { open class Tombstone(type: List<String> = emptyList(), override val id: String) :
constructor( Object(add(type, "Tombstone")),
type: List<String> = emptyList(), HasId {
name: String = "Tombstone", override fun equals(other: Any?): Boolean {
actor: String? = null, if (this === other) return true
id: String if (javaClass != other?.javaClass) return false
) : super(add(type, "Tombstone"), name, actor, id) if (!super.equals(other)) return false
other as Tombstone
return id == other.id
}
override fun hashCode(): Int {
var result = super.hashCode()
result = 31 * result + id.hashCode()
return result
}
override fun toString(): String = "Tombstone(id='$id') ${super.toString()}"
} }

View File

@ -3,43 +3,41 @@ package dev.usbharu.hideout.activitypub.domain.model
import com.fasterxml.jackson.databind.annotation.JsonDeserialize 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 import dev.usbharu.hideout.activitypub.domain.model.objects.ObjectDeserializer
import java.time.Instant
open class Undo : Object {
open class Undo(
type: List<String> = emptyList(),
override val actor: String,
override val id: String,
@JsonDeserialize(using = ObjectDeserializer::class) @JsonDeserialize(using = ObjectDeserializer::class)
@Suppress("VariableNaming") @Suppress("VariableNaming") val `object`: Object,
var `object`: Object? = null val published: String
var published: String? = null ) : Object(add(type, "Undo")), HasId, HasActor {
protected constructor() : super()
constructor(
type: List<String> = emptyList(),
name: String,
actor: String,
id: String?,
`object`: Object,
published: Instant
) : super(add(type, "Undo"), name, actor, id) {
this.`object` = `object`
this.published = published.toString()
}
override fun equals(other: Any?): Boolean { override fun equals(other: Any?): Boolean {
if (this === other) return true if (this === other) return true
if (other !is Undo) return false if (javaClass != other?.javaClass) return false
if (!super.equals(other)) return false if (!super.equals(other)) return false
other as Undo
if (`object` != other.`object`) return false if (`object` != other.`object`) return false
return published == other.published if (published != other.published) return false
if (actor != other.actor) return false
if (id != other.id) return false
return true
} }
override fun hashCode(): Int { override fun hashCode(): Int {
var result = super.hashCode() var result = super.hashCode()
result = 31 * result + (`object`?.hashCode() ?: 0) result = 31 * result + (`object`?.hashCode() ?: 0)
result = 31 * result + (published?.hashCode() ?: 0) result = 31 * result + (published?.hashCode() ?: 0)
result = 31 * result + actor.hashCode()
result = 31 * result + id.hashCode()
return result return result
} }
override fun toString(): String = "Undo(`object`=$`object`, published=$published) ${super.toString()}" override fun toString(): String {
return "Undo(`object`=$`object`, published=$published, actor='$actor', id='$id') ${super.toString()}"
}
} }

View File

@ -12,41 +12,29 @@ open class Object : JsonLd {
set(value) { set(value) {
field = value.filter { it.isNotBlank() } field = value.filter { it.isNotBlank() }
} }
var name: String? = null
var actor: String? = null
var id: String? = null
protected constructor() protected constructor()
constructor(type: List<String>, name: String? = null, actor: String? = null, id: String? = null) : super() { constructor(type: List<String>) : super() {
this.type = type.filter { it.isNotBlank() } this.type = type.filter { it.isNotBlank() }
this.name = name
this.actor = actor
this.id = id
} }
override fun equals(other: Any?): Boolean { override fun equals(other: Any?): Boolean {
if (this === other) return true if (this === other) return true
if (other !is Object) return false if (javaClass != other?.javaClass) return false
if (!super.equals(other)) return false if (!super.equals(other)) return false
if (type != other.type) return false other as Object
if (name != other.name) return false
if (actor != other.actor) return false
if (id != other.id) return false
return true return type == other.type
} }
override fun hashCode(): Int { override fun hashCode(): Int {
var result = super.hashCode() var result = super.hashCode()
result = 31 * result + type.hashCode() result = 31 * result + type.hashCode()
result = 31 * result + (name?.hashCode() ?: 0)
result = 31 * result + (actor?.hashCode() ?: 0)
result = 31 * result + (id?.hashCode() ?: 0)
return result return result
} }
override fun toString(): String = "Object(type=$type, name=$name, actor=$actor, id=$id) ${super.toString()}" override fun toString(): String = "Object(type=$type) ${super.toString()}"
companion object { companion object {
@JvmStatic @JvmStatic

View File

@ -15,9 +15,6 @@ class ObjectDeserializer : JsonDeserializer<Object>() {
if (treeNode.isValueNode) { if (treeNode.isValueNode) {
return ObjectValue( return ObjectValue(
emptyList(), emptyList(),
null,
null,
null,
treeNode.asText() treeNode.asText()
) )
} else if (treeNode.isObject) { } else if (treeNode.isObject) {

View File

@ -1,33 +1,27 @@
package dev.usbharu.hideout.activitypub.domain.model.objects package dev.usbharu.hideout.activitypub.domain.model.objects
import com.fasterxml.jackson.annotation.JsonCreator
@Suppress("VariableNaming") @Suppress("VariableNaming")
open class ObjectValue : Object { open class ObjectValue @JsonCreator constructor(type: List<String>, var `object`: String) : Object(
type
var `object`: String? = null ) {
protected constructor() : super()
constructor(type: List<String>, name: String?, actor: String?, id: String?, `object`: String?) : super(
type,
name,
actor,
id
) {
this.`object` = `object`
}
override fun equals(other: Any?): Boolean { override fun equals(other: Any?): Boolean {
if (this === other) return true if (this === other) return true
if (other !is ObjectValue) return false if (javaClass != other?.javaClass) return false
if (!super.equals(other)) return false if (!super.equals(other)) return false
other as ObjectValue
return `object` == other.`object` return `object` == other.`object`
} }
override fun hashCode(): Int { override fun hashCode(): Int {
var result = super.hashCode() var result = super.hashCode()
result = 31 * result + (`object`?.hashCode() ?: 0) result = 31 * result + `object`.hashCode()
return result return result
} }
override fun toString(): String = "ObjectValue(`object`=$`object`) ${super.toString()}" override fun toString(): String = "ObjectValue(`object`='$`object`') ${super.toString()}"
} }

View File

@ -64,7 +64,6 @@ class NoteQueryServiceImpl(private val postRepository: PostRepository, private v
this[Users.followers] this[Users.followers]
) )
return Note( return Note(
name = "Post",
id = this[Posts.apId], id = this[Posts.apId],
attributedTo = this[Users.url], attributedTo = this[Users.url],
content = this[Posts.text], content = this[Posts.text],

View File

@ -12,7 +12,7 @@ import dev.usbharu.hideout.core.query.UserQueryService
import dev.usbharu.hideout.core.service.user.UserService import dev.usbharu.hideout.core.service.user.UserService
class ApAcceptProcessor( class ApAcceptProcessor(
private val transaction: Transaction, transaction: Transaction,
private val userQueryService: UserQueryService, private val userQueryService: UserQueryService,
private val followerQueryService: FollowerQueryService, private val followerQueryService: FollowerQueryService,
private val userService: UserService private val userService: UserService
@ -20,17 +20,17 @@ class ApAcceptProcessor(
AbstractActivityPubProcessor<Accept>(transaction) { AbstractActivityPubProcessor<Accept>(transaction) {
override suspend fun internalProcess(activity: ActivityPubProcessContext<Accept>) { override suspend fun internalProcess(activity: ActivityPubProcessContext<Accept>) {
val value = activity.activity.`object` ?: throw IllegalActivityPubObjectException("object is null") val value = activity.activity.apObject ?: throw IllegalActivityPubObjectException("object is null")
if (value.type.contains("Follow").not()) { if (value.type.contains("Follow").not()) {
logger.warn("FAILED Activity type is not Follow.") logger.warn("FAILED Activity type isn't Follow.")
throw IllegalActivityPubObjectException("Invalid type ${value.type}") throw IllegalActivityPubObjectException("Invalid type ${value.type}")
} }
val follow = value as Follow val follow = value as Follow
val userUrl = follow.`object` ?: throw IllegalActivityPubObjectException("object is null") val userUrl = follow.apObject
val followerUrl = follow.actor ?: throw IllegalActivityPubObjectException("actor is null") val followerUrl = follow.actor
val user = userQueryService.findByUrl(userUrl) val user = userQueryService.findByUrl(userUrl)
val follower = userQueryService.findByUrl(followerUrl) val follower = userQueryService.findByUrl(followerUrl)

View File

@ -33,7 +33,7 @@ class ApSendCreateServiceImpl(
val note = noteQueryService.findById(post.id).first val note = noteQueryService.findById(post.id).first
val create = Create( val create = Create(
name = "Create Note", name = "Create Note",
`object` = note, apObject = note,
actor = note.attributedTo, actor = note.attributedTo,
id = "${applicationConfig.url}/create/note/${post.id}" id = "${applicationConfig.url}/create/note/${post.id}"
) )

View File

@ -11,9 +11,9 @@ import org.springframework.stereotype.Service
@Service @Service
class CreateActivityProcessor(transaction: Transaction, private val apNoteService: APNoteService) : class CreateActivityProcessor(transaction: Transaction, private val apNoteService: APNoteService) :
AbstractActivityPubProcessor<Create>(transaction, false) { AbstractActivityPubProcessor<Create>(transaction) {
override suspend fun internalProcess(activity: ActivityPubProcessContext<Create>) { override suspend fun internalProcess(activity: ActivityPubProcessContext<Create>) {
apNoteService.fetchNote(activity.activity.`object` as Note) apNoteService.fetchNote(activity.activity.apObject as Note)
} }
override fun isSupported(activityType: ActivityType): Boolean = activityType == ActivityType.Create override fun isSupported(activityType: ActivityType): Boolean = activityType == ActivityType.Create

View File

@ -2,6 +2,7 @@ package dev.usbharu.hideout.activitypub.service.activity.delete
import dev.usbharu.hideout.activitypub.domain.exception.IllegalActivityPubObjectException import dev.usbharu.hideout.activitypub.domain.exception.IllegalActivityPubObjectException
import dev.usbharu.hideout.activitypub.domain.model.Delete import dev.usbharu.hideout.activitypub.domain.model.Delete
import dev.usbharu.hideout.activitypub.domain.model.HasId
import dev.usbharu.hideout.activitypub.service.common.AbstractActivityPubProcessor import dev.usbharu.hideout.activitypub.service.common.AbstractActivityPubProcessor
import dev.usbharu.hideout.activitypub.service.common.ActivityPubProcessContext import dev.usbharu.hideout.activitypub.service.common.ActivityPubProcessContext
import dev.usbharu.hideout.activitypub.service.common.ActivityType import dev.usbharu.hideout.activitypub.service.common.ActivityType
@ -17,7 +18,11 @@ class APDeleteProcessor(
) : ) :
AbstractActivityPubProcessor<Delete>(transaction) { AbstractActivityPubProcessor<Delete>(transaction) {
override suspend fun internalProcess(activity: ActivityPubProcessContext<Delete>) { override suspend fun internalProcess(activity: ActivityPubProcessContext<Delete>) {
val deleteId = activity.activity.`object`?.id ?: throw IllegalActivityPubObjectException("object.id is null") val value = activity.activity.apObject
if (value !is HasId) {
throw IllegalActivityPubObjectException("object hasn't id")
}
val deleteId = value.id
val post = try { val post = try {
postQueryService.findByApId(deleteId) postQueryService.findByApId(deleteId)

View File

@ -1,7 +1,6 @@
package dev.usbharu.hideout.activitypub.service.activity.follow package dev.usbharu.hideout.activitypub.service.activity.follow
import com.fasterxml.jackson.databind.ObjectMapper import com.fasterxml.jackson.databind.ObjectMapper
import dev.usbharu.hideout.activitypub.domain.exception.IllegalActivityPubObjectException
import dev.usbharu.hideout.activitypub.domain.model.Follow import dev.usbharu.hideout.activitypub.domain.model.Follow
import dev.usbharu.hideout.activitypub.service.common.AbstractActivityPubProcessor import dev.usbharu.hideout.activitypub.service.common.AbstractActivityPubProcessor
import dev.usbharu.hideout.activitypub.service.common.ActivityPubProcessContext import dev.usbharu.hideout.activitypub.service.common.ActivityPubProcessContext
@ -18,13 +17,13 @@ class APFollowProcessor(
) : ) :
AbstractActivityPubProcessor<Follow>(transaction) { AbstractActivityPubProcessor<Follow>(transaction) {
override suspend fun internalProcess(activity: ActivityPubProcessContext<Follow>) { override suspend fun internalProcess(activity: ActivityPubProcessContext<Follow>) {
logger.info("FOLLOW from: {} to {}", activity.activity.actor, activity.activity.`object`) logger.info("FOLLOW from: {} to {}", activity.activity.actor, activity.activity.apObject)
// inboxをジョブキューに乗せているので既に不要だが、フォロー承認制アカウントを実装する際に必要なので残す // inboxをジョブキューに乗せているので既に不要だが、フォロー承認制アカウントを実装する際に必要なので残す
val jobProps = ReceiveFollowJobParam( val jobProps = ReceiveFollowJobParam(
activity.activity.actor ?: throw IllegalActivityPubObjectException("actor is null"), activity.activity.actor,
objectMapper.writeValueAsString(activity.activity), objectMapper.writeValueAsString(activity.activity),
activity.activity.`object` ?: throw IllegalActivityPubObjectException("object is null") activity.activity.apObject
) )
jobQueueParentService.scheduleTypeSafe(ReceiveFollowJob, jobProps) jobQueueParentService.scheduleTypeSafe(ReceiveFollowJob, jobProps)
} }

View File

@ -33,13 +33,13 @@ class APReceiveFollowJobProcessor(
val signer = userQueryService.findByUrl(param.targetActor) val signer = userQueryService.findByUrl(param.targetActor)
val urlString = person.inbox ?: throw IllegalArgumentException("inbox is not found.") val urlString = person.inbox
apRequestService.apPost( apRequestService.apPost(
url = urlString, url = urlString,
body = Accept( body = Accept(
name = "Follow", name = "Follow",
`object` = follow, apObject = follow,
actor = param.targetActor actor = param.targetActor
), ),
signer = signer signer = signer
@ -47,7 +47,7 @@ class APReceiveFollowJobProcessor(
val targetEntity = userQueryService.findByUrl(param.targetActor) val targetEntity = userQueryService.findByUrl(param.targetActor)
val followActorEntity = val followActorEntity =
userQueryService.findByUrl(follow.actor ?: throw IllegalArgumentException("actor is null")) userQueryService.findByUrl(follow.actor)
userService.followRequest(targetEntity.id, followActorEntity.id) userService.followRequest(targetEntity.id, followActorEntity.id)
logger.info("SUCCESS Follow from: {} to: {}", param.targetActor, param.actor) logger.info("SUCCESS Follow from: {} to: {}", param.targetActor, param.actor)

View File

@ -18,11 +18,11 @@ class APReceiveFollowServiceImpl(
@Qualifier("activitypub") private val objectMapper: ObjectMapper @Qualifier("activitypub") private val objectMapper: ObjectMapper
) : APReceiveFollowService { ) : APReceiveFollowService {
override suspend fun receiveFollow(follow: Follow) { override suspend fun receiveFollow(follow: Follow) {
logger.info("FOLLOW from: {} to: {}", follow.actor, follow.`object`) logger.info("FOLLOW from: {} to: {}", follow.actor, follow.apObject)
jobQueueParentService.schedule(ReceiveFollowJob) { jobQueueParentService.schedule(ReceiveFollowJob) {
props[ReceiveFollowJob.actor] = follow.actor props[ReceiveFollowJob.actor] = follow.actor
props[ReceiveFollowJob.follow] = objectMapper.writeValueAsString(follow) props[ReceiveFollowJob.follow] = objectMapper.writeValueAsString(follow)
props[ReceiveFollowJob.targetActor] = follow.`object` props[ReceiveFollowJob.targetActor] = follow.apObject
} }
return return
} }

View File

@ -15,8 +15,7 @@ class APSendFollowServiceImpl(
) : APSendFollowService { ) : APSendFollowService {
override suspend fun sendFollow(sendFollowDto: SendFollowDto) { override suspend fun sendFollow(sendFollowDto: SendFollowDto) {
val follow = Follow( val follow = Follow(
name = "Follow", apObject = sendFollowDto.followTargetUserId.url,
`object` = sendFollowDto.followTargetUserId.url,
actor = sendFollowDto.userId.url actor = sendFollowDto.userId.url
) )

View File

@ -1,7 +1,6 @@
package dev.usbharu.hideout.activitypub.service.activity.like package dev.usbharu.hideout.activitypub.service.activity.like
import dev.usbharu.hideout.activitypub.domain.exception.FailedToGetActivityPubResourceException import dev.usbharu.hideout.activitypub.domain.exception.FailedToGetActivityPubResourceException
import dev.usbharu.hideout.activitypub.domain.exception.IllegalActivityPubObjectException
import dev.usbharu.hideout.activitypub.domain.model.Like import dev.usbharu.hideout.activitypub.domain.model.Like
import dev.usbharu.hideout.activitypub.service.common.AbstractActivityPubProcessor import dev.usbharu.hideout.activitypub.service.common.AbstractActivityPubProcessor
import dev.usbharu.hideout.activitypub.service.common.ActivityPubProcessContext import dev.usbharu.hideout.activitypub.service.common.ActivityPubProcessContext
@ -21,10 +20,10 @@ class APLikeProcessor(
) : ) :
AbstractActivityPubProcessor<Like>(transaction) { AbstractActivityPubProcessor<Like>(transaction) {
override suspend fun internalProcess(activity: ActivityPubProcessContext<Like>) { override suspend fun internalProcess(activity: ActivityPubProcessContext<Like>) {
val actor = activity.activity.actor ?: throw IllegalActivityPubObjectException("actor is null") val actor = activity.activity.actor
val content = activity.activity.content ?: throw IllegalActivityPubObjectException("content is null") val content = activity.activity.content
val target = activity.activity.`object` ?: throw IllegalActivityPubObjectException("object is null") val target = activity.activity.apObject
val personWithEntity = apUserService.fetchPersonWithEntity(actor) val personWithEntity = apUserService.fetchPersonWithEntity(actor)

View File

@ -21,9 +21,8 @@ class ApReactionJobProcessor(
apRequestService.apPost( apRequestService.apPost(
param.inbox, param.inbox,
Like( Like(
name = "Like",
actor = param.actor, actor = param.actor,
`object` = param.postUrl, apObject = param.postUrl,
id = "${applicationConfig.url}/liek/note/${param.id}", id = "${applicationConfig.url}/liek/note/${param.id}",
content = param.reaction content = param.reaction
), ),

View File

@ -28,11 +28,10 @@ class ApRemoveReactionJobProcessor(
apRequestService.apPost( apRequestService.apPost(
param.inbox, param.inbox,
Undo( Undo(
name = "Undo Reaction",
actor = param.actor, actor = param.actor,
`object` = like, `object` = like,
id = "${applicationConfig.url}/undo/like/${param.id}", id = "${applicationConfig.url}/undo/like/${param.id}",
published = Instant.now() published = Instant.now().toString()
), ),
signer signer
) )

View File

@ -24,7 +24,7 @@ class APUndoProcessor(
} }
val type = val type =
undo.`object`?.type.orEmpty() undo.`object`.type.orEmpty()
.firstOrNull { it == "Block" || it == "Follow" || it == "Like" || it == "Announce" || it == "Accept" } .firstOrNull { it == "Block" || it == "Follow" || it == "Like" || it == "Announce" || it == "Accept" }
?: return ?: return
@ -32,12 +32,12 @@ class APUndoProcessor(
"Follow" -> { "Follow" -> {
val follow = undo.`object` as Follow val follow = undo.`object` as Follow
if (follow.`object` == null) { if (follow.apObject == null) {
return return
} }
apUserService.fetchPerson(undo.actor!!, follow.`object`) apUserService.fetchPerson(undo.actor, follow.apObject)
val follower = userQueryService.findByUrl(undo.actor!!) val follower = userQueryService.findByUrl(undo.actor)
val target = userQueryService.findByUrl(follow.`object`!!) val target = userQueryService.findByUrl(follow.apObject)
userService.unfollow(target.id, follower.id) userService.unfollow(target.id, follower.id)
return return
} }

View File

@ -61,7 +61,7 @@ class APRequestServiceImpl(
url: String url: String
): HttpResponse { ): HttpResponse {
val headers = headers { val headers = headers {
append("Accept", ContentType.Application.Activity) append("Accept", Activity)
append("Date", date) append("Date", date)
append("Host", u.host) append("Host", u.host)
} }
@ -87,13 +87,13 @@ class APRequestServiceImpl(
remove("Host") remove("Host")
} }
} }
contentType(ContentType.Application.Activity) contentType(Activity)
} }
return httpResponse return httpResponse
} }
private suspend fun apGetNotSign(url: String, date: String?) = httpClient.get(url) { private suspend fun apGetNotSign(url: String, date: String?) = httpClient.get(url) {
header("Accept", ContentType.Application.Activity) header("Accept", Activity)
header("Date", date) header("Date", date)
} }
@ -153,12 +153,12 @@ class APRequestServiceImpl(
digest: String, digest: String,
requestBody: String? requestBody: String?
) = httpClient.post(url) { ) = httpClient.post(url) {
accept(ContentType.Application.Activity) accept(Activity)
header("Date", date) header("Date", date)
header("Digest", "sha-256=$digest") header("Digest", "sha-256=$digest")
if (requestBody != null) { if (requestBody != null) {
setBody(requestBody) setBody(requestBody)
contentType(ContentType.Application.Activity) contentType(Activity)
} }
} }
@ -170,7 +170,7 @@ class APRequestServiceImpl(
requestBody: String? requestBody: String?
): HttpResponse { ): HttpResponse {
val headers = headers { val headers = headers {
append("Accept", ContentType.Application.Activity) append("Accept", Activity)
append("Date", date) append("Date", date)
append("Host", u.host) append("Host", u.host)
append("Digest", "sha-256=$digest") append("Digest", "sha-256=$digest")
@ -196,7 +196,7 @@ class APRequestServiceImpl(
remove("Host") remove("Host")
} }
setBody(requestBody) setBody(requestBody)
contentType(ContentType.Application.Activity) contentType(Activity)
} }
return httpResponse return httpResponse
} }

View File

@ -5,13 +5,14 @@ import dev.usbharu.hideout.activitypub.domain.exception.FailedProcessException
import dev.usbharu.hideout.activitypub.domain.exception.HttpSignatureUnauthorizedException import dev.usbharu.hideout.activitypub.domain.exception.HttpSignatureUnauthorizedException
import dev.usbharu.hideout.activitypub.domain.model.objects.Object import dev.usbharu.hideout.activitypub.domain.model.objects.Object
import dev.usbharu.hideout.application.external.Transaction import dev.usbharu.hideout.application.external.Transaction
import org.slf4j.Logger
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
abstract class AbstractActivityPubProcessor<T : Object>( abstract class AbstractActivityPubProcessor<T : Object>(
private val transaction: Transaction, private val transaction: Transaction,
private val allowUnauthorized: Boolean = false private val allowUnauthorized: Boolean = false
) : ActivityPubProcessor<T> { ) : ActivityPubProcessor<T> {
protected val logger = LoggerFactory.getLogger(this::class.java) protected val logger: Logger = LoggerFactory.getLogger(this::class.java)
override suspend fun process(activity: ActivityPubProcessContext<T>) { override suspend fun process(activity: ActivityPubProcessContext<T>) {
if (activity.isAuthorized.not() && allowUnauthorized.not()) { if (activity.isAuthorized.not() && allowUnauthorized.not()) {

View File

@ -1,7 +1,6 @@
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.exception.IllegalActivityPubObjectException
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
@ -91,7 +90,7 @@ class APNoteServiceImpl(
requireNotNull(note.id) { "id is null" } requireNotNull(note.id) { "id is null" }
return try { return try {
noteQueryService.findByApid(note.id!!).first noteQueryService.findByApid(note.id).first
} catch (_: FailedToGetResourcesException) { } catch (_: FailedToGetResourcesException) {
saveNote(note, targetActor, url) saveNote(note, targetActor, url)
} }
@ -99,7 +98,7 @@ class APNoteServiceImpl(
private suspend fun saveNote(note: Note, targetActor: String?, url: String): Note { private suspend fun saveNote(note: Note, targetActor: String?, url: String): Note {
val person = apUserService.fetchPersonWithEntity( val person = apUserService.fetchPersonWithEntity(
note.attributedTo ?: throw IllegalActivityPubObjectException("note.attributedTo is null"), note.attributedTo,
targetActor targetActor
) )
@ -128,9 +127,9 @@ class APNoteServiceImpl(
.map { .map {
mediaService.uploadRemoteMedia( mediaService.uploadRemoteMedia(
RemoteMedia( RemoteMedia(
(it.name ?: it.url)!!, it.name,
it.url!!, it.url,
it.mediaType ?: "application/octet-stream", it.mediaType,
description = it.name description = it.name
) )
) )
@ -142,13 +141,13 @@ class APNoteServiceImpl(
postBuilder.of( postBuilder.of(
id = postRepository.generateId(), id = postRepository.generateId(),
userId = person.second.id, userId = person.second.id,
text = note.content.orEmpty(), text = note.content,
createdAt = Instant.parse(note.published).toEpochMilli(), createdAt = Instant.parse(note.published).toEpochMilli(),
visibility = visibility, visibility = visibility,
url = note.id ?: url, url = note.id,
replyId = reply?.id, replyId = reply?.id,
sensitive = note.sensitive, sensitive = note.sensitive,
apId = note.id ?: url, apId = note.id,
mediaIds = mediaList mediaIds = mediaList
) )
) )
@ -156,7 +155,7 @@ class APNoteServiceImpl(
} }
override suspend fun fetchNote(note: Note, targetActor: String?): Note = override suspend fun fetchNote(note: Note, targetActor: String?): Note =
saveIfMissing(note, targetActor, note.id ?: throw IllegalArgumentException("note.id is null")) saveIfMissing(note, targetActor, note.id)
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"

View File

@ -57,13 +57,11 @@ class APUserServiceImpl(
url = userUrl, url = userUrl,
icon = Image( icon = Image(
type = emptyList(), type = emptyList(),
name = "$userUrl/icon.png",
mediaType = "image/png", mediaType = "image/png",
url = "$userUrl/icon.png" url = "$userUrl/icon.png"
), ),
publicKey = Key( publicKey = Key(
type = emptyList(), type = emptyList(),
name = "Public Key",
id = userEntity.keyId, id = userEntity.keyId,
owner = userUrl, owner = userUrl,
publicKeyPem = userEntity.publicKey publicKeyPem = userEntity.publicKey
@ -85,7 +83,7 @@ class APUserServiceImpl(
} catch (ignore: FailedToGetResourcesException) { } catch (ignore: FailedToGetResourcesException) {
val person = apResourceResolveService.resolve<Person>(url, null as Long?) val person = apResourceResolveService.resolve<Person>(url, null as Long?)
val id = person.id ?: throw IllegalActivityPubObjectException("id is null") val id = person.id
try { try {
val userEntity = userQueryService.findByUrl(id) val userEntity = userQueryService.findByUrl(id)
return entityToPerson(userEntity, id) to userEntity return entityToPerson(userEntity, id) to userEntity
@ -96,11 +94,11 @@ class APUserServiceImpl(
name = person.preferredUsername name = person.preferredUsername
?: throw IllegalActivityPubObjectException("preferredUsername is null"), ?: throw IllegalActivityPubObjectException("preferredUsername is null"),
domain = id.substringAfter("://").substringBefore("/"), domain = id.substringAfter("://").substringBefore("/"),
screenName = (person.name ?: person.preferredUsername) screenName = person.name
?: throw IllegalActivityPubObjectException("preferredUsername is null"), ?: throw IllegalActivityPubObjectException("preferredUsername is null"),
description = person.summary.orEmpty(), description = person.summary.orEmpty(),
inbox = person.inbox ?: throw IllegalActivityPubObjectException("inbox is null"), inbox = person.inbox,
outbox = person.outbox ?: throw IllegalActivityPubObjectException("outbox is null"), outbox = person.outbox,
url = id, url = id,
publicKey = person.publicKey?.publicKeyPem publicKey = person.publicKey?.publicKeyPem
?: throw IllegalActivityPubObjectException("publicKey is null"), ?: throw IllegalActivityPubObjectException("publicKey is null"),
@ -127,13 +125,11 @@ class APUserServiceImpl(
url = id, url = id,
icon = Image( icon = Image(
type = emptyList(), type = emptyList(),
name = "$id/icon.png",
mediaType = "image/png", mediaType = "image/png",
url = "$id/icon.png" url = "$id/icon.png"
), ),
publicKey = Key( publicKey = Key(
type = emptyList(), type = emptyList(),
name = "Public Key",
id = userEntity.keyId, id = userEntity.keyId,
owner = id, owner = id,
publicKeyPem = userEntity.publicKey publicKeyPem = userEntity.publicKey

View File

@ -25,6 +25,7 @@ class ActivityPubConfig {
.enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY) .enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY)
.setSerializationInclusion(JsonInclude.Include.NON_EMPTY) .setSerializationInclusion(JsonInclude.Include.NON_EMPTY)
.setDefaultSetterInfo(JsonSetter.Value.forContentNulls(Nulls.AS_EMPTY)) .setDefaultSetterInfo(JsonSetter.Value.forContentNulls(Nulls.AS_EMPTY))
.setDefaultSetterInfo(JsonSetter.Value.forValueNulls(Nulls.AS_EMPTY))
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
.configure(JsonParser.Feature.ALLOW_COMMENTS, true) .configure(JsonParser.Feature.ALLOW_COMMENTS, true)
.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true) .configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true)

View File

@ -1,5 +1,7 @@
package dev.usbharu.hideout.core.domain.exception.media package dev.usbharu.hideout.core.domain.exception.media
import java.io.Serial
open class MediaConvertException : MediaException { open class MediaConvertException : MediaException {
constructor() : super() constructor() : super()
constructor(message: String?) : super(message) constructor(message: String?) : super(message)
@ -11,4 +13,9 @@ open class MediaConvertException : MediaException {
enableSuppression, enableSuppression,
writableStackTrace writableStackTrace
) )
companion object {
@Serial
private const val serialVersionUID: Long = -6349105549968160551L
}
} }

View File

@ -1,5 +1,7 @@
package dev.usbharu.hideout.core.domain.exception.media package dev.usbharu.hideout.core.domain.exception.media
import java.io.Serial
abstract class MediaException : RuntimeException { abstract class MediaException : RuntimeException {
constructor() : super() constructor() : super()
constructor(message: String?) : super(message) constructor(message: String?) : super(message)
@ -11,4 +13,9 @@ abstract class MediaException : RuntimeException {
enableSuppression, enableSuppression,
writableStackTrace writableStackTrace
) )
companion object {
@Serial
private const val serialVersionUID: Long = 5988922562494187852L
}
} }

View File

@ -1,5 +1,7 @@
package dev.usbharu.hideout.core.domain.exception.media package dev.usbharu.hideout.core.domain.exception.media
import java.io.Serial
open class MediaFileSizeException : MediaException { open class MediaFileSizeException : MediaException {
constructor() : super() constructor() : super()
constructor(message: String?) : super(message) constructor(message: String?) : super(message)
@ -11,4 +13,9 @@ open class MediaFileSizeException : MediaException {
enableSuppression, enableSuppression,
writableStackTrace writableStackTrace
) )
companion object {
@Serial
private const val serialVersionUID: Long = 8672626879026555064L
}
} }

View File

@ -1,5 +1,7 @@
package dev.usbharu.hideout.core.domain.exception.media package dev.usbharu.hideout.core.domain.exception.media
import java.io.Serial
class MediaFileSizeIsZeroException : MediaFileSizeException { class MediaFileSizeIsZeroException : MediaFileSizeException {
constructor() : super() constructor() : super()
constructor(message: String?) : super(message) constructor(message: String?) : super(message)
@ -11,4 +13,9 @@ class MediaFileSizeIsZeroException : MediaFileSizeException {
enableSuppression, enableSuppression,
writableStackTrace writableStackTrace
) )
companion object {
@Serial
private const val serialVersionUID: Long = -2398394583775317875L
}
} }

View File

@ -1,5 +1,7 @@
package dev.usbharu.hideout.core.domain.exception.media package dev.usbharu.hideout.core.domain.exception.media
import java.io.Serial
class MediaProcessException : MediaException { class MediaProcessException : MediaException {
constructor() : super() constructor() : super()
constructor(message: String?) : super(message) constructor(message: String?) : super(message)
@ -11,4 +13,9 @@ class MediaProcessException : MediaException {
enableSuppression, enableSuppression,
writableStackTrace writableStackTrace
) )
companion object {
@Serial
private const val serialVersionUID: Long = -5195233013542703735L
}
} }

View File

@ -1,5 +1,7 @@
package dev.usbharu.hideout.core.domain.exception.media package dev.usbharu.hideout.core.domain.exception.media
import java.io.Serial
class UnsupportedMediaException : MediaException { class UnsupportedMediaException : MediaException {
constructor() : super() constructor() : super()
constructor(message: String?) : super(message) constructor(message: String?) : super(message)
@ -11,4 +13,9 @@ class UnsupportedMediaException : MediaException {
enableSuppression, enableSuppression,
writableStackTrace writableStackTrace
) )
companion object {
@Serial
private const val serialVersionUID: Long = -116741513216017134L
}
} }

View File

@ -1,15 +1,11 @@
package dev.usbharu.hideout.core.domain.model.instance package dev.usbharu.hideout.core.domain.model.instance
class Nodeinfo { class Nodeinfo private constructor() {
var links: List<Links> = emptyList() var links: List<Links> = emptyList()
private constructor()
} }
class Links { class Links private constructor() {
var rel: String? = null var rel: String? = null
var href: String? = null var href: String? = null
private constructor()
} }

View File

@ -3,23 +3,17 @@
package dev.usbharu.hideout.core.domain.model.instance package dev.usbharu.hideout.core.domain.model.instance
@Suppress("ClassNaming") @Suppress("ClassNaming")
class Nodeinfo2_0 { class Nodeinfo2_0() {
var metadata: Metadata? = null var metadata: Metadata? = null
var software: Software? = null var software: Software? = null
constructor()
} }
class Metadata { class Metadata() {
var nodeName: String? = null var nodeName: String? = null
var nodeDescription: String? = null var nodeDescription: String? = null
constructor()
} }
class Software { class Software() {
var name: String? = null var name: String? = null
var version: String? = null var version: String? = null
constructor()
} }

View File

@ -54,7 +54,7 @@ class InstanceRepositoryImpl(private val idGenerateService: IdGenerateService) :
} }
override suspend fun delete(instance: InstanceEntity) { override suspend fun delete(instance: InstanceEntity) {
Instance.deleteWhere { Instance.id eq instance.id } Instance.deleteWhere { id eq instance.id }
} }
} }

View File

@ -62,7 +62,7 @@ class ExposedOAuth2AuthorizationService(
it[accessTokenMetadata] = accessToken?.metadata?.let { it1 -> mapToJson(it1) } it[accessTokenMetadata] = accessToken?.metadata?.let { it1 -> mapToJson(it1) }
it[accessTokenType] = accessToken?.token?.tokenType?.value it[accessTokenType] = accessToken?.token?.tokenType?.value
it[accessTokenScopes] = it[accessTokenScopes] =
accessToken?.run { token.scopes.joinToString(",").takeIf { it.isNotEmpty() } } accessToken?.run { token.scopes.joinToString(",").takeIf { s -> s.isNotEmpty() } }
it[refreshTokenValue] = refreshToken?.token?.tokenValue it[refreshTokenValue] = refreshToken?.token?.tokenValue
it[refreshTokenIssuedAt] = refreshToken?.token?.issuedAt it[refreshTokenIssuedAt] = refreshToken?.token?.issuedAt
it[refreshTokenExpiresAt] = refreshToken?.token?.expiresAt it[refreshTokenExpiresAt] = refreshToken?.token?.expiresAt

View File

@ -53,7 +53,7 @@ class InstanceServiceImpl(
name = nodeinfo20.metadata?.nodeName, name = nodeinfo20.metadata?.nodeName,
description = nodeinfo20.metadata?.nodeDescription, description = nodeinfo20.metadata?.nodeDescription,
url = resolveInstanceUrl, url = resolveInstanceUrl,
iconUrl = resolveInstanceUrl + "/favicon.ico", iconUrl = "$resolveInstanceUrl/favicon.ico",
sharedInbox = sharedInbox, sharedInbox = sharedInbox,
software = nodeinfo20.software?.name, software = nodeinfo20.software?.name,
version = nodeinfo20.software?.version version = nodeinfo20.software?.version
@ -72,7 +72,7 @@ class InstanceServiceImpl(
name = nodeinfo20.metadata?.nodeName, name = nodeinfo20.metadata?.nodeName,
description = nodeinfo20.metadata?.nodeDescription, description = nodeinfo20.metadata?.nodeDescription,
url = resolveInstanceUrl, url = resolveInstanceUrl,
iconUrl = resolveInstanceUrl + "/favicon.ico", iconUrl = "$resolveInstanceUrl/favicon.ico",
sharedInbox = sharedInbox, sharedInbox = sharedInbox,
software = nodeinfo20.software?.name, software = nodeinfo20.software?.name,
version = nodeinfo20.software?.version version = nodeinfo20.software?.version

View File

@ -5,4 +5,29 @@ data class MediaSave(
val prefix: String, val prefix: String,
val fileInputStream: ByteArray, val fileInputStream: ByteArray,
val thumbnailInputStream: ByteArray? val thumbnailInputStream: ByteArray?
) ) {
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false
other as MediaSave
if (name != other.name) return false
if (prefix != other.prefix) return false
if (!fileInputStream.contentEquals(other.fileInputStream)) return false
if (thumbnailInputStream != null) {
if (other.thumbnailInputStream == null) return false
if (!thumbnailInputStream.contentEquals(other.thumbnailInputStream)) return false
} else if (other.thumbnailInputStream != null) return false
return true
}
override fun hashCode(): Int {
var result = name.hashCode()
result = 31 * result + prefix.hashCode()
result = 31 * result + fileInputStream.contentHashCode()
result = 31 * result + (thumbnailInputStream?.contentHashCode() ?: 0)
return result
}
}

View File

@ -15,7 +15,7 @@ import dev.usbharu.hideout.core.domain.model.media.Media as EntityMedia
@Service @Service
@Suppress("TooGenericExceptionCaught") @Suppress("TooGenericExceptionCaught")
open class MediaServiceImpl( class MediaServiceImpl(
private val mediaDataStore: MediaDataStore, private val mediaDataStore: MediaDataStore,
private val fileTypeDeterminationService: FileTypeDeterminationService, private val fileTypeDeterminationService: FileTypeDeterminationService,
private val mediaBlurhashService: MediaBlurhashService, private val mediaBlurhashService: MediaBlurhashService,

View File

@ -3,4 +3,22 @@ package dev.usbharu.hideout.core.service.media
data class ProcessedFile( data class ProcessedFile(
val byteArray: ByteArray, val byteArray: ByteArray,
val extension: String val extension: String
) ) {
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false
other as ProcessedFile
if (!byteArray.contentEquals(other.byteArray)) return false
if (extension != other.extension) return false
return true
}
override fun hashCode(): Int {
var result = byteArray.contentHashCode()
result = 31 * result + extension.hashCode()
return result
}
}

View File

@ -6,6 +6,7 @@ import dev.usbharu.hideout.core.domain.model.reaction.Reaction
import dev.usbharu.hideout.core.domain.model.reaction.ReactionRepository import dev.usbharu.hideout.core.domain.model.reaction.ReactionRepository
import dev.usbharu.hideout.core.query.ReactionQueryService import dev.usbharu.hideout.core.query.ReactionQueryService
import org.jetbrains.exposed.exceptions.ExposedSQLException import org.jetbrains.exposed.exceptions.ExposedSQLException
import org.slf4j.Logger
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
import org.springframework.stereotype.Service import org.springframework.stereotype.Service
@ -50,6 +51,6 @@ class ReactionServiceImpl(
} }
companion object { companion object {
val LOGGER = LoggerFactory.getLogger(ReactionServiceImpl::class.java) val LOGGER: Logger = LoggerFactory.getLogger(ReactionServiceImpl::class.java)
} }
} }

View File

@ -18,7 +18,7 @@ class InMemoryCacheManager : CacheManager {
keyMutex.withLock { keyMutex.withLock {
cacheKey.filter { Instant.ofEpochMilli(it.value).plusSeconds(300) <= Instant.now() } cacheKey.filter { Instant.ofEpochMilli(it.value).plusSeconds(300) <= Instant.now() }
val cached = cacheKey.get(key) val cached = cacheKey[key]
if (cached == null) { if (cached == null) {
needRunBlock = true needRunBlock = true
cacheKey[key] = Instant.now().toEpochMilli() cacheKey[key] = Instant.now().toEpochMilli()

View File

@ -52,8 +52,7 @@ class UserServiceImpl(
createdAt = Instant.now(), createdAt = Instant.now(),
following = "$userUrl/following", following = "$userUrl/following",
followers = "$userUrl/followers", followers = "$userUrl/followers",
keyId = "$userUrl#pubkey", keyId = "$userUrl#pubkey"
instance = null
) )
return userRepository.save(userEntity) return userRepository.save(userEntity)
} }

View File

@ -1,5 +1,6 @@
package dev.usbharu.hideout.generate package dev.usbharu.hideout.generate
import org.slf4j.Logger
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
import org.springframework.core.MethodParameter import org.springframework.core.MethodParameter
import org.springframework.web.bind.support.WebDataBinderFactory import org.springframework.web.bind.support.WebDataBinderFactory
@ -49,6 +50,6 @@ class JsonOrFormModelMethodProcessor(
} }
companion object { companion object {
val logger = LoggerFactory.getLogger(JsonOrFormModelMethodProcessor::class.java) val logger: Logger = LoggerFactory.getLogger(JsonOrFormModelMethodProcessor::class.java)
} }
} }

View File

@ -11,6 +11,7 @@ import org.jetbrains.exposed.sql.select
import org.springframework.stereotype.Repository import org.springframework.stereotype.Repository
import java.time.Instant import java.time.Instant
@Suppress("IncompleteDestructuring")
@Repository @Repository
class StatusQueryServiceImpl : StatusQueryService { class StatusQueryServiceImpl : StatusQueryService {
override suspend fun findByPostIds(ids: List<Long>): List<Status> = findByPostIdsWithMedia(ids) override suspend fun findByPostIds(ids: List<Long>): List<Status> = findByPostIdsWithMedia(ids)

View File

@ -25,7 +25,6 @@ class MediaApiServiceImpl(private val mediaService: MediaService, private val tr
type = type, type = type,
url = uploadLocalMedia.url, url = uploadLocalMedia.url,
previewUrl = uploadLocalMedia.thumbnailUrl, previewUrl = uploadLocalMedia.thumbnailUrl,
remoteUrl = null,
description = mediaRequest.description, description = mediaRequest.description,
blurhash = uploadLocalMedia.blurHash, blurhash = uploadLocalMedia.blurHash,
textUrl = uploadLocalMedia.url textUrl = uploadLocalMedia.url

View File

@ -35,7 +35,7 @@ object AcctUtil {
} }
else -> { else -> {
throw IllegalArgumentException("Invalid acct.(Too many @)") throw IllegalArgumentException("Invalid acct. (Too many @)")
} }
} }
} }

View File

@ -3,10 +3,10 @@ package dev.usbharu.hideout.util
import io.ktor.http.* import io.ktor.http.*
object HttpUtil { object HttpUtil {
val ContentType.Application.Activity: ContentType val Activity: ContentType
get() = ContentType("application", "activity+json") get() = ContentType("application", "activity+json")
val ContentType.Application.JsonLd: ContentType val JsonLd: ContentType
get() { get() {
return ContentType( return ContentType(
contentType = "application", contentType = "application",

View File

@ -46,7 +46,6 @@ class DeleteSerializeTest {
val readValue = objectMapper.readValue<Delete>(json) val readValue = objectMapper.readValue<Delete>(json)
val expected = Delete( val expected = Delete(
name = null,
actor = "https://misskey.usbharu.dev/users/97ws8y3rj6", actor = "https://misskey.usbharu.dev/users/97ws8y3rj6",
id = "https://misskey.usbharu.dev/4b5b6ed5-9269-45f3-8403-cba1e74b4b69", id = "https://misskey.usbharu.dev/4b5b6ed5-9269-45f3-8403-cba1e74b4b69",
`object` = Tombstone( `object` = Tombstone(
@ -61,7 +60,6 @@ class DeleteSerializeTest {
@Test @Test
fun シリアライズできる() { fun シリアライズできる() {
val delete = Delete( val delete = Delete(
name = null,
actor = "https://misskey.usbharu.dev/users/97ws8y3rj6", actor = "https://misskey.usbharu.dev/users/97ws8y3rj6",
id = "https://misskey.usbharu.dev/4b5b6ed5-9269-45f3-8403-cba1e74b4b69", id = "https://misskey.usbharu.dev/4b5b6ed5-9269-45f3-8403-cba1e74b4b69",
`object` = Tombstone( `object` = Tombstone(
@ -75,7 +73,7 @@ class DeleteSerializeTest {
val actual = objectMapper.writeValueAsString(delete) val actual = objectMapper.writeValueAsString(delete)
val expected = val expected =
"""{"type":"Delete","actor":"https://misskey.usbharu.dev/users/97ws8y3rj6","id":"https://misskey.usbharu.dev/4b5b6ed5-9269-45f3-8403-cba1e74b4b69","object":{"type":"Tombstone","name":"Tombstone","id":"https://misskey.usbharu.dev/notes/9lkwqnwqk9"},"published":"2023-11-02T15:30:34.160Z"}""" """{"type":"Delete","actor":"https://misskey.usbharu.dev/users/97ws8y3rj6","id":"https://misskey.usbharu.dev/4b5b6ed5-9269-45f3-8403-cba1e74b4b69","object":{"type":"Tombstone","id":"https://misskey.usbharu.dev/notes/9lkwqnwqk9"},"published":"2023-11-02T15:30:34.160Z"}"""
assertEquals(expected, actual) assertEquals(expected, actual)
} }
} }

View File

@ -10,7 +10,6 @@ class NoteSerializeTest {
@Test @Test
fun Noteのシリアライズができる() { fun Noteのシリアライズができる() {
val note = Note( val note = Note(
name = "Note",
id = "https://example.com", id = "https://example.com",
attributedTo = "https://example.com/actor", attributedTo = "https://example.com/actor",
content = "Hello", content = "Hello",
@ -22,7 +21,7 @@ class NoteSerializeTest {
val writeValueAsString = objectMapper.writeValueAsString(note) val writeValueAsString = objectMapper.writeValueAsString(note)
assertEquals( assertEquals(
"{\"type\":\"Note\",\"name\":\"Note\",\"id\":\"https://example.com\",\"attributedTo\":\"https://example.com/actor\",\"content\":\"Hello\",\"published\":\"2023-05-20T10:28:17.308Z\",\"sensitive\":false}", """{"type":"Note","id":"https://example.com","attributedTo":"https://example.com/actor","content":"Hello","published":"2023-05-20T10:28:17.308Z","sensitive":false}""",
writeValueAsString writeValueAsString
) )
} }
@ -65,7 +64,6 @@ class NoteSerializeTest {
val readValue = objectMapper.readValue<Note>(json) val readValue = objectMapper.readValue<Note>(json)
val note = Note( val note = Note(
name = "",
id = "https://misskey.usbharu.dev/notes/9f2i9cm88e", id = "https://misskey.usbharu.dev/notes/9f2i9cm88e",
type = listOf("Note"), type = listOf("Note"),
attributedTo = "https://misskey.usbharu.dev/users/97ws8y3rj6", attributedTo = "https://misskey.usbharu.dev/users/97ws8y3rj6",
@ -77,7 +75,6 @@ class NoteSerializeTest {
inReplyTo = "https://calckey.jp/notes/9f2i7ymf1d", inReplyTo = "https://calckey.jp/notes/9f2i7ymf1d",
attachment = emptyList() attachment = emptyList()
) )
note.name = null
assertEquals(note, readValue) assertEquals(note, readValue)
} }
} }

View File

@ -1,8 +1,8 @@
package dev.usbharu.hideout.activitypub.domain.model package dev.usbharu.hideout.activitypub.domain.model
import dev.usbharu.hideout.application.config.ActivityPubConfig
import org.intellij.lang.annotations.Language import org.intellij.lang.annotations.Language
import org.junit.jupiter.api.Test import org.junit.jupiter.api.Test
import utils.JsonObjectMapper
import java.time.Clock import java.time.Clock
import java.time.Instant import java.time.Instant
import java.time.ZoneId import java.time.ZoneId
@ -12,18 +12,16 @@ class UndoTest {
fun Undoのシリアライズができる() { fun Undoのシリアライズができる() {
val undo = Undo( val undo = Undo(
emptyList(), emptyList(),
"Undo Follow",
"https://follower.example.com/", "https://follower.example.com/",
"https://follower.example.com/undo/1", "https://follower.example.com/undo/1",
Follow( Follow(
emptyList(), emptyList(),
null,
"https://follower.example.com/users/", "https://follower.example.com/users/",
actor = "https://follower.exaple.com/users/1" actor = "https://follower.exaple.com/users/1"
), ),
Instant.now(Clock.tickMillis(ZoneId.systemDefault())) Instant.now(Clock.tickMillis(ZoneId.systemDefault())).toString()
) )
val writeValueAsString = JsonObjectMapper.objectMapper.writeValueAsString(undo) val writeValueAsString = ActivityPubConfig().objectMapper().writeValueAsString(undo)
println(writeValueAsString) println(writeValueAsString)
} }
@ -70,7 +68,7 @@ class UndoTest {
""".trimIndent() """.trimIndent()
val undo = JsonObjectMapper.objectMapper.readValue(json, Undo::class.java) val undo = ActivityPubConfig().objectMapper().readValue(json, Undo::class.java)
println(undo) println(undo)
} }
} }

View File

@ -16,10 +16,7 @@ class ObjectSerializeTest {
val readValue = objectMapper.readValue<Object>(json) val readValue = objectMapper.readValue<Object>(json)
val expected = Object( val expected = Object(
listOf("Object"), listOf("Object")
null,
null,
null
) )
assertEquals(expected, readValue) assertEquals(expected, readValue)
} }
@ -34,10 +31,7 @@ class ObjectSerializeTest {
val readValue = objectMapper.readValue<Object>(json) val readValue = objectMapper.readValue<Object>(json)
val expected = Object( val expected = Object(
listOf("Hoge", "Object"), listOf("Hoge", "Object")
null,
null,
null
) )
assertEquals(expected, readValue) assertEquals(expected, readValue)
@ -53,10 +47,7 @@ class ObjectSerializeTest {
val readValue = objectMapper.readValue<Object>(json) val readValue = objectMapper.readValue<Object>(json)
val expected = Object( val expected = Object(
emptyList(), emptyList()
null,
null,
null
) )
assertEquals(expected, readValue) assertEquals(expected, readValue)

View File

@ -49,12 +49,10 @@ class UserAPControllerImplTest {
outbox = "https://example.com/users/hoge/outbox", outbox = "https://example.com/users/hoge/outbox",
url = "https://example.com/users/hoge", url = "https://example.com/users/hoge",
icon = Image( icon = Image(
name = "icon",
mediaType = "image/jpeg", mediaType = "image/jpeg",
url = "https://example.com/users/hoge/icon.jpg" url = "https://example.com/users/hoge/icon.jpg"
), ),
publicKey = Key( publicKey = Key(
name = "Public Key",
id = "https://example.com/users/hoge#pubkey", id = "https://example.com/users/hoge#pubkey",
owner = "https://example.com/users/hoge", owner = "https://example.com/users/hoge",
publicKeyPem = "-----BEGIN PUBLIC KEY-----...-----END PUBLIC KEY-----", publicKeyPem = "-----BEGIN PUBLIC KEY-----...-----END PUBLIC KEY-----",

View File

@ -53,7 +53,6 @@ class NoteApControllerImplTest {
fun `postAP 匿名で取得できる`() = runTest { fun `postAP 匿名で取得できる`() = runTest {
SecurityContextHolder.clearContext() SecurityContextHolder.clearContext()
val note = Note( val note = Note(
name = "Note",
id = "https://example.com/users/hoge/posts/1234", id = "https://example.com/users/hoge/posts/1234",
attributedTo = "https://example.com/users/hoge", attributedTo = "https://example.com/users/hoge",
content = "Hello", content = "Hello",
@ -90,7 +89,6 @@ class NoteApControllerImplTest {
@Test @Test
fun `postAP 認証に成功している場合userIdがnullでない`() = runTest { fun `postAP 認証に成功している場合userIdがnullでない`() = runTest {
val note = Note( val note = Note(
name = "Note",
id = "https://example.com/users/hoge/posts/1234", id = "https://example.com/users/hoge/posts/1234",
attributedTo = "https://example.com/users/hoge", attributedTo = "https://example.com/users/hoge",
content = "Hello", content = "Hello",

View File

@ -52,7 +52,6 @@ class ApSendCreateServiceImplTest {
val post = PostBuilder.of() val post = PostBuilder.of()
val user = UserBuilder.localUserOf(id = post.userId) val user = UserBuilder.localUserOf(id = post.userId)
val note = Note( val note = Note(
name = "Post",
id = post.apId, id = post.apId,
attributedTo = user.url, attributedTo = user.url,
content = post.text, content = post.text,

View File

@ -24,8 +24,7 @@ class APSendFollowServiceImplTest {
apSendFollowServiceImpl.sendFollow(sendFollowDto) apSendFollowServiceImpl.sendFollow(sendFollowDto)
val value = Follow( val value = Follow(
name = "Follow", apObject = sendFollowDto.followTargetUserId.url,
`object` = sendFollowDto.followTargetUserId.url,
actor = sendFollowDto.userId.url actor = sendFollowDto.userId.url
) )
verify(apRequestService, times(1)).apPost( verify(apRequestService, times(1)).apPost(

View File

@ -39,7 +39,7 @@ class APRequestServiceImplTest {
assertDoesNotThrow { assertDoesNotThrow {
dateTimeFormatter.parse(it.headers["Date"]) dateTimeFormatter.parse(it.headers["Date"])
} }
respond("{}") respond("""{"type":"Follow","object": "https://example.com","actor": "https://example.com"}""")
}), }),
objectMapper, objectMapper,
mock(), mock(),
@ -47,8 +47,7 @@ class APRequestServiceImplTest {
) )
val responseClass = Follow( val responseClass = Follow(
name = "Follow", apObject = "https://example.com",
`object` = "https://example.com",
actor = "https://example.com" actor = "https://example.com"
) )
apRequestServiceImpl.apGet("https://example.com", responseClass = responseClass::class.java) apRequestServiceImpl.apGet("https://example.com", responseClass = responseClass::class.java)
@ -65,7 +64,7 @@ class APRequestServiceImplTest {
assertDoesNotThrow { assertDoesNotThrow {
dateTimeFormatter.parse(it.headers["Date"]) dateTimeFormatter.parse(it.headers["Date"])
} }
respond("{}") respond("""{"type":"Follow","object": "https://example.com","actor": "https://example.com"}""")
}), }),
objectMapper, objectMapper,
mock(), mock(),
@ -73,8 +72,7 @@ class APRequestServiceImplTest {
) )
val responseClass = Follow( val responseClass = Follow(
name = "Follow", apObject = "https://example.com",
`object` = "https://example.com",
actor = "https://example.com" actor = "https://example.com"
) )
apRequestServiceImpl.apGet( apRequestServiceImpl.apGet(
@ -106,7 +104,7 @@ class APRequestServiceImplTest {
assertDoesNotThrow { assertDoesNotThrow {
dateTimeFormatter.parse(it.headers["Date"]) dateTimeFormatter.parse(it.headers["Date"])
} }
respond("{}") respond("""{"type":"Follow","object": "https://example.com","actor": "https://example.com"}""")
}), }),
objectMapper, objectMapper,
httpSignatureSigner, httpSignatureSigner,
@ -114,8 +112,7 @@ class APRequestServiceImplTest {
) )
val responseClass = Follow( val responseClass = Follow(
name = "Follow", apObject = "https://example.com",
`object` = "https://example.com",
actor = "https://example.com" actor = "https://example.com"
) )
apRequestServiceImpl.apGet( apRequestServiceImpl.apGet(
@ -166,8 +163,7 @@ class APRequestServiceImplTest {
}), objectMapper, mock(), dateTimeFormatter) }), objectMapper, mock(), dateTimeFormatter)
val body = Follow( val body = Follow(
name = "Follow", apObject = "https://example.com",
`object` = "https://example.com",
actor = "https://example.com" actor = "https://example.com"
) )
apRequestServiceImpl.apPost("https://example.com", body, null) apRequestServiceImpl.apPost("https://example.com", body, null)
@ -213,8 +209,7 @@ class APRequestServiceImplTest {
}), objectMapper, mock(), dateTimeFormatter) }), objectMapper, mock(), dateTimeFormatter)
val body = Follow( val body = Follow(
name = "Follow", apObject = "https://example.com",
`object` = "https://example.com",
actor = "https://example.com" actor = "https://example.com"
) )
apRequestServiceImpl.apPost("https://example.com", body, null) apRequestServiceImpl.apPost("https://example.com", body, null)
@ -244,8 +239,7 @@ class APRequestServiceImplTest {
}), objectMapper, mock(), dateTimeFormatter) }), objectMapper, mock(), dateTimeFormatter)
val body = Follow( val body = Follow(
name = "Follow", apObject = "https://example.com",
`object` = "https://example.com",
actor = "https://example.com" actor = "https://example.com"
) )
apRequestServiceImpl.apPost("https://example.com", body, UserBuilder.remoteUserOf()) apRequestServiceImpl.apPost("https://example.com", body, UserBuilder.remoteUserOf())
@ -286,8 +280,7 @@ class APRequestServiceImplTest {
}), objectMapper, httpSignatureSigner, dateTimeFormatter) }), objectMapper, httpSignatureSigner, dateTimeFormatter)
val body = Follow( val body = Follow(
name = "Follow", apObject = "https://example.com",
`object` = "https://example.com",
actor = "https://example.com" actor = "https://example.com"
) )
apRequestServiceImpl.apPost( apRequestServiceImpl.apPost(
@ -337,8 +330,7 @@ class APRequestServiceImplTest {
}), objectMapper, mock(), dateTimeFormatter) }), objectMapper, mock(), dateTimeFormatter)
val body = Follow( val body = Follow(
name = "Follow", apObject = "https://example.com",
`object` = "https://example.com",
actor = "https://example.com" actor = "https://example.com"
) )
val actual = apRequestServiceImpl.apPost("https://example.com", body, null, body::class.java) val actual = apRequestServiceImpl.apPost("https://example.com", body, null, body::class.java)

View File

@ -56,7 +56,6 @@ class APNoteServiceImplTest {
onBlocking { findById(eq(post.userId)) } doReturn user onBlocking { findById(eq(post.userId)) } doReturn user
} }
val expected = Note( val expected = Note(
name = "Post",
id = post.apId, id = post.apId,
attributedTo = user.url, attributedTo = user.url,
content = post.text, content = post.text,
@ -98,7 +97,6 @@ class APNoteServiceImplTest {
onBlocking { findById(eq(post.userId)) } doReturn user onBlocking { findById(eq(post.userId)) } doReturn user
} }
val note = Note( val note = Note(
name = "Post",
id = post.apId, id = post.apId,
attributedTo = user.url, attributedTo = user.url,
content = post.text, content = post.text,
@ -124,13 +122,11 @@ class APNoteServiceImplTest {
url = user.url, url = user.url,
icon = Image( icon = Image(
type = emptyList(), type = emptyList(),
name = user.url + "/icon.png",
mediaType = "image/png", mediaType = "image/png",
url = user.url + "/icon.png" url = user.url + "/icon.png"
), ),
publicKey = Key( publicKey = Key(
type = emptyList(), type = emptyList(),
name = "Public Key",
id = user.keyId, id = user.keyId,
owner = user.url, owner = user.url,
publicKeyPem = user.publicKey publicKeyPem = user.publicKey
@ -177,7 +173,6 @@ class APNoteServiceImplTest {
onBlocking { findById(eq(post.userId)) } doReturn user onBlocking { findById(eq(post.userId)) } doReturn user
} }
val note = Note( val note = Note(
name = "Post",
id = post.apId, id = post.apId,
attributedTo = user.url, attributedTo = user.url,
content = post.text, content = post.text,
@ -246,11 +241,11 @@ class APNoteServiceImplTest {
outbox = user.outbox, outbox = user.outbox,
url = user.url, url = user.url,
icon = Image( icon = Image(
name = user.url + "/icon.png", mediaType = "image/png", url = user.url + "/icon.png" mediaType = "image/png",
url = user.url + "/icon.png"
), ),
publicKey = Key( publicKey = Key(
type = emptyList(), type = emptyList(),
name = "Public Key",
id = user.keyId, id = user.keyId,
owner = user.url, owner = user.url,
publicKeyPem = user.publicKey publicKeyPem = user.publicKey
@ -278,7 +273,6 @@ class APNoteServiceImplTest {
) )
val note = Note( val note = Note(
name = "Post",
id = post.apId, id = post.apId,
attributedTo = user.url, attributedTo = user.url,
content = post.text, content = post.text,
@ -311,7 +305,6 @@ class APNoteServiceImplTest {
onBlocking { findById(eq(user.id)) } doReturn user onBlocking { findById(eq(user.id)) } doReturn user
} }
val note = Note( val note = Note(
name = "Post",
id = post.apId, id = post.apId,
attributedTo = user.url, attributedTo = user.url,
content = post.text, content = post.text,

View File

@ -12,9 +12,8 @@ class ContextSerializerTest {
val accept = Accept( val accept = Accept(
name = "aaa", name = "aaa",
actor = "bbb", actor = "bbb",
`object` = Follow( apObject = Follow(
name = "ccc", apObject = "ddd",
`object` = "ddd",
actor = "aaa" actor = "aaa"
) )
) )