mirror of https://github.com/usbharu/Hideout.git
Merge branch 'develop' into feature/for-update-transaction
# Conflicts: # src/main/kotlin/dev/usbharu/hideout/core/domain/model/actor/Actor.kt
This commit is contained in:
commit
7684a03015
|
@ -236,14 +236,14 @@ jobs:
|
||||||
- name: Run Kover
|
- name: Run Kover
|
||||||
uses: gradle/gradle-build-action@v2.8.1
|
uses: gradle/gradle-build-action@v2.8.1
|
||||||
with:
|
with:
|
||||||
arguments: koverXmlReport -x integrationTest -x e2eTest
|
arguments: koverXmlReport -x integrationTest -x e2eTest --rerun-tasks
|
||||||
|
|
||||||
- name: Add coverage report to PR
|
- name: Add coverage report to PR
|
||||||
if: always()
|
if: always()
|
||||||
id: kover
|
id: kover
|
||||||
uses: mi-kas/kover-report@v1
|
uses: madrapps/jacoco-report@v1.6.1
|
||||||
with:
|
with:
|
||||||
path: |
|
paths: |
|
||||||
${{ github.workspace }}/build/reports/kover/report.xml
|
${{ github.workspace }}/build/reports/kover/report.xml
|
||||||
token: ${{ secrets.GITHUB_TOKEN }}
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
title: Code Coverage
|
title: Code Coverage
|
||||||
|
|
|
@ -83,7 +83,9 @@ tasks.withType<Test> {
|
||||||
useJUnitPlatform()
|
useJUnitPlatform()
|
||||||
doFirst {
|
doFirst {
|
||||||
jvmArgs = arrayOf(
|
jvmArgs = arrayOf(
|
||||||
"--add-opens", "java.base/java.lang=ALL-UNNAMED"
|
"--add-opens", "java.base/java.lang=ALL-UNNAMED",
|
||||||
|
"--add-opens", "java.base/java.util=ALL-UNNAMED",
|
||||||
|
"--add-opens", "java.naming/javax.naming=ALL-UNNAMED",
|
||||||
).toMutableList()
|
).toMutableList()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,6 +50,13 @@ open class Delete : Object, HasId, HasActor {
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun toString(): String =
|
override fun toString(): String {
|
||||||
"Delete(`object`=$apObject, published=$published, actor='$actor', id='$id') ${super.toString()}"
|
return "Delete(" +
|
||||||
|
"apObject=$apObject, " +
|
||||||
|
"published='$published', " +
|
||||||
|
"actor='$actor', " +
|
||||||
|
"id='$id'" +
|
||||||
|
")" +
|
||||||
|
" ${super.toString()}"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,21 +14,37 @@ open class Emoji(
|
||||||
HasName,
|
HasName,
|
||||||
HasId {
|
HasId {
|
||||||
|
|
||||||
|
override fun toString(): String {
|
||||||
|
return "Emoji(" +
|
||||||
|
"name='$name', " +
|
||||||
|
"id='$id', " +
|
||||||
|
"updated='$updated', " +
|
||||||
|
"icon=$icon" +
|
||||||
|
")" +
|
||||||
|
" ${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 Emoji) return false
|
if (javaClass != other?.javaClass) return false
|
||||||
if (!super.equals(other)) return false
|
if (!super.equals(other)) return false
|
||||||
|
|
||||||
|
other as Emoji
|
||||||
|
|
||||||
|
if (name != other.name) return false
|
||||||
|
if (id != other.id) return false
|
||||||
if (updated != other.updated) return false
|
if (updated != other.updated) return false
|
||||||
return icon == other.icon
|
if (icon != other.icon) return false
|
||||||
|
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun hashCode(): Int {
|
override fun hashCode(): Int {
|
||||||
var result = super.hashCode()
|
var result = super.hashCode()
|
||||||
|
result = 31 * result + name.hashCode()
|
||||||
|
result = 31 * result + id.hashCode()
|
||||||
result = 31 * result + updated.hashCode()
|
result = 31 * result + updated.hashCode()
|
||||||
result = 31 * result + icon.hashCode()
|
result = 31 * result + icon.hashCode()
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun toString(): String = "Emoji(updated=$updated, icon=$icon) ${super.toString()}"
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,5 +32,11 @@ open class Follow(
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun toString(): String = "Follow(`object`=$apObject, actor='$actor') ${super.toString()}"
|
override fun toString(): String {
|
||||||
|
return "Follow(" +
|
||||||
|
"apObject='$apObject', " +
|
||||||
|
"actor='$actor'" +
|
||||||
|
")" +
|
||||||
|
" ${super.toString()}"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,6 +38,13 @@ open class Undo(
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun toString(): String =
|
override fun toString(): String {
|
||||||
"Undo(`object`=$apObject, published=$published, actor='$actor', id='$id') ${super.toString()}"
|
return "Undo(" +
|
||||||
|
"actor='$actor', " +
|
||||||
|
"id='$id', " +
|
||||||
|
"apObject=$apObject, " +
|
||||||
|
"published='$published'" +
|
||||||
|
")" +
|
||||||
|
" ${super.toString()}"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,5 +73,18 @@ class APResourceResolveServiceImpl(
|
||||||
override suspend fun statusMessage(): String {
|
override suspend fun statusMessage(): String {
|
||||||
TODO("Not yet implemented")
|
TODO("Not yet implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun equals(other: Any?): Boolean {
|
||||||
|
if (this === other) return true
|
||||||
|
if (javaClass != other?.javaClass) return false
|
||||||
|
|
||||||
|
other as APResolveResponse<*>
|
||||||
|
|
||||||
|
return objects == other.objects
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hashCode(): Int {
|
||||||
|
return objects.hashCode()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@ import dev.usbharu.httpsignature.verify.HttpSignatureVerifier
|
||||||
import dev.usbharu.httpsignature.verify.Signature
|
import dev.usbharu.httpsignature.verify.Signature
|
||||||
import dev.usbharu.httpsignature.verify.SignatureHeaderParser
|
import dev.usbharu.httpsignature.verify.SignatureHeaderParser
|
||||||
import org.slf4j.LoggerFactory
|
import org.slf4j.LoggerFactory
|
||||||
|
import org.springframework.beans.factory.annotation.Value
|
||||||
import org.springframework.stereotype.Service
|
import org.springframework.stereotype.Service
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
|
@ -31,6 +32,9 @@ class InboxJobProcessor(
|
||||||
private val transaction: Transaction
|
private val transaction: Transaction
|
||||||
) : JobProcessor<InboxJobParam, InboxJob> {
|
) : JobProcessor<InboxJobParam, InboxJob> {
|
||||||
|
|
||||||
|
@Value("\${hideout.debug.trace-inbox:false}")
|
||||||
|
private var traceJson: Boolean = false
|
||||||
|
|
||||||
private suspend fun verifyHttpSignature(
|
private suspend fun verifyHttpSignature(
|
||||||
httpRequest: HttpRequest,
|
httpRequest: HttpRequest,
|
||||||
signature: Signature,
|
signature: Signature,
|
||||||
|
@ -79,7 +83,10 @@ class InboxJobProcessor(
|
||||||
val jsonNode = objectMapper.readTree(param.json)
|
val jsonNode = objectMapper.readTree(param.json)
|
||||||
|
|
||||||
logger.info("START Process inbox. type: {}", param.type)
|
logger.info("START Process inbox. type: {}", param.type)
|
||||||
logger.trace("type: {}\njson: \n{}", param.type, jsonNode.toPrettyString())
|
if (traceJson) {
|
||||||
|
logger.trace("type: {}\njson: \n{}", param.type, jsonNode.toPrettyString())
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
val map = objectMapper.readValue<Map<String, List<String>>>(param.headers)
|
val map = objectMapper.readValue<Map<String, List<String>>>(param.headers)
|
||||||
|
|
||||||
|
|
|
@ -43,4 +43,25 @@ open class SnowflakeIdGenerateService(private val baseTime: Long) : IdGenerateSe
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getTime(): Long = Instant.now().toEpochMilli()
|
private fun getTime(): Long = Instant.now().toEpochMilli()
|
||||||
|
override fun equals(other: Any?): Boolean {
|
||||||
|
if (this === other) return true
|
||||||
|
if (javaClass != other?.javaClass) return false
|
||||||
|
|
||||||
|
other as SnowflakeIdGenerateService
|
||||||
|
|
||||||
|
if (baseTime != other.baseTime) return false
|
||||||
|
if (lastTimeStamp != other.lastTimeStamp) return false
|
||||||
|
if (sequenceId != other.sequenceId) return false
|
||||||
|
if (mutex != other.mutex) return false
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hashCode(): Int {
|
||||||
|
var result = baseTime.hashCode()
|
||||||
|
result = 31 * result + lastTimeStamp.hashCode()
|
||||||
|
result = 31 * result + sequenceId
|
||||||
|
result = 31 * result + mutex.hashCode()
|
||||||
|
return result
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -224,7 +224,11 @@ data class Actor private constructor(
|
||||||
"followers=$followers, " +
|
"followers=$followers, " +
|
||||||
"following=$following, " +
|
"following=$following, " +
|
||||||
"instance=$instance, " +
|
"instance=$instance, " +
|
||||||
"locked=$locked" +
|
"locked=$locked, " +
|
||||||
|
"followersCount=$followersCount, " +
|
||||||
|
"followingCount=$followingCount, " +
|
||||||
|
"postsCount=$postsCount, " +
|
||||||
|
"lastPostDate=$lastPostDate" +
|
||||||
")"
|
")"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,9 +3,38 @@ package dev.usbharu.hideout.core.domain.model.instance
|
||||||
class Nodeinfo private constructor() {
|
class Nodeinfo private constructor() {
|
||||||
|
|
||||||
var links: List<Links> = emptyList()
|
var links: List<Links> = emptyList()
|
||||||
|
override fun equals(other: Any?): Boolean {
|
||||||
|
if (this === other) return true
|
||||||
|
if (javaClass != other?.javaClass) return false
|
||||||
|
|
||||||
|
other as Nodeinfo
|
||||||
|
|
||||||
|
return links == other.links
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hashCode(): Int {
|
||||||
|
return links.hashCode()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Links private constructor() {
|
class Links private constructor() {
|
||||||
var rel: String? = null
|
var rel: String? = null
|
||||||
var href: String? = null
|
var href: String? = null
|
||||||
|
override fun equals(other: Any?): Boolean {
|
||||||
|
if (this === other) return true
|
||||||
|
if (javaClass != other?.javaClass) return false
|
||||||
|
|
||||||
|
other as Links
|
||||||
|
|
||||||
|
if (rel != other.rel) return false
|
||||||
|
if (href != other.href) return false
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hashCode(): Int {
|
||||||
|
var result = rel?.hashCode() ?: 0
|
||||||
|
result = 31 * result + (href?.hashCode() ?: 0)
|
||||||
|
return result
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,14 +6,66 @@ package dev.usbharu.hideout.core.domain.model.instance
|
||||||
class Nodeinfo2_0 {
|
class Nodeinfo2_0 {
|
||||||
var metadata: Metadata? = null
|
var metadata: Metadata? = null
|
||||||
var software: Software? = null
|
var software: Software? = null
|
||||||
|
override fun equals(other: Any?): Boolean {
|
||||||
|
if (this === other) return true
|
||||||
|
if (javaClass != other?.javaClass) return false
|
||||||
|
|
||||||
|
other as Nodeinfo2_0
|
||||||
|
|
||||||
|
if (metadata != other.metadata) return false
|
||||||
|
if (software != other.software) return false
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hashCode(): Int {
|
||||||
|
var result = metadata?.hashCode() ?: 0
|
||||||
|
result = 31 * result + (software?.hashCode() ?: 0)
|
||||||
|
return result
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Metadata {
|
class Metadata {
|
||||||
var nodeName: String? = null
|
var nodeName: String? = null
|
||||||
var nodeDescription: String? = null
|
var nodeDescription: String? = null
|
||||||
|
override fun equals(other: Any?): Boolean {
|
||||||
|
if (this === other) return true
|
||||||
|
if (javaClass != other?.javaClass) return false
|
||||||
|
|
||||||
|
other as Metadata
|
||||||
|
|
||||||
|
if (nodeName != other.nodeName) return false
|
||||||
|
if (nodeDescription != other.nodeDescription) return false
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hashCode(): Int {
|
||||||
|
var result = nodeName?.hashCode() ?: 0
|
||||||
|
result = 31 * result + (nodeDescription?.hashCode() ?: 0)
|
||||||
|
return result
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Software {
|
class Software {
|
||||||
var name: String? = null
|
var name: String? = null
|
||||||
var version: String? = null
|
var version: String? = null
|
||||||
|
|
||||||
|
override fun equals(other: Any?): Boolean {
|
||||||
|
if (this === other) return true
|
||||||
|
if (javaClass != other?.javaClass) return false
|
||||||
|
|
||||||
|
other as Software
|
||||||
|
|
||||||
|
if (name != other.name) return false
|
||||||
|
if (version != other.version) return false
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hashCode(): Int {
|
||||||
|
var result = name?.hashCode() ?: 0
|
||||||
|
result = 31 * result + (version?.hashCode() ?: 0)
|
||||||
|
return result
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,6 +39,14 @@ class HttpSignatureUser(
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun toString(): String {
|
||||||
|
return "HttpSignatureUser(" +
|
||||||
|
"domain='$domain', " +
|
||||||
|
"id=$id" +
|
||||||
|
")" +
|
||||||
|
" ${super.toString()}"
|
||||||
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@Serial
|
@Serial
|
||||||
private const val serialVersionUID: Long = -3330552099960982997L
|
private const val serialVersionUID: Long = -3330552099960982997L
|
||||||
|
|
|
@ -19,4 +19,22 @@ class HttpSignatureVerifierComposite(
|
||||||
|
|
||||||
throw IllegalArgumentException("Unsupported algorithm. ${signature.algorithm}")
|
throw IllegalArgumentException("Unsupported algorithm. ${signature.algorithm}")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun equals(other: Any?): Boolean {
|
||||||
|
if (this === other) return true
|
||||||
|
if (javaClass != other?.javaClass) return false
|
||||||
|
|
||||||
|
other as HttpSignatureVerifierComposite
|
||||||
|
|
||||||
|
if (map != other.map) return false
|
||||||
|
if (httpSignatureHeaderParser != other.httpSignatureHeaderParser) return false
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hashCode(): Int {
|
||||||
|
var result = map.hashCode()
|
||||||
|
result = 31 * result + httpSignatureHeaderParser.hashCode()
|
||||||
|
return result
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,6 +30,29 @@ class UserDetailsImpl(
|
||||||
@Serial
|
@Serial
|
||||||
private const val serialVersionUID: Long = -899168205656607781L
|
private const val serialVersionUID: Long = -899168205656607781L
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun toString(): String {
|
||||||
|
return "UserDetailsImpl(" +
|
||||||
|
"id=$id" +
|
||||||
|
")" +
|
||||||
|
" ${super.toString()}"
|
||||||
|
}
|
||||||
|
|
||||||
|
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 UserDetailsImpl
|
||||||
|
|
||||||
|
return id == other.id
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hashCode(): Int {
|
||||||
|
var result = super.hashCode()
|
||||||
|
result = 31 * result + id.hashCode()
|
||||||
|
return result
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY)
|
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY)
|
||||||
|
|
|
@ -1,16 +1,73 @@
|
||||||
package dev.usbharu.hideout.core.service.media
|
package dev.usbharu.hideout.core.service.media
|
||||||
|
|
||||||
sealed class SavedMedia(val success: Boolean)
|
sealed class SavedMedia(val success: Boolean) {
|
||||||
|
override fun equals(other: Any?): Boolean {
|
||||||
|
if (this === other) return true
|
||||||
|
if (javaClass != other?.javaClass) return false
|
||||||
|
|
||||||
|
other as SavedMedia
|
||||||
|
|
||||||
|
return success == other.success
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hashCode(): Int {
|
||||||
|
return success.hashCode()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class SuccessSavedMedia(
|
class SuccessSavedMedia(
|
||||||
val name: String,
|
val name: String,
|
||||||
val url: String,
|
val url: String,
|
||||||
val thumbnailUrl: String,
|
val thumbnailUrl: String,
|
||||||
) :
|
) :
|
||||||
SavedMedia(true)
|
SavedMedia(true) {
|
||||||
|
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 SuccessSavedMedia
|
||||||
|
|
||||||
|
if (name != other.name) return false
|
||||||
|
if (url != other.url) return false
|
||||||
|
if (thumbnailUrl != other.thumbnailUrl) return false
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hashCode(): Int {
|
||||||
|
var result = super.hashCode()
|
||||||
|
result = 31 * result + name.hashCode()
|
||||||
|
result = 31 * result + url.hashCode()
|
||||||
|
result = 31 * result + thumbnailUrl.hashCode()
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class FaildSavedMedia(
|
class FaildSavedMedia(
|
||||||
val reason: String,
|
val reason: String,
|
||||||
val description: String,
|
val description: String,
|
||||||
val trace: Throwable? = null
|
val trace: Throwable? = null
|
||||||
) : SavedMedia(false)
|
) : SavedMedia(false) {
|
||||||
|
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 FaildSavedMedia
|
||||||
|
|
||||||
|
if (reason != other.reason) return false
|
||||||
|
if (description != other.description) return false
|
||||||
|
if (trace != other.trace) return false
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hashCode(): Int {
|
||||||
|
var result = super.hashCode()
|
||||||
|
result = 31 * result + reason.hashCode()
|
||||||
|
result = 31 * result + description.hashCode()
|
||||||
|
result = 31 * result + (trace?.hashCode() ?: 0)
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -28,4 +28,23 @@ class KtorResolveResponse(val ktorHttpResponse: HttpResponse) : ResolveResponse
|
||||||
override suspend fun header(): Map<String, List<String>> = ktorHttpResponse.headers.toMap()
|
override suspend fun header(): Map<String, List<String>> = ktorHttpResponse.headers.toMap()
|
||||||
override suspend fun status(): Int = ktorHttpResponse.status.value
|
override suspend fun status(): Int = ktorHttpResponse.status.value
|
||||||
override suspend fun statusMessage(): String = ktorHttpResponse.status.description
|
override suspend fun statusMessage(): String = ktorHttpResponse.status.description
|
||||||
|
override fun equals(other: Any?): Boolean {
|
||||||
|
if (this === other) return true
|
||||||
|
if (javaClass != other?.javaClass) return false
|
||||||
|
|
||||||
|
other as KtorResolveResponse
|
||||||
|
|
||||||
|
if (ktorHttpResponse != other.ktorHttpResponse) return false
|
||||||
|
if (_bodyAsText != other._bodyAsText) return false
|
||||||
|
if (!_bodyAsBytes.contentEquals(other._bodyAsBytes)) return false
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hashCode(): Int {
|
||||||
|
var result = ktorHttpResponse.hashCode()
|
||||||
|
result = 31 * result + _bodyAsText.hashCode()
|
||||||
|
result = 31 * result + _bodyAsBytes.contentHashCode()
|
||||||
|
return result
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,9 +65,17 @@ class StatusesRequest {
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun toString(): String {
|
override fun toString(): String {
|
||||||
return "StatusesRequest(status=$status, mediaIds=$media_ids, poll=$poll, inReplyToId=$in_reply_to_id, " +
|
return "StatusesRequest(" +
|
||||||
"sensitive=$sensitive, spoilerText=$spoiler_text, visibility=$visibility, language=$language," +
|
"status=$status, " +
|
||||||
" scheduledAt=$scheduled_at)"
|
"media_ids=$media_ids, " +
|
||||||
|
"poll=$poll, " +
|
||||||
|
"in_reply_to_id=$in_reply_to_id, " +
|
||||||
|
"sensitive=$sensitive, " +
|
||||||
|
"spoiler_text=$spoiler_text, " +
|
||||||
|
"visibility=$visibility, " +
|
||||||
|
"language=$language, " +
|
||||||
|
"scheduled_at=$scheduled_at" +
|
||||||
|
")"
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("EnumNaming", "EnumEntryNameCase")
|
@Suppress("EnumNaming", "EnumEntryNameCase")
|
||||||
|
|
|
@ -5,6 +5,12 @@ import java.io.Serial
|
||||||
class LruCache<K, V>(private val maxSize: Int) : LinkedHashMap<K, V>(15, 0.75f, true) {
|
class LruCache<K, V>(private val maxSize: Int) : LinkedHashMap<K, V>(15, 0.75f, true) {
|
||||||
|
|
||||||
override fun removeEldestEntry(eldest: MutableMap.MutableEntry<K, V>?): Boolean = size > maxSize
|
override fun removeEldestEntry(eldest: MutableMap.MutableEntry<K, V>?): Boolean = size > maxSize
|
||||||
|
override fun toString(): String {
|
||||||
|
return "LruCache(" +
|
||||||
|
"maxSize=$maxSize" +
|
||||||
|
")" +
|
||||||
|
" ${super.toString()}"
|
||||||
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@Serial
|
@Serial
|
||||||
|
|
|
@ -9,4 +9,17 @@ class TempFile<T : Path?>(val path: T) : AutoCloseable {
|
||||||
override fun close() {
|
override fun close() {
|
||||||
path?.let { Files.deleteIfExists(it) }
|
path?.let { Files.deleteIfExists(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun equals(other: Any?): Boolean {
|
||||||
|
if (this === other) return true
|
||||||
|
if (javaClass != other?.javaClass) return false
|
||||||
|
|
||||||
|
other as TempFile<*>
|
||||||
|
|
||||||
|
return path == other.path
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hashCode(): Int {
|
||||||
|
return path?.hashCode() ?: 0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,41 +1,111 @@
|
||||||
package dev.usbharu.hideout
|
package dev.usbharu.hideout
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.module.kotlin.isKotlinClass
|
||||||
import com.jparams.verifier.tostring.ToStringVerifier
|
import com.jparams.verifier.tostring.ToStringVerifier
|
||||||
|
import com.jparams.verifier.tostring.preset.Presets
|
||||||
import nl.jqno.equalsverifier.EqualsVerifier
|
import nl.jqno.equalsverifier.EqualsVerifier
|
||||||
import nl.jqno.equalsverifier.Warning
|
import nl.jqno.equalsverifier.Warning
|
||||||
import nl.jqno.equalsverifier.internal.reflection.PackageScanner
|
import nl.jqno.equalsverifier.internal.reflection.PackageScanner
|
||||||
import org.junit.jupiter.api.Test
|
import org.junit.jupiter.api.DynamicTest
|
||||||
|
import org.junit.jupiter.api.DynamicTest.dynamicTest
|
||||||
|
import org.junit.jupiter.api.TestFactory
|
||||||
|
import org.springframework.context.annotation.Configuration
|
||||||
|
import org.springframework.stereotype.Component
|
||||||
|
import org.springframework.stereotype.Controller
|
||||||
|
import org.springframework.stereotype.Repository
|
||||||
|
import org.springframework.stereotype.Service
|
||||||
|
import org.springframework.web.bind.annotation.RestController
|
||||||
import java.lang.reflect.Modifier
|
import java.lang.reflect.Modifier
|
||||||
import kotlin.test.assertFails
|
|
||||||
|
|
||||||
class EqualsAndToStringTest {
|
class EqualsAndToStringTest {
|
||||||
@Test
|
@TestFactory
|
||||||
fun equalsTest() {
|
fun equalsTest(): List<DynamicTest> {
|
||||||
assertFails {
|
|
||||||
EqualsVerifier
|
val classes = PackageScanner.getClassesIn("dev.usbharu.hideout", null, true)
|
||||||
.simple()
|
|
||||||
.suppress(Warning.INHERITED_DIRECTLY_FROM_OBJECT)
|
return classes
|
||||||
.forPackage("dev.usbharu.hideout", true)
|
.asSequence()
|
||||||
.verify()
|
.filter {
|
||||||
}
|
it.getAnnotation(Service::class.java) == null
|
||||||
|
}
|
||||||
|
.filter {
|
||||||
|
it.getAnnotation(Repository::class.java) == null
|
||||||
|
}
|
||||||
|
.filter {
|
||||||
|
it.getAnnotation(Component::class.java) == null
|
||||||
|
}
|
||||||
|
.filter {
|
||||||
|
it.getAnnotation(Controller::class.java) == null
|
||||||
|
}
|
||||||
|
.filter {
|
||||||
|
it.getAnnotation(RestController::class.java) == null
|
||||||
|
}
|
||||||
|
.filter {
|
||||||
|
it.getAnnotation(Configuration::class.java) == null
|
||||||
|
}
|
||||||
|
.filterNot {
|
||||||
|
it.packageName.startsWith("dev.usbharu.hideout.domain.mastodon.model.generated")
|
||||||
|
}
|
||||||
|
.filterNot {
|
||||||
|
Throwable::class.java.isAssignableFrom(it)
|
||||||
|
}
|
||||||
|
.filterNot {
|
||||||
|
Modifier.isAbstract(it.modifiers)
|
||||||
|
}
|
||||||
|
.filter {
|
||||||
|
try {
|
||||||
|
it.kotlin.objectInstance == null
|
||||||
|
} catch (_: Exception) {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
.filter {
|
||||||
|
it.superclass == Any::class.java || it.superclass?.packageName?.startsWith("dev.usbharu") ?: true
|
||||||
|
}
|
||||||
|
.map {
|
||||||
|
dynamicTest(it.name) {
|
||||||
|
if (it.isKotlinClass()) {
|
||||||
|
println(" at ${it.name}.toString(${it.simpleName}.kt:1)")
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
EqualsVerifier.simple()
|
||||||
|
.suppress(Warning.INHERITED_DIRECTLY_FROM_OBJECT, Warning.TRANSIENT_FIELDS)
|
||||||
|
.forClass(it)
|
||||||
|
.verify()
|
||||||
|
} catch (e: AssertionError) {
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.toList()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@TestFactory
|
||||||
fun toStringTest() {
|
fun toStringTest(): List<DynamicTest> {
|
||||||
|
|
||||||
PackageScanner.getClassesIn("dev.usbharu.hideout", null, true)
|
return PackageScanner.getClassesIn("dev.usbharu.hideout", null, true)
|
||||||
.filter {
|
.filter {
|
||||||
it != null && !it.isEnum && !it.isInterface && !Modifier.isAbstract(it.modifiers)
|
it != null && !it.isEnum && !it.isInterface && !Modifier.isAbstract(it.modifiers)
|
||||||
}
|
}
|
||||||
.forEach {
|
.filter {
|
||||||
try {
|
val clazz = it.getMethod(it::toString.name).declaringClass
|
||||||
ToStringVerifier.forClass(it).verify()
|
clazz != Any::class.java && clazz != Throwable::class.java
|
||||||
} catch (e: AssertionError) {
|
}
|
||||||
println(it.name)
|
.filter {
|
||||||
e.printStackTrace()
|
it.superclass == Any::class.java || it.superclass?.packageName?.startsWith("dev.usbharu") ?: true
|
||||||
} catch (e: Exception) {
|
}
|
||||||
println(it.name)
|
.map {
|
||||||
e.printStackTrace()
|
|
||||||
|
dynamicTest(it.name) {
|
||||||
|
if (it.isKotlinClass()) {
|
||||||
|
println(" at ${it.name}.toString(${it.simpleName}.kt:1)")
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
ToStringVerifier.forClass(it).withPreset(Presets.INTELLI_J).verify()
|
||||||
|
} catch (e: Exception) {
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,83 @@
|
||||||
|
package dev.usbharu.hideout.activitypub.domain.model
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.module.kotlin.readValue
|
||||||
|
import dev.usbharu.hideout.application.config.ActivityPubConfig
|
||||||
|
import org.intellij.lang.annotations.Language
|
||||||
|
import org.junit.jupiter.api.Test
|
||||||
|
|
||||||
|
class CreateTest {
|
||||||
|
@Test
|
||||||
|
fun Createのデイシリアライズができる() {
|
||||||
|
@Language("JSON") val json = """{
|
||||||
|
"@context": [
|
||||||
|
"https://www.w3.org/ns/activitystreams",
|
||||||
|
"https://w3id.org/security/v1",
|
||||||
|
{
|
||||||
|
"manuallyApprovesFollowers": "as:manuallyApprovesFollowers",
|
||||||
|
"sensitive": "as:sensitive",
|
||||||
|
"Hashtag": "as:Hashtag",
|
||||||
|
"quoteUrl": "as:quoteUrl",
|
||||||
|
"toot": "http://joinmastodon.org/ns#",
|
||||||
|
"Emoji": "toot:Emoji",
|
||||||
|
"featured": "toot:featured",
|
||||||
|
"discoverable": "toot:discoverable",
|
||||||
|
"schema": "http://schema.org#",
|
||||||
|
"PropertyValue": "schema:PropertyValue",
|
||||||
|
"value": "schema:value",
|
||||||
|
"misskey": "https://misskey-hub.net/ns#",
|
||||||
|
"_misskey_content": "misskey:_misskey_content",
|
||||||
|
"_misskey_quote": "misskey:_misskey_quote",
|
||||||
|
"_misskey_reaction": "misskey:_misskey_reaction",
|
||||||
|
"_misskey_votes": "misskey:_misskey_votes",
|
||||||
|
"isCat": "misskey:isCat",
|
||||||
|
"vcard": "http://www.w3.org/2006/vcard/ns#"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"id": "https://misskey.usbharu.dev/notes/9f2i9cm88e/activity",
|
||||||
|
"actor": "https://misskey.usbharu.dev/users/97ws8y3rj6",
|
||||||
|
"type": "Create",
|
||||||
|
"published": "2023-05-22T14:26:53.600Z",
|
||||||
|
"object": {
|
||||||
|
"id": "https://misskey.usbharu.dev/notes/9f2i9cm88e",
|
||||||
|
"type": "Note",
|
||||||
|
"attributedTo": "https://misskey.usbharu.dev/users/97ws8y3rj6",
|
||||||
|
"content": "<p><a href=\"https://calckey.jp/@trapezial\" class=\"u-url mention\">@trapezial@calckey.jp</a><span> いやそういうことじゃなくて、連合先と自インスタンスで状態が狂うことが多いのでどっちに合わせるべきかと…</span></p>",
|
||||||
|
"_misskey_content": "@trapezial@calckey.jp いやそういうことじゃなくて、連合先と自インスタンスで状態が狂うことが多いのでどっちに合わせるべきかと…",
|
||||||
|
"source": {
|
||||||
|
"content": "@trapezial@calckey.jp いやそういうことじゃなくて、連合先と自インスタンスで状態が狂うことが多いのでどっちに合わせるべきかと…",
|
||||||
|
"mediaType": "text/x.misskeymarkdown"
|
||||||
|
},
|
||||||
|
"published": "2023-05-22T14:26:53.600Z",
|
||||||
|
"to": [
|
||||||
|
"https://misskey.usbharu.dev/users/97ws8y3rj6/followers"
|
||||||
|
],
|
||||||
|
"cc": [
|
||||||
|
"https://www.w3.org/ns/activitystreams#Public",
|
||||||
|
"https://calckey.jp/users/9bu1xzwjyb"
|
||||||
|
],
|
||||||
|
"inReplyTo": "https://calckey.jp/notes/9f2i7ymf1d",
|
||||||
|
"attachment": [],
|
||||||
|
"sensitive": false,
|
||||||
|
"tag": [
|
||||||
|
{
|
||||||
|
"type": "Mention",
|
||||||
|
"href": "https://calckey.jp/users/9bu1xzwjyb",
|
||||||
|
"name": "@trapezial@calckey.jp"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"to": [
|
||||||
|
"https://misskey.usbharu.dev/users/97ws8y3rj6/followers"
|
||||||
|
],
|
||||||
|
"cc": [
|
||||||
|
"https://www.w3.org/ns/activitystreams#Public",
|
||||||
|
"https://calckey.jp/users/9bu1xzwjyb"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
|
||||||
|
val objectMapper = ActivityPubConfig().objectMapper()
|
||||||
|
|
||||||
|
objectMapper.readValue<Create>(json)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
package dev.usbharu.hideout.activitypub.domain.model
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.module.kotlin.readValue
|
||||||
|
import dev.usbharu.hideout.application.config.ActivityPubConfig
|
||||||
|
import org.intellij.lang.annotations.Language
|
||||||
|
import org.junit.jupiter.api.Test
|
||||||
|
|
||||||
|
class DocumentTest {
|
||||||
|
@Test
|
||||||
|
fun Documentをデシリアライズできる() {
|
||||||
|
@Language("JSON") val json = """{
|
||||||
|
"type": "Document",
|
||||||
|
"mediaType": "image/webp",
|
||||||
|
"url": "https://s3misskey.usbharu.dev/misskey-minio/misskey-minio/data/81ec9ad1-2581-466e-b90c-d9d2350ab95c.webp",
|
||||||
|
"name": "ALTテスト"
|
||||||
|
}"""
|
||||||
|
|
||||||
|
val objectMapper = ActivityPubConfig().objectMapper()
|
||||||
|
|
||||||
|
objectMapper.readValue<Document>(json)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun nameがnullなDocumentのデイシリアライズができる() {
|
||||||
|
//language=JSON
|
||||||
|
val json = """{
|
||||||
|
"type": "Document",
|
||||||
|
"mediaType": "image/webp",
|
||||||
|
"url": "https://s3misskey.usbharu.dev/misskey-minio/misskey-minio/data/81ec9ad1-2581-466e-b90c-d9d2350ab95c.webp",
|
||||||
|
"name": null
|
||||||
|
}"""
|
||||||
|
|
||||||
|
val objectMapper = ActivityPubConfig().objectMapper()
|
||||||
|
|
||||||
|
objectMapper.readValue<Document>(json)
|
||||||
|
}
|
||||||
|
}
|
|
@ -72,4 +72,68 @@ class PersonSerializeTest {
|
||||||
|
|
||||||
val readValue = objectMapper.readValue<Person>(personString)
|
val readValue = objectMapper.readValue<Person>(personString)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun MisskeyのnameがnullのPersonのデシリアライズができる() {
|
||||||
|
//language=JSON
|
||||||
|
val json = """{
|
||||||
|
"@context": [
|
||||||
|
"https://www.w3.org/ns/activitystreams",
|
||||||
|
"https://w3id.org/security/v1",
|
||||||
|
{
|
||||||
|
"manuallyApprovesFollowers": "as:manuallyApprovesFollowers",
|
||||||
|
"sensitive": "as:sensitive",
|
||||||
|
"Hashtag": "as:Hashtag",
|
||||||
|
"quoteUrl": "as:quoteUrl",
|
||||||
|
"toot": "http://joinmastodon.org/ns#",
|
||||||
|
"Emoji": "toot:Emoji",
|
||||||
|
"featured": "toot:featured",
|
||||||
|
"discoverable": "toot:discoverable",
|
||||||
|
"schema": "http://schema.org#",
|
||||||
|
"PropertyValue": "schema:PropertyValue",
|
||||||
|
"value": "schema:value",
|
||||||
|
"misskey": "https://misskey-hub.net/ns#",
|
||||||
|
"_misskey_content": "misskey:_misskey_content",
|
||||||
|
"_misskey_quote": "misskey:_misskey_quote",
|
||||||
|
"_misskey_reaction": "misskey:_misskey_reaction",
|
||||||
|
"_misskey_votes": "misskey:_misskey_votes",
|
||||||
|
"_misskey_summary": "misskey:_misskey_summary",
|
||||||
|
"isCat": "misskey:isCat",
|
||||||
|
"vcard": "http://www.w3.org/2006/vcard/ns#"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "Person",
|
||||||
|
"id": "https://misskey.usbharu.dev/users/9ghwhv9zgg",
|
||||||
|
"inbox": "https://misskey.usbharu.dev/users/9ghwhv9zgg/inbox",
|
||||||
|
"outbox": "https://misskey.usbharu.dev/users/9ghwhv9zgg/outbox",
|
||||||
|
"followers": "https://misskey.usbharu.dev/users/9ghwhv9zgg/followers",
|
||||||
|
"following": "https://misskey.usbharu.dev/users/9ghwhv9zgg/following",
|
||||||
|
"featured": "https://misskey.usbharu.dev/users/9ghwhv9zgg/collections/featured",
|
||||||
|
"sharedInbox": "https://misskey.usbharu.dev/inbox",
|
||||||
|
"endpoints": {
|
||||||
|
"sharedInbox": "https://misskey.usbharu.dev/inbox"
|
||||||
|
},
|
||||||
|
"url": "https://misskey.usbharu.dev/@relay_test",
|
||||||
|
"preferredUsername": "relay_test",
|
||||||
|
"name": null,
|
||||||
|
"summary": null,
|
||||||
|
"_misskey_summary": null,
|
||||||
|
"icon": null,
|
||||||
|
"image": null,
|
||||||
|
"tag": [],
|
||||||
|
"manuallyApprovesFollowers": true,
|
||||||
|
"discoverable": true,
|
||||||
|
"publicKey": {
|
||||||
|
"id": "https://misskey.usbharu.dev/users/9ghwhv9zgg#main-key",
|
||||||
|
"type": "Key",
|
||||||
|
"owner": "https://misskey.usbharu.dev/users/9ghwhv9zgg",
|
||||||
|
"publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA2n5yekTaI4ex5VDWzQfE\nJpWMURAMWl8RcXHLPyLQVQ/PrHp7qatGXmKJUnAOBcq1cwk+VCqTEqx8vJCOZsr1\nMq+D3FMcFdwgtJ0nivPJPx2457b5kfQ4LTkWajcFhj2qixa/XFq6hHei3LDaE6hJ\nGQbdj9NTVlMd7VpiFQkoU09vAPUwGxRoP9Qbc/sh7jrKYFB3iRmY/+zOc+PFpnfn\nG8V1d2v+lnkb9f7t0Z8y2ckk6TVcLPRZktF15eGClVptlgts3hwhrcyrpBs2Dn0U\n35KgIhkhZGAjzk0uyplpfKcserXuGvsjJvelZ3BtMGsuR4kGLHrmiRQp23mIoA1I\n8tfVuV0zPOyO3ruLk2fOjoeZ4XvFHGRNKo66Qx055/8G8Ug5vU8lvIGXm9sflaA9\ntR3AKDNsyxEfjAfrfgJ7cwlKSlLZmkU51jtYEqJ48ZkiIa6fMC0m4QGXdaXmhFWC\no1sGoIErRFpRHewdGlLC9S8R/cMxjex+n8maF0yh79y7aVvU+TS6pRWg5wYjY8r3\nZqAVg/PGRVGAbjVdIdcsjH5ClwAFBW16S633D3m7HJypwwVCzVOvMZqPqcQ/2o8c\nUk+xa88xQG+OPqoAaQqyV9iqsmCMgYM/AcX/BC2h7L2mE/PWoXnoCxGPxr5uvyBf\nHQakDGg4pFZcpVNrDlYo260CAwEAAQ==\n-----END PUBLIC KEY-----\n"
|
||||||
|
},
|
||||||
|
"isCat": false
|
||||||
|
}"""
|
||||||
|
|
||||||
|
val objectMapper = ActivityPubConfig().objectMapper()
|
||||||
|
|
||||||
|
objectMapper.readValue<Person>(json)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue