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
import java.io.Serial
class FailedProcessException : RuntimeException {
constructor() : super()
constructor(message: String?) : super(message)
@ -11,4 +13,9 @@ class FailedProcessException : RuntimeException {
enableSuppression,
writableStackTrace
)
companion object {
@Serial
private const val serialVersionUID: Long = -1305337651143409144L
}
}

View File

@ -1,10 +1,16 @@
package dev.usbharu.hideout.activitypub.domain.exception
import dev.usbharu.hideout.core.domain.exception.FailedToGetResourcesException
import java.io.Serial
class FailedToGetActivityPubResourceException : FailedToGetResourcesException {
constructor() : super()
constructor(s: String?) : super(s)
constructor(message: String?, cause: Throwable?) : super(message, 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
import java.io.Serial
class HttpSignatureUnauthorizedException : RuntimeException {
constructor() : super()
constructor(message: String?) : super(message)
@ -11,4 +13,9 @@ class HttpSignatureUnauthorizedException : RuntimeException {
enableSuppression,
writableStackTrace
)
companion object {
@Serial
private const val serialVersionUID: Long = -6449793151674654501L
}
}

View File

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

View File

@ -1,38 +1,36 @@
package dev.usbharu.hideout.activitypub.domain.model
import com.fasterxml.jackson.annotation.JsonProperty
import dev.usbharu.hideout.activitypub.domain.model.objects.Object
open class Follow : Object {
@Suppress("VariableNaming")
var `object`: String? = null
protected constructor() : super()
constructor(
type: List<String> = emptyList(),
name: String?,
`object`: String?,
actor: String?
) : super(
type = add(type, "Follow"),
name = name,
actor = actor
) {
this.`object` = `object`
}
open class Follow(
type: List<String> = emptyList(),
@JsonProperty("object") val apObject: String,
override val actor: String
) : Object(
type = add(type, "Follow")
),
HasActor {
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other !is Follow) return false
if (javaClass != other?.javaClass) 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 {
var result = super.hashCode()
result = 31 * result + (`object`?.hashCode() ?: 0)
result = 31 * result + apObject.hashCode()
result = 31 * result + actor.hashCode()
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
open class Image : Object {
private var mediaType: String? = null
private var url: String? = null
protected constructor() : super()
constructor(type: List<String> = emptyList(), name: String, mediaType: String?, url: String?) : super(
add(type, "Image"),
name
) {
this.mediaType = mediaType
this.url = url
}
open class Image(
type: List<String> = emptyList(),
val mediaType: String,
val url: String
) : Object(
add(type, "Image")
) {
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other !is Image) return false
if (javaClass != other?.javaClass) return false
if (!super.equals(other)) return false
other as Image
if (mediaType != other.mediaType) return false
return url == other.url
if (url != other.url) return false
return true
}
override fun hashCode(): Int {
var result = super.hashCode()
result = 31 * result + (mediaType?.hashCode() ?: 0)
result = 31 * result + (url?.hashCode() ?: 0)
result = 31 * result + mediaType.hashCode()
result = 31 * result + url.hashCode()
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
open class Key : Object {
var owner: String? = null
var publicKeyPem: String? = null
protected constructor() : super()
constructor(
type: List<String>,
name: String,
id: String,
owner: String?,
publicKeyPem: String?
) : super(
type = add(list = type, type = "Key"),
name = name,
id = id
) {
this.owner = owner
this.publicKeyPem = publicKeyPem
}
open class Key(
type: List<String>,
override val id: String,
val owner: String,
val publicKeyPem: String
) : Object(
type = add(list = type, type = "Key")
),
HasId {
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other !is Key) return false
if (javaClass != other?.javaClass) return false
if (!super.equals(other)) return false
other as Key
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 {
var result = super.hashCode()
result = 31 * result + (owner?.hashCode() ?: 0)
result = 31 * result + (publicKeyPem?.hashCode() ?: 0)
result = 31 * result + owner.hashCode()
result = 31 * result + publicKeyPem.hashCode()
result = 31 * result + id.hashCode()
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
import com.fasterxml.jackson.annotation.JsonProperty
import com.fasterxml.jackson.databind.annotation.JsonDeserialize
import dev.usbharu.hideout.activitypub.domain.model.objects.Object
import dev.usbharu.hideout.activitypub.domain.model.objects.ObjectDeserializer
open class Like : Object {
@Suppress("VariableNaming")
var `object`: String? = null
var content: String? = null
@JsonDeserialize(contentUsing = ObjectDeserializer::class)
var tag: List<Object> = emptyList()
protected constructor() : super()
constructor(
type: List<String> = emptyList(),
name: String?,
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
}
open class Like(
type: List<String> = emptyList(),
override val actor: String,
override val id: String,
@JsonProperty("object") val apObject: String,
val content: String,
@JsonDeserialize(contentUsing = ObjectDeserializer::class) val tag: List<Object> = emptyList()
) : Object(
type = add(type, "Like")
),
HasId,
HasActor {
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other !is Like) return false
if (javaClass != other?.javaClass) 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
return tag == other.tag
if (tag != other.tag) return false
return true
}
override fun hashCode(): Int {
var result = super.hashCode()
result = 31 * result + (`object`?.hashCode() ?: 0)
result = 31 * result + (content?.hashCode() ?: 0)
result = 31 * result + actor.hashCode()
result = 31 * result + id.hashCode()
result = 31 * result + apObject.hashCode()
result = 31 * result + content.hashCode()
result = 31 * result + tag.hashCode()
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
open class Note : Object {
var attributedTo: String? = null
var attachment: List<Document> = emptyList()
var content: String? = null
var published: String? = null
var to: List<String> = emptyList()
var cc: List<String> = emptyList()
var sensitive: Boolean = false
var inReplyTo: String? = null
protected constructor() : super()
@Suppress("LongParameterList")
constructor(
type: List<String> = emptyList(),
name: String,
id: String?,
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
}
open class Note
@Suppress("LongParameterList")
constructor(
type: List<String> = emptyList(),
override val id: String,
val attributedTo: String,
val content: String,
val published: String,
val to: List<String> = emptyList(),
val cc: List<String> = emptyList(),
val sensitive: Boolean = false,
val inReplyTo: String? = null,
val attachment: List<Document> = emptyList()
) : Object(
type = add(type, "Note")
),
HasId {
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other !is Note) return false
if (javaClass != other?.javaClass) return false
if (!super.equals(other)) return false
other as Note
if (id != other.id) return false
if (attributedTo != other.attributedTo) return false
if (attachment != other.attachment) return false
if (content != other.content) return false
if (published != other.published) return false
if (to != other.to) return false
if (cc != other.cc) return false
if (sensitive != other.sensitive) return false
if (inReplyTo != other.inReplyTo) return false
if (attachment != other.attachment) return false
return true
}
override fun hashCode(): Int {
var result = super.hashCode()
result = 31 * result + (attributedTo?.hashCode() ?: 0)
result = 31 * result + attachment.hashCode()
result = 31 * result + (content?.hashCode() ?: 0)
result = 31 * result + (published?.hashCode() ?: 0)
result = 31 * result + id.hashCode()
result = 31 * result + attributedTo.hashCode()
result = 31 * result + content.hashCode()
result = 31 * result + published.hashCode()
result = 31 * result + to.hashCode()
result = 31 * result + cc.hashCode()
result = 31 * result + sensitive.hashCode()
result = 31 * result + (inReplyTo?.hashCode() ?: 0)
result = 31 * result + attachment.hashCode()
return result
}
override fun toString(): String {
return "Note(attributedTo=$attributedTo, attachment=$attachment, " +
"content=$content, published=$published, to=$to, cc=$cc, sensitive=$sensitive," +
" inReplyTo=$inReplyTo) ${super.toString()}"
return "Note(" +
"id='$id', " +
"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
open class Person : Object {
var preferredUsername: String? = null
var summary: String? = null
var inbox: String? = null
var outbox: String? = null
var url: String? = null
private var icon: Image? = null
var publicKey: Key? = null
var endpoints: Map<String, String> = emptyMap()
var following: String? = null
var followers: String? = null
protected constructor() : super()
@Suppress("LongParameterList")
constructor(
type: List<String> = emptyList(),
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
}
open class Person
@Suppress("LongParameterList")
constructor(
type: List<String> = emptyList(),
override val name: String,
override val id: String,
var preferredUsername: String?,
var summary: String?,
var inbox: String,
var outbox: String,
var url: String,
private var icon: Image?,
var publicKey: Key?,
var endpoints: Map<String, String> = emptyMap(),
var followers: String?,
var following: String?
) : Object(add(type, "Person")), HasId, HasName {
override fun equals(other: Any?): Boolean {
if (this === other) return true
@ -65,9 +41,9 @@ open class Person : Object {
var result = super.hashCode()
result = 31 * result + (preferredUsername?.hashCode() ?: 0)
result = 31 * result + (summary?.hashCode() ?: 0)
result = 31 * result + (inbox?.hashCode() ?: 0)
result = 31 * result + (outbox?.hashCode() ?: 0)
result = 31 * result + (url?.hashCode() ?: 0)
result = 31 * result + inbox.hashCode()
result = 31 * result + outbox.hashCode()
result = 31 * result + url.hashCode()
result = 31 * result + (icon?.hashCode() ?: 0)
result = 31 * result + (publicKey?.hashCode() ?: 0)
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
open class Tombstone : Object {
constructor(
type: List<String> = emptyList(),
name: String = "Tombstone",
actor: String? = null,
id: String
) : super(add(type, "Tombstone"), name, actor, id)
open class Tombstone(type: List<String> = emptyList(), override val id: String) :
Object(add(type, "Tombstone")),
HasId {
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false
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 dev.usbharu.hideout.activitypub.domain.model.objects.Object
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)
@Suppress("VariableNaming")
var `object`: Object? = null
var published: String? = null
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()
}
@Suppress("VariableNaming") val `object`: Object,
val published: String
) : Object(add(type, "Undo")), HasId, HasActor {
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other !is Undo) return false
if (javaClass != other?.javaClass) return false
if (!super.equals(other)) return false
other as Undo
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 {
var result = super.hashCode()
result = 31 * result + (`object`?.hashCode() ?: 0)
result = 31 * result + (published?.hashCode() ?: 0)
result = 31 * result + actor.hashCode()
result = 31 * result + id.hashCode()
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) {
field = value.filter { it.isNotBlank() }
}
var name: String? = null
var actor: String? = null
var id: String? = null
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.name = name
this.actor = actor
this.id = id
}
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other !is Object) return false
if (javaClass != other?.javaClass) return false
if (!super.equals(other)) return false
if (type != other.type) return false
if (name != other.name) return false
if (actor != other.actor) return false
if (id != other.id) return false
other as Object
return true
return type == other.type
}
override fun hashCode(): Int {
var result = super.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
}
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 {
@JvmStatic

View File

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

View File

@ -1,33 +1,27 @@
package dev.usbharu.hideout.activitypub.domain.model.objects
import com.fasterxml.jackson.annotation.JsonCreator
@Suppress("VariableNaming")
open class ObjectValue : Object {
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`
}
open class ObjectValue @JsonCreator constructor(type: List<String>, var `object`: String) : Object(
type
) {
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other !is ObjectValue) return false
if (javaClass != other?.javaClass) return false
if (!super.equals(other)) return false
other as ObjectValue
return `object` == other.`object`
}
override fun hashCode(): Int {
var result = super.hashCode()
result = 31 * result + (`object`?.hashCode() ?: 0)
result = 31 * result + `object`.hashCode()
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]
)
return Note(
name = "Post",
id = this[Posts.apId],
attributedTo = this[Users.url],
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
class ApAcceptProcessor(
private val transaction: Transaction,
transaction: Transaction,
private val userQueryService: UserQueryService,
private val followerQueryService: FollowerQueryService,
private val userService: UserService
@ -20,17 +20,17 @@ class ApAcceptProcessor(
AbstractActivityPubProcessor<Accept>(transaction) {
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()) {
logger.warn("FAILED Activity type is not Follow.")
logger.warn("FAILED Activity type isn't Follow.")
throw IllegalActivityPubObjectException("Invalid type ${value.type}")
}
val follow = value as Follow
val userUrl = follow.`object` ?: throw IllegalActivityPubObjectException("object is null")
val followerUrl = follow.actor ?: throw IllegalActivityPubObjectException("actor is null")
val userUrl = follow.apObject
val followerUrl = follow.actor
val user = userQueryService.findByUrl(userUrl)
val follower = userQueryService.findByUrl(followerUrl)

View File

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

View File

@ -11,9 +11,9 @@ import org.springframework.stereotype.Service
@Service
class CreateActivityProcessor(transaction: Transaction, private val apNoteService: APNoteService) :
AbstractActivityPubProcessor<Create>(transaction, false) {
AbstractActivityPubProcessor<Create>(transaction) {
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

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.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.ActivityPubProcessContext
import dev.usbharu.hideout.activitypub.service.common.ActivityType
@ -17,7 +18,11 @@ class APDeleteProcessor(
) :
AbstractActivityPubProcessor<Delete>(transaction) {
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 {
postQueryService.findByApId(deleteId)

View File

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

View File

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

View File

@ -18,11 +18,11 @@ class APReceiveFollowServiceImpl(
@Qualifier("activitypub") private val objectMapper: ObjectMapper
) : APReceiveFollowService {
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) {
props[ReceiveFollowJob.actor] = follow.actor
props[ReceiveFollowJob.follow] = objectMapper.writeValueAsString(follow)
props[ReceiveFollowJob.targetActor] = follow.`object`
props[ReceiveFollowJob.targetActor] = follow.apObject
}
return
}

View File

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

View File

@ -1,7 +1,6 @@
package dev.usbharu.hideout.activitypub.service.activity.like
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.service.common.AbstractActivityPubProcessor
import dev.usbharu.hideout.activitypub.service.common.ActivityPubProcessContext
@ -21,10 +20,10 @@ class APLikeProcessor(
) :
AbstractActivityPubProcessor<Like>(transaction) {
override suspend fun internalProcess(activity: ActivityPubProcessContext<Like>) {
val actor = activity.activity.actor ?: throw IllegalActivityPubObjectException("actor is null")
val content = activity.activity.content ?: throw IllegalActivityPubObjectException("content is null")
val actor = activity.activity.actor
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)

View File

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

View File

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

View File

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

View File

@ -61,7 +61,7 @@ class APRequestServiceImpl(
url: String
): HttpResponse {
val headers = headers {
append("Accept", ContentType.Application.Activity)
append("Accept", Activity)
append("Date", date)
append("Host", u.host)
}
@ -87,13 +87,13 @@ class APRequestServiceImpl(
remove("Host")
}
}
contentType(ContentType.Application.Activity)
contentType(Activity)
}
return httpResponse
}
private suspend fun apGetNotSign(url: String, date: String?) = httpClient.get(url) {
header("Accept", ContentType.Application.Activity)
header("Accept", Activity)
header("Date", date)
}
@ -153,12 +153,12 @@ class APRequestServiceImpl(
digest: String,
requestBody: String?
) = httpClient.post(url) {
accept(ContentType.Application.Activity)
accept(Activity)
header("Date", date)
header("Digest", "sha-256=$digest")
if (requestBody != null) {
setBody(requestBody)
contentType(ContentType.Application.Activity)
contentType(Activity)
}
}
@ -170,7 +170,7 @@ class APRequestServiceImpl(
requestBody: String?
): HttpResponse {
val headers = headers {
append("Accept", ContentType.Application.Activity)
append("Accept", Activity)
append("Date", date)
append("Host", u.host)
append("Digest", "sha-256=$digest")
@ -196,7 +196,7 @@ class APRequestServiceImpl(
remove("Host")
}
setBody(requestBody)
contentType(ContentType.Application.Activity)
contentType(Activity)
}
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.model.objects.Object
import dev.usbharu.hideout.application.external.Transaction
import org.slf4j.Logger
import org.slf4j.LoggerFactory
abstract class AbstractActivityPubProcessor<T : Object>(
private val transaction: Transaction,
private val allowUnauthorized: Boolean = false
) : 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>) {
if (activity.isAuthorized.not() && allowUnauthorized.not()) {

View File

@ -1,7 +1,6 @@
package dev.usbharu.hideout.activitypub.service.objects.note
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.query.NoteQueryService
import dev.usbharu.hideout.activitypub.service.common.APResourceResolveService
@ -91,7 +90,7 @@ class APNoteServiceImpl(
requireNotNull(note.id) { "id is null" }
return try {
noteQueryService.findByApid(note.id!!).first
noteQueryService.findByApid(note.id).first
} catch (_: FailedToGetResourcesException) {
saveNote(note, targetActor, url)
}
@ -99,7 +98,7 @@ class APNoteServiceImpl(
private suspend fun saveNote(note: Note, targetActor: String?, url: String): Note {
val person = apUserService.fetchPersonWithEntity(
note.attributedTo ?: throw IllegalActivityPubObjectException("note.attributedTo is null"),
note.attributedTo,
targetActor
)
@ -128,9 +127,9 @@ class APNoteServiceImpl(
.map {
mediaService.uploadRemoteMedia(
RemoteMedia(
(it.name ?: it.url)!!,
it.url!!,
it.mediaType ?: "application/octet-stream",
it.name,
it.url,
it.mediaType,
description = it.name
)
)
@ -142,13 +141,13 @@ class APNoteServiceImpl(
postBuilder.of(
id = postRepository.generateId(),
userId = person.second.id,
text = note.content.orEmpty(),
text = note.content,
createdAt = Instant.parse(note.published).toEpochMilli(),
visibility = visibility,
url = note.id ?: url,
url = note.id,
replyId = reply?.id,
sensitive = note.sensitive,
apId = note.id ?: url,
apId = note.id,
mediaIds = mediaList
)
)
@ -156,7 +155,7 @@ class APNoteServiceImpl(
}
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 {
const val public: String = "https://www.w3.org/ns/activitystreams#Public"

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -3,23 +3,17 @@
package dev.usbharu.hideout.core.domain.model.instance
@Suppress("ClassNaming")
class Nodeinfo2_0 {
class Nodeinfo2_0() {
var metadata: Metadata? = null
var software: Software? = null
constructor()
}
class Metadata {
class Metadata() {
var nodeName: String? = null
var nodeDescription: String? = null
constructor()
}
class Software {
class Software() {
var name: 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) {
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[accessTokenType] = accessToken?.token?.tokenType?.value
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[refreshTokenIssuedAt] = refreshToken?.token?.issuedAt
it[refreshTokenExpiresAt] = refreshToken?.token?.expiresAt

View File

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

View File

@ -5,4 +5,29 @@ data class MediaSave(
val prefix: String,
val fileInputStream: 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
@Suppress("TooGenericExceptionCaught")
open class MediaServiceImpl(
class MediaServiceImpl(
private val mediaDataStore: MediaDataStore,
private val fileTypeDeterminationService: FileTypeDeterminationService,
private val mediaBlurhashService: MediaBlurhashService,

View File

@ -3,4 +3,22 @@ package dev.usbharu.hideout.core.service.media
data class ProcessedFile(
val byteArray: ByteArray,
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.query.ReactionQueryService
import org.jetbrains.exposed.exceptions.ExposedSQLException
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import org.springframework.stereotype.Service
@ -50,6 +51,6 @@ class ReactionServiceImpl(
}
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 {
cacheKey.filter { Instant.ofEpochMilli(it.value).plusSeconds(300) <= Instant.now() }
val cached = cacheKey.get(key)
val cached = cacheKey[key]
if (cached == null) {
needRunBlock = true
cacheKey[key] = Instant.now().toEpochMilli()

View File

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

View File

@ -1,5 +1,6 @@
package dev.usbharu.hideout.generate
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import org.springframework.core.MethodParameter
import org.springframework.web.bind.support.WebDataBinderFactory
@ -49,6 +50,6 @@ class JsonOrFormModelMethodProcessor(
}
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 java.time.Instant
@Suppress("IncompleteDestructuring")
@Repository
class StatusQueryServiceImpl : StatusQueryService {
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,
url = uploadLocalMedia.url,
previewUrl = uploadLocalMedia.thumbnailUrl,
remoteUrl = null,
description = mediaRequest.description,
blurhash = uploadLocalMedia.blurHash,
textUrl = uploadLocalMedia.url

View File

@ -35,7 +35,7 @@ object AcctUtil {
}
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.*
object HttpUtil {
val ContentType.Application.Activity: ContentType
val Activity: ContentType
get() = ContentType("application", "activity+json")
val ContentType.Application.JsonLd: ContentType
val JsonLd: ContentType
get() {
return ContentType(
contentType = "application",

View File

@ -46,7 +46,6 @@ class DeleteSerializeTest {
val readValue = objectMapper.readValue<Delete>(json)
val expected = Delete(
name = null,
actor = "https://misskey.usbharu.dev/users/97ws8y3rj6",
id = "https://misskey.usbharu.dev/4b5b6ed5-9269-45f3-8403-cba1e74b4b69",
`object` = Tombstone(
@ -61,7 +60,6 @@ class DeleteSerializeTest {
@Test
fun シリアライズできる() {
val delete = Delete(
name = null,
actor = "https://misskey.usbharu.dev/users/97ws8y3rj6",
id = "https://misskey.usbharu.dev/4b5b6ed5-9269-45f3-8403-cba1e74b4b69",
`object` = Tombstone(
@ -75,7 +73,7 @@ class DeleteSerializeTest {
val actual = objectMapper.writeValueAsString(delete)
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)
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -39,7 +39,7 @@ class APRequestServiceImplTest {
assertDoesNotThrow {
dateTimeFormatter.parse(it.headers["Date"])
}
respond("{}")
respond("""{"type":"Follow","object": "https://example.com","actor": "https://example.com"}""")
}),
objectMapper,
mock(),
@ -47,8 +47,7 @@ class APRequestServiceImplTest {
)
val responseClass = Follow(
name = "Follow",
`object` = "https://example.com",
apObject = "https://example.com",
actor = "https://example.com"
)
apRequestServiceImpl.apGet("https://example.com", responseClass = responseClass::class.java)
@ -65,7 +64,7 @@ class APRequestServiceImplTest {
assertDoesNotThrow {
dateTimeFormatter.parse(it.headers["Date"])
}
respond("{}")
respond("""{"type":"Follow","object": "https://example.com","actor": "https://example.com"}""")
}),
objectMapper,
mock(),
@ -73,8 +72,7 @@ class APRequestServiceImplTest {
)
val responseClass = Follow(
name = "Follow",
`object` = "https://example.com",
apObject = "https://example.com",
actor = "https://example.com"
)
apRequestServiceImpl.apGet(
@ -106,7 +104,7 @@ class APRequestServiceImplTest {
assertDoesNotThrow {
dateTimeFormatter.parse(it.headers["Date"])
}
respond("{}")
respond("""{"type":"Follow","object": "https://example.com","actor": "https://example.com"}""")
}),
objectMapper,
httpSignatureSigner,
@ -114,8 +112,7 @@ class APRequestServiceImplTest {
)
val responseClass = Follow(
name = "Follow",
`object` = "https://example.com",
apObject = "https://example.com",
actor = "https://example.com"
)
apRequestServiceImpl.apGet(
@ -166,8 +163,7 @@ class APRequestServiceImplTest {
}), objectMapper, mock(), dateTimeFormatter)
val body = Follow(
name = "Follow",
`object` = "https://example.com",
apObject = "https://example.com",
actor = "https://example.com"
)
apRequestServiceImpl.apPost("https://example.com", body, null)
@ -213,8 +209,7 @@ class APRequestServiceImplTest {
}), objectMapper, mock(), dateTimeFormatter)
val body = Follow(
name = "Follow",
`object` = "https://example.com",
apObject = "https://example.com",
actor = "https://example.com"
)
apRequestServiceImpl.apPost("https://example.com", body, null)
@ -244,8 +239,7 @@ class APRequestServiceImplTest {
}), objectMapper, mock(), dateTimeFormatter)
val body = Follow(
name = "Follow",
`object` = "https://example.com",
apObject = "https://example.com",
actor = "https://example.com"
)
apRequestServiceImpl.apPost("https://example.com", body, UserBuilder.remoteUserOf())
@ -286,8 +280,7 @@ class APRequestServiceImplTest {
}), objectMapper, httpSignatureSigner, dateTimeFormatter)
val body = Follow(
name = "Follow",
`object` = "https://example.com",
apObject = "https://example.com",
actor = "https://example.com"
)
apRequestServiceImpl.apPost(
@ -337,8 +330,7 @@ class APRequestServiceImplTest {
}), objectMapper, mock(), dateTimeFormatter)
val body = Follow(
name = "Follow",
`object` = "https://example.com",
apObject = "https://example.com",
actor = "https://example.com"
)
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
}
val expected = Note(
name = "Post",
id = post.apId,
attributedTo = user.url,
content = post.text,
@ -98,7 +97,6 @@ class APNoteServiceImplTest {
onBlocking { findById(eq(post.userId)) } doReturn user
}
val note = Note(
name = "Post",
id = post.apId,
attributedTo = user.url,
content = post.text,
@ -124,13 +122,11 @@ class APNoteServiceImplTest {
url = user.url,
icon = Image(
type = emptyList(),
name = user.url + "/icon.png",
mediaType = "image/png",
url = user.url + "/icon.png"
),
publicKey = Key(
type = emptyList(),
name = "Public Key",
id = user.keyId,
owner = user.url,
publicKeyPem = user.publicKey
@ -177,7 +173,6 @@ class APNoteServiceImplTest {
onBlocking { findById(eq(post.userId)) } doReturn user
}
val note = Note(
name = "Post",
id = post.apId,
attributedTo = user.url,
content = post.text,
@ -246,11 +241,11 @@ class APNoteServiceImplTest {
outbox = user.outbox,
url = user.url,
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(
type = emptyList(),
name = "Public Key",
id = user.keyId,
owner = user.url,
publicKeyPem = user.publicKey
@ -278,7 +273,6 @@ class APNoteServiceImplTest {
)
val note = Note(
name = "Post",
id = post.apId,
attributedTo = user.url,
content = post.text,
@ -311,7 +305,6 @@ class APNoteServiceImplTest {
onBlocking { findById(eq(user.id)) } doReturn user
}
val note = Note(
name = "Post",
id = post.apId,
attributedTo = user.url,
content = post.text,

View File

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