diff --git a/core/src/main/kotlin/dev/usbharu/multim/api/ApiClient.kt b/core/src/main/kotlin/dev/usbharu/multim/api/ApiClient.kt index 6cd8c0d..1b11cc0 100644 --- a/core/src/main/kotlin/dev/usbharu/multim/api/ApiClient.kt +++ b/core/src/main/kotlin/dev/usbharu/multim/api/ApiClient.kt @@ -67,6 +67,7 @@ abstract class ApiClient(var baseUrl: String, val client: HttpClient) { } catch (e: ServerResponseException) { return Err(HttpClientServerError(e)) } + Logger.warn(post.bodyAsText()) return runCatching { post.body() }.fold( onSuccess = { Ok(it) }, onFailure = { @@ -81,15 +82,18 @@ abstract class ApiClient(var baseUrl: String, val client: HttpClient) { baseUrl: String = this.baseUrl ): Result { Logger.trace("Api Client", "Post without response $baseUrl$path") - return runCatching { + try { client.post(baseUrl + path) { contentType(ContentType.Application.Json) setBody(content) } - }.fold(onSuccess = Ok(), onFailure = { - Logger.warn("Api Client", "FAILURE Post withou response $baseUrl$path") - Err(ThrowableError(it)) - }) + } catch (e: ClientRequestException) { + return Err(HttpClientClientError(e)) + } catch (e: ServerResponseException) { + return Err(HttpClientServerError(e)) + } + return Ok(Unit) + } suspend fun get( diff --git a/core/src/main/kotlin/dev/usbharu/multim/error/MultiMError.kt b/core/src/main/kotlin/dev/usbharu/multim/error/MultiMError.kt index bd24e62..ebc26cf 100644 --- a/core/src/main/kotlin/dev/usbharu/multim/error/MultiMError.kt +++ b/core/src/main/kotlin/dev/usbharu/multim/error/MultiMError.kt @@ -10,7 +10,7 @@ open class MultiMError( val _throwable: Throwable? = null, val errorType: ErrorType ) : - ThrowableError(_throwable ?: Throwable(message),"MultiM ${errorType.message} ERROR : $message") + ThrowableError(_throwable ?: Throwable(message), "MultiM ${errorType.message} ERROR : $message") class MultiMHttpError(val httpError: HttpError, throwable: Throwable? = httpError.throwable) : MultiMError( @@ -115,7 +115,9 @@ fun Result.mapMultiMError(): Result { is HttpClientClientError -> { Err(MultiMHttpError(this.error.throwable as ClientRequestException)) } - + is MultiMError -> { + Err(this.error as MultiMError) + } else -> { Err(MultiMError(this.error.message, this.error.throwable, ErrorType.UNKNOWN)) } @@ -124,8 +126,8 @@ fun Result.mapMultiMError(): Result { } } -typealias MultiMResult = Result +typealias MultiMResult = Result fun TODO(throwable: Throwable? = runCatching { kotlin.TODO() }.exceptionOrNull()): Err { - return Err(MultiMError("Not yet Implement.",throwable,ErrorType.NOT_IMPL)) + return Err(MultiMError("Not yet Implement.", throwable, ErrorType.NOT_IMPL)) } diff --git a/impl/misskey/build.gradle.kts b/impl/misskey/build.gradle.kts index e4a7497..ab7825b 100644 --- a/impl/misskey/build.gradle.kts +++ b/impl/misskey/build.gradle.kts @@ -2,6 +2,15 @@ dependencies { implementation(project(":core")) } +sourceSets{ + test{ + kotlin{ + compileClasspath+=project(":core").sourceSets.test.get().output + runtimeClasspath+=project(":core").sourceSets.test.get().output + } + } +} + kotlin{ } diff --git a/impl/misskey/src/main/kotlin/dev/usbharu/multim/misskey/v12/common/api/MisskeyAccountApi.kt b/impl/misskey/src/main/kotlin/dev/usbharu/multim/misskey/v12/common/api/MisskeyAccountApi.kt index 0b9cb0e..e91a44d 100644 --- a/impl/misskey/src/main/kotlin/dev/usbharu/multim/misskey/v12/common/api/MisskeyAccountApi.kt +++ b/impl/misskey/src/main/kotlin/dev/usbharu/multim/misskey/v12/common/api/MisskeyAccountApi.kt @@ -4,10 +4,12 @@ import com.github.michaelbull.result.Err import com.github.michaelbull.result.Ok import com.github.michaelbull.result.Result import com.github.michaelbull.result.map +import dev.usbharu.multim.Logger import dev.usbharu.multim.api.AccountApi import dev.usbharu.multim.error.ErrorType import dev.usbharu.multim.error.MultiMError import dev.usbharu.multim.error.TODO +import dev.usbharu.multim.error.mapMultiMError import dev.usbharu.multim.misskey.v12.api.MisskeyApis import dev.usbharu.multim.misskey.v12.common.* import dev.usbharu.multim.misskey.v12.converter.misskey.v12.NoteConverter.toStatus @@ -44,8 +46,7 @@ class MisskeyAccountApi(val misskeyApis: MisskeyApis) : AccountApi { override suspend fun follow(account: Account): Result { return if (account is MisskeyAccount) { - misskeyApis.following.create(FollowingCreateRequest(account.id)) - Ok(Unit) + misskeyApis.following.create(FollowingCreateRequest(account.id)).map { } } else { TODO() } @@ -53,8 +54,7 @@ class MisskeyAccountApi(val misskeyApis: MisskeyApis) : AccountApi { override suspend fun unfollow(account: Account): Result { return if (account is MisskeyAccount) { - misskeyApis.following.delete(FollowingDeleteRequest(account.id)) - Ok(Unit) + misskeyApis.following.delete(FollowingDeleteRequest(account.id)).map { } } else { // サーバーが認知していないアカウントのフォローを辞めることはできないのでfalse Err(MultiMError("Can not unfollow", null, ErrorType.API)) diff --git a/impl/misskey/src/main/kotlin/dev/usbharu/multim/misskey/v12/model/FollowingCreate.kt b/impl/misskey/src/main/kotlin/dev/usbharu/multim/misskey/v12/model/FollowingCreate.kt index 1d87932..504db26 100644 --- a/impl/misskey/src/main/kotlin/dev/usbharu/multim/misskey/v12/model/FollowingCreate.kt +++ b/impl/misskey/src/main/kotlin/dev/usbharu/multim/misskey/v12/model/FollowingCreate.kt @@ -1,10 +1,11 @@ package dev.usbharu.multim.misskey.v12.model +import dev.usbharu.multim.misskey.v12.model.components.MisskeyNeedAuth import dev.usbharu.multim.misskey.v12.model.components.UserLite @kotlinx.serialization.Serializable data class FollowingCreateRequest( val userId: String -) +):MisskeyNeedAuth() typealias FollowingCreateResponse = UserLite diff --git a/impl/misskey/src/main/kotlin/dev/usbharu/multim/misskey/v12/model/FollowingDelete.kt b/impl/misskey/src/main/kotlin/dev/usbharu/multim/misskey/v12/model/FollowingDelete.kt index de1684b..427331e 100644 --- a/impl/misskey/src/main/kotlin/dev/usbharu/multim/misskey/v12/model/FollowingDelete.kt +++ b/impl/misskey/src/main/kotlin/dev/usbharu/multim/misskey/v12/model/FollowingDelete.kt @@ -1,10 +1,11 @@ package dev.usbharu.multim.misskey.v12.model +import dev.usbharu.multim.misskey.v12.model.components.MisskeyNeedAuth import dev.usbharu.multim.misskey.v12.model.components.UserLite @kotlinx.serialization.Serializable data class FollowingDeleteRequest( val userId: String -) +) : MisskeyNeedAuth() typealias FollowingDeleteResponse = UserLite diff --git a/impl/misskey/src/main/kotlin/dev/usbharu/multim/misskey/v12/model/UsersRelation.kt b/impl/misskey/src/main/kotlin/dev/usbharu/multim/misskey/v12/model/UsersRelation.kt index 52c9bbd..9f30ed2 100644 --- a/impl/misskey/src/main/kotlin/dev/usbharu/multim/misskey/v12/model/UsersRelation.kt +++ b/impl/misskey/src/main/kotlin/dev/usbharu/multim/misskey/v12/model/UsersRelation.kt @@ -1,7 +1,9 @@ package dev.usbharu.multim.misskey.v12.model +import dev.usbharu.multim.misskey.v12.model.components.MisskeyNeedAuth + @kotlinx.serialization.Serializable -data class UsersRelationRequest(val userId: String) +data class UsersRelationRequest(val userId: String) : MisskeyNeedAuth() @kotlinx.serialization.Serializable data class UsersRelationResponse( diff --git a/impl/misskey/src/test/kotlin/dev/usbharu/multim/api/MisskeyAccountApiTest.kt b/impl/misskey/src/test/kotlin/dev/usbharu/multim/api/MisskeyAccountApiTest.kt new file mode 100644 index 0000000..691164c --- /dev/null +++ b/impl/misskey/src/test/kotlin/dev/usbharu/multim/api/MisskeyAccountApiTest.kt @@ -0,0 +1,284 @@ +package dev.usbharu.multim.api + +import com.github.michaelbull.result.get +import com.github.michaelbull.result.getError +import com.github.michaelbull.result.onFailure +import com.github.michaelbull.result.onSuccess +import dev.usbharu.multim.Logger +import dev.usbharu.multim.MultiM +import dev.usbharu.multim.error.MultiMHttpError +import dev.usbharu.multim.error.MultiMResult +import dev.usbharu.multim.misskey.v12.api.MisskeyApis +import dev.usbharu.multim.misskey.v12.common.MisskeyAccount +import dev.usbharu.multim.misskey.v12.common.MisskeyAvatar +import dev.usbharu.multim.misskey.v12.common.api.MisskeyAccountApi +import dev.usbharu.multim.misskey.v12.common.api.MisskeyApiClient +import dev.usbharu.multim.model.SingleTokenAuth +import io.github.aakira.napier.DebugAntilog +import io.github.aakira.napier.Napier +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.test.runTest +import org.junit.jupiter.api.Assertions.* +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.fail + +@OptIn(ExperimentalCoroutinesApi::class) +class MisskeyAccountApiTest : AccountApiTest() { + override val accountApi: AccountApi + get() = MisskeyAccountApi( + MisskeyApis( + MisskeyApiClient( + SingleTokenAuth(System.getProperty("multim_misskey_token")), + System.getProperty("multim_misskey_instance"), + MultiM.httpClientWithJson + ) + ) + ) + + @Test + override fun userTimeline() = runTest { + accountApi.userTimeline( + MisskeyAccount( + "9bg1zu54y7", + "test", + "test", + false, + MisskeyAvatar("https://test-misskey-v12.usbharu.dev/identicon/9bg1zu54y7") + ) + ).failOnError() + } + + @Test + override fun follow() = runTest { + val myself = MisskeyAccount( + "9bg1zu54y7", + "test", + "test", + false, + MisskeyAvatar("https://test-misskey-v12.usbharu.dev/identicon/9bg1zu54y7") + ) + val account = MisskeyAccount( + "9bk3hbcjcy", + "test1", + "test1", + false, + MisskeyAvatar("https://test-misskey-v12.usbharu.dev/identicon/9bk3hbcjcy") + ) + if (accountApi.relationships(myself, account).failOnError().following) { + Logger.warn("すでにフォローされているのでフォローをいったん解除します。") + accountApi.unfollow(account) + } + accountApi.follow(account).failOnError() + assertTrue(accountApi.relationships(myself, account).failOnError().following,"フォローされていない") + accountApi.unfollow(account).failOnError() + assertFalse(accountApi.relationships(myself, account).failOnError().following,"フォローしたまま") + } + + @Test + override fun follow_illegalAccount_returnErr() = runTest { + val myself = MisskeyAccount( + "9bg1zu54y7", + "test", + "test", + false, + MisskeyAvatar("https://test-misskey-v12.usbharu.dev/identicon/9bg1zu54y7") + ) + val illegalAccount = MisskeyAccount( + "Obrg", + "beard", + "leg", + false, + MisskeyAvatar("https://test-misskey-v12.usbharu.dev/identicon/TrT") + ) + val follow = accountApi.follow(illegalAccount) + follow.onSuccess { + fail("成功してはいけない") + } + follow.onFailure { + if (it is MultiMHttpError) { + + }else { + Napier.base(DebugAntilog()) + Logger.error("Account Api Test","想定されたエラーではない",it) + fail("想定されたエラーではない",) + } + } + } + + @Test + override fun unfollow() = runTest { + val myself = MisskeyAccount( + "9bg1zu54y7", + "test", + "test", + false, + MisskeyAvatar("https://test-misskey-v12.usbharu.dev/identicon/9bg1zu54y7") + ) + val account = MisskeyAccount( + "9bk3hbcjcy", + "test1", + "test1", + false, + MisskeyAvatar("https://test-misskey-v12.usbharu.dev/identicon/9bk3hbcjcy") + ) + if (!accountApi.relationships(myself, account).failOnError().following) { + Logger.warn("まだにフォローされているのでフォローをいったんします。") + accountApi.follow(account) + } + accountApi.unfollow(account).failOnError() + assertFalse(accountApi.relationships(myself, account).failOnError().following,"フォローされていない") + } + + @Test + override fun unfollow_illegalAccount_returnErr() = runTest { + val illegalAccount = MisskeyAccount( + "I37", + "1Q8I", + "U72oM", + false, + MisskeyAvatar("https://test-misskey-v12.usbharu.dev/identicon/TFOTXjvs") + ) + val unfollow = accountApi.unfollow(illegalAccount) + unfollow.onSuccess { + fail("成功してはいけない") + } + unfollow.onFailure { + if (it is MultiMHttpError) { + + }else { + Napier.base(DebugAntilog()) + Logger.error("Account Api Test","想定されたエラーではない",it) + fail("想定されたエラーではない",) + } + } + } + + @Test + override fun profile() = runTest { + val myself = MisskeyAccount( + "9bg1zu54y7", + "test", + "test", + false, + MisskeyAvatar("https://test-misskey-v12.usbharu.dev/identicon/9bg1zu54y7") + ) + val profile = accountApi.profile(myself).failOnError() + assertEquals(myself,profile.account) + } + + @Test + override fun profile_illegalAccount_returnErr() = runTest { + val illegalAccount = MisskeyAccount( + "x0Z3N", + "R8kOy", + "2bQfw", + false, + MisskeyAvatar("https://test-misskey-v12.usbharu.dev/identicon/BPk") + ) + val profile = accountApi.profile(illegalAccount) + profile.onSuccess { + fail("成功してはいけない") + } + profile.onFailure { + if (it is MultiMHttpError) { + + }else { + fail("想定されたエラーではない") + } + } + } + + override fun statuses() { + TODO("Not yet implemented") + } + + override fun statusesWithIncludeRepost() { + TODO("Not yet implemented") + } + + override fun statuses_illegalAccount_returnErr() { + TODO("Not yet implemented") + } + + @Test + override fun relationships() = runTest { + val myself = MisskeyAccount( + "9bg1zu54y7", + "test", + "test", + false, + MisskeyAvatar("https://test-misskey-v12.usbharu.dev/identicon/9bg1zu54y7") + ) + val account = MisskeyAccount( + "9bk3hbcjcy", + "test1", + "test1", + false, + MisskeyAvatar("https://test-misskey-v12.usbharu.dev/identicon/9bk3hbcjcy") + ) + accountApi.relationships(myself,account).failOnError() + } + + @Test + override fun relationships_illegalAccount_returnErr() = runTest { + Napier.base(DebugAntilog()) + val myself = MisskeyAccount( + "9bg1zu54y7", + "test", + "test", + false, + MisskeyAvatar("https://test-misskey-v12.usbharu.dev/identicon/9bg1zu54y7") + ) + val illegalAccount = MisskeyAccount( + "Obrg", + "beard", + "leg", + false, + MisskeyAvatar("https://test-misskey-v12.usbharu.dev/identicon/TrT") + ) + val relationships = accountApi.relationships(myself, illegalAccount) + relationships.onSuccess { + + } + relationships.onFailure { + if (it is MultiMHttpError) { + fail("Misskey実装ではエラーが出ない") + }else { + fail("想定されたエラーではない") + } + } + } + + override fun requestCancel() { + TODO("Not yet implemented") + } + + override fun requestCancel_illegalAccount_returnErr() { + TODO("Not yet implemented") + } + + override fun requestAccept() { + TODO("Not yet implemented") + } + + override fun requestAccept_illegalAccount_returnErr() { + TODO("Not yet implemented") + } + + override fun requestReject() { + TODO("Not yet implemented") + } + + override fun requestReject_illegalAccount_returnErr() { + TODO("Not yet implemented") + } + + fun MultiMResult.failOnError(): T { + val get = this.get() + if (get != null) { + return get + } + val error = this.getError()!! + fail("Return Error", error.throwable) + } +}