diff --git a/core/src/main/kotlin/dev/usbharu/multim/Logger.kt b/core/src/main/kotlin/dev/usbharu/multim/Logger.kt new file mode 100644 index 0000000..cd953d0 --- /dev/null +++ b/core/src/main/kotlin/dev/usbharu/multim/Logger.kt @@ -0,0 +1,94 @@ +package dev.usbharu.multim + +import dev.usbharu.multim.error.Error +import dev.usbharu.multim.error.ThrowableError +import io.github.aakira.napier.Napier + +object Logger { + + const val nullString = "null" + fun info(tag: String? = null, message: String? = null) = + Napier.i(message ?: nullString, null, tag) + + fun info(message: String? = null) = Napier.i(message ?: nullString) + + fun info(tag: String? = null, message: String? = null, throwable: Throwable? = null) = + Napier.i(message ?: nullString, throwable, tag) + + fun info(tag: String? = null, message: String? = null, error: Error) { + message?.let { Napier.i(it, null, tag) } + if (error is ThrowableError) { + Napier.i(error.message, error.throwable, tag) + } else { + Napier.i(error.message, null, tag) + } + } + + fun debug(tag: String? = null, message: String? = null) = + Napier.d(message ?: nullString, null, tag) + + fun debug(message: String? = null) = Napier.d(message ?: nullString) + + fun debug(tag: String? = null, message: String? = null, throwable: Throwable? = null) = + Napier.d(message ?: nullString, throwable, tag) + + fun debug(tag: String? = null, message: String? = null, error: Error) { + message?.let { Napier.d(it, null, tag) } + if (error is ThrowableError) { + Napier.d(error.message, error.throwable, tag) + } else { + Napier.d(error.message, null, tag) + } + } + + fun error(tag: String? = null, message: String? = null) = + Napier.e(message ?: nullString, null, tag) + + fun error(message: String? = null) = Napier.e(message ?: nullString) + + fun error(tag: String? = null, message: String? = null, throwable: Throwable? = null) = + Napier.e(message ?: nullString, throwable, tag) + + fun error(tag: String? = null, message: String? = null, error: Error) { + message?.let { Napier.e(it, null, tag) } + if (error is ThrowableError) { + Napier.e(error.message, error.throwable, tag) + } else { + Napier.e(error.message, null, tag) + } + } + + fun warn(tag: String? = null, message: String? = null) = + Napier.w(message ?: nullString, null, tag) + + fun warn(message: String? = null) = Napier.w(message ?: nullString) + + fun warn(tag: String? = null, message: String? = null, throwable: Throwable? = null) = + Napier.w(message ?: nullString, throwable, tag) + + fun warn(tag: String? = null, message: String? = null, error: Error) { + message?.let { Napier.w(it, null, tag) } + if (error is ThrowableError) { + Napier.w(error.message, error.throwable, tag) + } else { + Napier.w(error.message, null, tag) + } + } + + fun trace(tag: String? = null, message: String? = null) = + Napier.v(message ?: nullString, null, tag) + + fun trace(message: String? = null) = Napier.v(message ?: nullString) + + fun trace(tag: String? = null, message: String? = null, throwable: Throwable? = null) = + Napier.v(message ?: nullString, throwable, tag) + + fun trace(tag: String? = null, message: String? = null, error: Error) { + message?.let { Napier.v(it, null, tag) } + if (error is ThrowableError) { + Napier.v(error.message, error.throwable, tag) + } else { + Napier.v(error.message, null, tag) + } + } +} diff --git a/core/src/main/kotlin/dev/usbharu/multim/MultiM.kt b/core/src/main/kotlin/dev/usbharu/multim/MultiM.kt index df1b53d..f3a6ffd 100644 --- a/core/src/main/kotlin/dev/usbharu/multim/MultiM.kt +++ b/core/src/main/kotlin/dev/usbharu/multim/MultiM.kt @@ -1,18 +1,19 @@ package dev.usbharu.multim import com.github.michaelbull.result.Result -import com.github.michaelbull.result.flatMap import com.github.michaelbull.result.map +import com.github.michaelbull.result.onFailure +import com.github.michaelbull.result.onSuccess import dev.usbharu.multim.api.NodeinfoApi import dev.usbharu.multim.error.MultiMError import dev.usbharu.multim.factory.MultiMApis import dev.usbharu.multim.factory.PlatformApiFactory import dev.usbharu.multim.multi.MultiAccountApiBase -import io.github.aakira.napier.Napier import io.ktor.client.* import io.ktor.client.engine.cio.* import io.ktor.client.plugins.contentnegotiation.* import io.ktor.client.plugins.logging.* +import io.ktor.client.plugins.logging.Logger import io.ktor.serialization.kotlinx.json.* import kotlinx.serialization.json.Json @@ -34,13 +35,33 @@ object MultiM { token: String, factory: PlatformApiFactory, httpClient: HttpClient = httpClientWithJson - ): Result { + ): Result { + dev.usbharu.multim.Logger.info("Create Client", "START Create client with url:$url.") + dev.usbharu.multim.Logger.debug( + "Create Client", + "Create client with url:$url token:${"*".repeat(token.length)} factory:${factory::class.java}." + ) + val result = NodeinfoApi(httpClient).nodeinfo(url) + .map { nodeInfo -> factory.factory(nodeInfo, httpClient, token, url) } + result.onSuccess { + dev.usbharu.multim.Logger.info("Create Client", "SUCCESS Create Client with url:$url") + } + result.onFailure { + dev.usbharu.multim.Logger.error( + "Create Client", + "FAILURE Create Client with url:$url token:${"*".repeat(token.length)} factory:${factory::class.java}.", + it + ) - return NodeinfoApi(httpClient).nodeinfo(url).map{ nodeInfo -> factory.factory(nodeInfo,httpClient,token,url) } + } + return result } fun createMultiAccountClients(serviceInfoList: List = listOf()): MultiAccountApiBase { - return MultiAccountApiBase(serviceInfoList) + dev.usbharu.multim.Logger.info("Create Client","START Create multi account client with ${serviceInfoList.size} services.") + val multiAccountApiBase = MultiAccountApiBase(serviceInfoList) + dev.usbharu.multim.Logger.info("Create Client","SUCCESS Create multi account client with ${serviceInfoList.size} services.") + return multiAccountApiBase } val json = Json { @@ -48,7 +69,7 @@ object MultiM { ignoreUnknownKeys = true } - val httpClient = HttpClient(CIO){ + val httpClient = HttpClient(CIO) { expectSuccess = true } @@ -56,7 +77,7 @@ object MultiM { install(Logging) { logger = object : Logger { override fun log(message: String) { - Napier.v(message,null,"HTTP Client") + dev.usbharu.multim.Logger.debug("HTTP Client", message) } } level = LogLevel.HEADERS @@ -64,7 +85,7 @@ object MultiM { } val httpClientWithJson = httpClientWithLogger.config { - install(ContentNegotiation){ + install(ContentNegotiation) { json(json) } } diff --git a/core/src/main/kotlin/dev/usbharu/multim/api/AccountApi.kt b/core/src/main/kotlin/dev/usbharu/multim/api/AccountApi.kt index 86c983d..74a7689 100644 --- a/core/src/main/kotlin/dev/usbharu/multim/api/AccountApi.kt +++ b/core/src/main/kotlin/dev/usbharu/multim/api/AccountApi.kt @@ -2,6 +2,7 @@ package dev.usbharu.multim.api import com.github.michaelbull.result.Err import com.github.michaelbull.result.Result +import dev.usbharu.multim.Logger import dev.usbharu.multim.error.ErrorType import dev.usbharu.multim.error.MultiMError import dev.usbharu.multim.model.* @@ -31,18 +32,22 @@ object NotImplAccountApi : AccountApi { since: StatusId?, until: StatusId? ): Result, MultiMError> { + Logger.debug("Account Api","Not impl account api. userTimeline.") return Err(MultiMError("userTimeline not implements", null, ErrorType.NOT_IMPL)) } override suspend fun follow(account: Account): Result { + Logger.debug("Account Api","Not impl account api. follow.") return Err(MultiMError("follow not implements", null, ErrorType.NOT_IMPL)) } override suspend fun unfollow(account: Account): Result { + Logger.debug("Account Api","Not impl account api. unfollow.") return Err(MultiMError("unfollow not implements",null,ErrorType.NOT_IMPL)) } override suspend fun profile(account: Account): Result { + Logger.debug("Account Api","Not impl account api. profile.") return Err(MultiMError("profile not implements",null,ErrorType.NOT_IMPL)) } @@ -50,6 +55,7 @@ object NotImplAccountApi : AccountApi { account: Account, includeRepost: Boolean ): Result, MultiMError> { + Logger.debug("Account Api","Not impl account api. statuses.") return Err(MultiMError("statuses not implements",null,ErrorType.NOT_IMPL)) } @@ -57,18 +63,22 @@ object NotImplAccountApi : AccountApi { myself: Account, other: Account ): Result { + Logger.debug("Account Api","Not impl account api. relationships.") return Err(MultiMError("relationships not implements",null,ErrorType.NOT_IMPL)) } override suspend fun requestCancel(account: Account): Result { + Logger.debug("Account Api","Not impl account api. requestCancel.") return Err(MultiMError("requestCancel not implements",null,ErrorType.NOT_IMPL)) } override suspend fun requestAccept(account: Account): Result { + Logger.debug("Account Api","Not impl account api. requestAccept.") return Err(MultiMError("requestAccept not implements",null,ErrorType.NOT_IMPL)) } override suspend fun requestReject(account: Account): Result { + Logger.debug("Account Api","Not impl account api. requestReject.") return Err(MultiMError("requestReject not implements",null,ErrorType.NOT_IMPL)) } } 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 e9f5fa1..6cd8c0d 100644 --- a/core/src/main/kotlin/dev/usbharu/multim/api/ApiClient.kt +++ b/core/src/main/kotlin/dev/usbharu/multim/api/ApiClient.kt @@ -3,8 +3,12 @@ package dev.usbharu.multim.api import com.github.michaelbull.result.Err import com.github.michaelbull.result.Ok import com.github.michaelbull.result.Result +import dev.usbharu.multim.Logger import dev.usbharu.multim.MultiM -import dev.usbharu.multim.error.* +import dev.usbharu.multim.error.HttpClientClientError +import dev.usbharu.multim.error.HttpClientServerError +import dev.usbharu.multim.error.Ok +import dev.usbharu.multim.error.ThrowableError import io.ktor.client.* import io.ktor.client.call.* import io.ktor.client.plugins.* @@ -22,16 +26,28 @@ abstract class ApiClient(var baseUrl: String, val client: HttpClient) { path: String, baseUrl: String = this.baseUrl ): Result { + Logger.trace("Api Client", "Post empty $baseUrl$path") val post = try { client.post(baseUrl + path) } catch (e: ClientRequestException) { + Logger.warn( + "Api Client", + "FAILURE Client Request Exception at Post empty $baseUrl$path" + ) return Err(HttpClientClientError(e)) } catch (e: ServerResponseException) { + Logger.warn( + "Api Client", + "FAILURE Server Response Exception at Post empty $baseUrl$path" + ) return Err(HttpClientServerError(e)) } return runCatching { post.body() }.fold( onSuccess = { Ok(it) }, - onFailure = { Err(ThrowableError(it)) }) + onFailure = { + Logger.warn("Api Client", "FAILURE Get body $baseUrl$path") + Err(ThrowableError(it)) + }) } suspend inline fun post( @@ -39,6 +55,7 @@ abstract class ApiClient(var baseUrl: String, val client: HttpClient) { path: String, baseUrl: String = this.baseUrl ): Result { + Logger.trace("Api Client", "Post with request body to $baseUrl$path ") val post = try { client.post(baseUrl + path) { @@ -52,7 +69,10 @@ abstract class ApiClient(var baseUrl: String, val client: HttpClient) { } return runCatching { post.body() }.fold( onSuccess = { Ok(it) }, - onFailure = { Err(ThrowableError(it)) }) + onFailure = { + Logger.warn("Api Client", "FAILURE Get body $baseUrl$path ") + Err(ThrowableError(it)) + }) } suspend inline fun postWithoutResponse( @@ -60,28 +80,43 @@ abstract class ApiClient(var baseUrl: String, val client: HttpClient) { path: String, baseUrl: String = this.baseUrl ): Result { + Logger.trace("Api Client", "Post without response $baseUrl$path") return runCatching { client.post(baseUrl + path) { contentType(ContentType.Application.Json) setBody(content) } - }.fold(onSuccess = Ok(), onFailure = ThrowableError()) + }.fold(onSuccess = Ok(), onFailure = { + Logger.warn("Api Client", "FAILURE Post withou response $baseUrl$path") + Err(ThrowableError(it)) + }) } suspend fun get( path: String, block: HttpRequestBuilder.() -> Unit ): Result { + Logger.trace("Api Client", "Get $baseUrl$path") return runCatching { client.get( baseUrl + path, block ) - }.fold(onSuccess = { Ok(it) }, onFailure = { Err(ThrowableError(it)) }) + }.fold(onSuccess = { Ok(it) }, onFailure = { + Logger.warn("Api Client", "FAILURE Get $baseUrl$path") + Err(ThrowableError(it)) + }) } } // todo なぜこれがここにあるのかわからないが、ここにあるのはおかしいので消す。 +@Deprecated( + "このAPIがここにあるのはおかしいので削除予定です。", ReplaceWith( + "MultiM.httpClientWithJson.config(config)", + "dev.usbharu.multim.MultiM" + ) +) fun createHttpClient(config: HttpClientConfig<*>.() -> Unit = {}): HttpClient { + Logger.warn("DEPRECATED","Deprecated API calls. This API is deprecated.") return MultiM.httpClientWithJson.config(config) } diff --git a/core/src/main/kotlin/dev/usbharu/multim/api/EmojiApi.kt b/core/src/main/kotlin/dev/usbharu/multim/api/EmojiApi.kt index d1a0a6a..1fdc3ac 100644 --- a/core/src/main/kotlin/dev/usbharu/multim/api/EmojiApi.kt +++ b/core/src/main/kotlin/dev/usbharu/multim/api/EmojiApi.kt @@ -1,6 +1,7 @@ package dev.usbharu.multim.api import com.github.michaelbull.result.Err +import dev.usbharu.multim.Logger import dev.usbharu.multim.error.ErrorType import dev.usbharu.multim.error.MultiMError import dev.usbharu.multim.error.MultiMResult @@ -14,10 +15,12 @@ interface EmojiApi { object NotImplEmojiApi : EmojiApi { override suspend fun get(name: String): MultiMResult { + Logger.debug("Emoji Api","Not impl emoji api get $name") return Err(MultiMError("emoji get not implements",null, ErrorType.NOT_IMPL)) } override suspend fun findByName(name: String): MultiMResult> { + Logger.debug("Emoji Api","Not impl emoji api findByName $name") return Err(MultiMError("emoji findByName not implements",null,ErrorType.NOT_IMPL)) } } diff --git a/core/src/main/kotlin/dev/usbharu/multim/api/NodeinfoApi.kt b/core/src/main/kotlin/dev/usbharu/multim/api/NodeinfoApi.kt index 02f8eba..954b4f8 100644 --- a/core/src/main/kotlin/dev/usbharu/multim/api/NodeinfoApi.kt +++ b/core/src/main/kotlin/dev/usbharu/multim/api/NodeinfoApi.kt @@ -1,6 +1,10 @@ package dev.usbharu.multim.api -import com.github.michaelbull.result.* +import com.github.michaelbull.result.Err +import com.github.michaelbull.result.Ok +import com.github.michaelbull.result.Result +import com.github.michaelbull.result.flatMap +import dev.usbharu.multim.Logger import dev.usbharu.multim.MultiM.json import dev.usbharu.multim.error.* import dev.usbharu.multim.model.wellknown.NodeinfoList @@ -11,7 +15,6 @@ import io.ktor.client.plugins.* import io.ktor.client.plugins.contentnegotiation.* import io.ktor.client.request.* import io.ktor.serialization.kotlinx.json.* -import kotlin.runCatching // todo well-knwonだけでパッケージ作ったほうがいいかも class NodeinfoApi(private var httpClient: HttpClient) { @@ -25,22 +28,35 @@ class NodeinfoApi(private var httpClient: HttpClient) { } suspend fun wellKnownNodeinfo(url: String): Result { + Logger.info("Nodeinfo Api", "START Get $url.well-known/nodeinfo") val get = try { httpClient.get("$url.well-known/nodeinfo") } catch (e: ServerResponseException) { + Logger.warn( + "Nodeinfo Api", + "FAILURE Server Response Exception Get $url.well-known/nodeinfo" + ) return Err( MultiMHttpError( HttpError.ServerError(e.response.status.value, e.message, e), e ) ) } catch (e: ClientRequestException) { + Logger.warn( + "Nodeinfo Api", + "FAILURE Client Request Exception Get $url.well-known/nodeinfo" + ) return Err( MultiMHttpError( HttpError.ClientError(e.response.status.value, e.message, e), e ) ) } - return runCatching { get.body() }.foldWithOk { + return runCatching { get.body() }.foldWithOk({ + Logger.info("Nodeinfo Api", "SUCCESS Get $url.well-known/nodeinfo") + Ok(it) + }) { + Logger.warn("Nodeinfo Api", "FAILURE Get body") MultiMJsonContentTransformError( it.localizedMessage ) @@ -48,9 +64,14 @@ class NodeinfoApi(private var httpClient: HttpClient) { } fun nodeinfoLink(nodeinfoList: NodeinfoList): Result { + Logger.info("Nodeinfo Api", "START Get nodeinfo link") return runCatching { nodeinfoList.links.minByOrNull { it.rel.substringAfterLast("/", "0").toFloat() }!! - }.foldWithOk { + }.foldWithOk({ + Logger.info("Nodeinfo Api","SUCCESS Get nodeinfo link") + Ok(it) + }) { + Logger.warn("Nodeinfo Api","FAILURE Get nodeinfo link") MultiMError(it.localizedMessage, it, ErrorType.API) } } diff --git a/core/src/main/kotlin/dev/usbharu/multim/api/StatusApi.kt b/core/src/main/kotlin/dev/usbharu/multim/api/StatusApi.kt index 564026b..49c9bc8 100644 --- a/core/src/main/kotlin/dev/usbharu/multim/api/StatusApi.kt +++ b/core/src/main/kotlin/dev/usbharu/multim/api/StatusApi.kt @@ -2,6 +2,7 @@ package dev.usbharu.multim.api import com.github.michaelbull.result.Err import com.github.michaelbull.result.Result +import dev.usbharu.multim.Logger import dev.usbharu.multim.error.ErrorType import dev.usbharu.multim.error.MultiMError import dev.usbharu.multim.model.* @@ -34,18 +35,22 @@ interface StatusApi { object NotImplStatusApi : StatusApi { override suspend fun post(status: StatusForPost): Result { + Logger.debug("Status Api","Not impl status api post") return Err(MultiMError("post not implements",null, ErrorType.NOT_IMPL)) } override suspend fun delete(id: StatusId): Result { + Logger.debug("Status Api","Not impl status api delete") return Err(MultiMError("delete not implements",null,ErrorType.NOT_IMPL)) } override suspend fun findById(id: StatusId): Result { + Logger.debug("Status Api","Not impl status api findById") return Err(MultiMError("findById not implements",null,ErrorType.NOT_IMPL)) } override suspend fun addReaction(id: StatusId, reaction: Reaction): Result { + Logger.debug("Status Api","Not impl status api addReaction") return Err(MultiMError("addReaction not implements",null,ErrorType.NOT_IMPL)) } @@ -53,38 +58,47 @@ object NotImplStatusApi : StatusApi { id: StatusId, reaction: Reaction? ): Result { + Logger.debug("Status Api","Not impl status api removeReaction") return Err(MultiMError("removeReaction not implements",null,ErrorType.NOT_IMPL)) } override suspend fun reactions(id: StatusId): Result, MultiMError> { + Logger.debug("Status Api","Not impl status api reactions") return Err(MultiMError("reactions not implements",null,ErrorType.NOT_IMPL)) } override suspend fun replies(id: StatusId): Result, MultiMError> { + Logger.debug("Status Api","Not impl status api replies") return Err(MultiMError("replies not implements",null,ErrorType.NOT_IMPL)) } override suspend fun repost(id: StatusId): Result { + Logger.debug("Status Api","Not impl status api repost") return Err(MultiMError("repost not implements",null,ErrorType.NOT_IMPL)) } override suspend fun unRepost(id: StatusId): Result { + Logger.debug("Status Api","Not impl status api unRepost") return Err(MultiMError("unRepost not implements",null,ErrorType.NOT_IMPL)) } override suspend fun replyTo(id: StatusId, status: StatusForPost): Result { + Logger.debug("Status Api","Not impl status api replyTo") return Err(MultiMError("replyTo not implements",null,ErrorType.NOT_IMPL)) } override suspend fun addToBookmarks(id: StatusId): Result { + Logger.debug("Status Api","Not impl status api addToBookmarks") return Err(MultiMError("addToBookmarks not implements",null,ErrorType.NOT_IMPL)) } override suspend fun removeFromBookmarks(id: StatusId): Result { + Logger.debug("Status Api","Not impl status api removeFromBookmarks") return Err(MultiMError("removeFromBookmarks not implements",null,ErrorType.NOT_IMPL)) } override suspend fun getPreviousAndNext(id: StatusId): Result { + Logger.debug("Status Api","Not impl status api getPreviousAndNext") return Err(MultiMError("getPreviousAndNext not implements",null,ErrorType.NOT_IMPL)) } } diff --git a/core/src/main/kotlin/dev/usbharu/multim/api/TimelineApi.kt b/core/src/main/kotlin/dev/usbharu/multim/api/TimelineApi.kt index 19d0a73..c79d192 100644 --- a/core/src/main/kotlin/dev/usbharu/multim/api/TimelineApi.kt +++ b/core/src/main/kotlin/dev/usbharu/multim/api/TimelineApi.kt @@ -2,6 +2,7 @@ package dev.usbharu.multim.api import com.github.michaelbull.result.Err import com.github.michaelbull.result.Result +import dev.usbharu.multim.Logger import dev.usbharu.multim.error.ErrorType import dev.usbharu.multim.error.MultiMError import dev.usbharu.multim.model.Status @@ -29,6 +30,7 @@ interface TimelineApi { object NotImplTimelineApi : TimelineApi { override suspend fun availableTimelines(): Result, MultiMError> { + Logger.debug("Timeline Api","Not impl timeline api availableTimelines") return Err(MultiMError("availableTimelines not implements",null, ErrorType.NOT_IMPL)) } @@ -36,14 +38,17 @@ object NotImplTimelineApi : TimelineApi { timeline: Timeline, callback: (List) -> Unit ): Result { + Logger.debug("Timeline Api","Not impl timeline api listen") return Err(MultiMError("timeline listen not implements",null,ErrorType.NOT_IMPL)) } override suspend fun connect(timeline: Timeline): Result { + Logger.debug("Timeline Api","Not impl timeline api connect") return Err(MultiMError("timeline connect not implements",null,ErrorType.NOT_IMPL)) } override suspend fun disconnect(timeline: Timeline, force: Boolean): Result { + Logger.debug("Timeline Api","Not impl timeline api disconnect") return Err(MultiMError("timeline disconnect not implements",null,ErrorType.NOT_IMPL)) } } 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 e7091fb..bd24e62 100644 --- a/core/src/main/kotlin/dev/usbharu/multim/error/MultiMError.kt +++ b/core/src/main/kotlin/dev/usbharu/multim/error/MultiMError.kt @@ -7,10 +7,10 @@ import io.ktor.client.plugins.* open class MultiMError( message: String, - val throwable: Throwable? = null, + val _throwable: Throwable? = null, val errorType: ErrorType ) : - Error("MultiM ${errorType.message} ERROR : $message") + ThrowableError(_throwable ?: Throwable(message),"MultiM ${errorType.message} ERROR : $message") class MultiMHttpError(val httpError: HttpError, throwable: Throwable? = httpError.throwable) : MultiMError( diff --git a/core/src/main/kotlin/dev/usbharu/multim/factory/ServiceInfoFactory.kt b/core/src/main/kotlin/dev/usbharu/multim/factory/ServiceInfoFactory.kt index 0c8b0f5..1e418ee 100644 --- a/core/src/main/kotlin/dev/usbharu/multim/factory/ServiceInfoFactory.kt +++ b/core/src/main/kotlin/dev/usbharu/multim/factory/ServiceInfoFactory.kt @@ -1,5 +1,6 @@ package dev.usbharu.multim.factory +import dev.usbharu.multim.Logger import dev.usbharu.multim.ServiceInfo import dev.usbharu.multim.api.PlatformApis import dev.usbharu.multim.model.wellknown.nodeinfo.NodeInfo @@ -26,11 +27,13 @@ class ServiceInfoFactory(private val services: List) : PlatformApiF httpClient ) ) + Logger.info("Platform Api Factory","Service Info factory found service.") return service.multiMApis( platFormApis ).apply { build(this, platFormApis) } } } + Logger.error("Platform Api Factory","Service Info factory cannot find service.") TODO("サービスが見つからなかった際のしょり") } } diff --git a/core/src/main/kotlin/dev/usbharu/multim/multi/MultiAccountAccountApi.kt b/core/src/main/kotlin/dev/usbharu/multim/multi/MultiAccountAccountApi.kt index 140db48..ba54759 100644 --- a/core/src/main/kotlin/dev/usbharu/multim/multi/MultiAccountAccountApi.kt +++ b/core/src/main/kotlin/dev/usbharu/multim/multi/MultiAccountAccountApi.kt @@ -3,6 +3,7 @@ package dev.usbharu.multim.multi import com.github.michaelbull.result.Result import com.github.michaelbull.result.flatMap import com.github.michaelbull.result.map +import dev.usbharu.multim.Logger import dev.usbharu.multim.api.AccountApi import dev.usbharu.multim.error.MultiMError import dev.usbharu.multim.model.* @@ -16,6 +17,7 @@ class MultiAccountAccountApi(private val multiAccountApiBase: MultiAccountApiBas since: StatusId?, until: StatusId? ): Result, MultiMError> { + Logger.debug("Account Api","Multi account account api userTimeline") return getImpl2(account) { userTimeline(it, since, until) } .flatMap { it.first.map { statuses -> @@ -30,19 +32,23 @@ class MultiAccountAccountApi(private val multiAccountApiBase: MultiAccountApiBas } override suspend fun follow(account: Account): Result { + Logger.debug("Account Api","Multi account account api follow") return getImpl2(account) { follow(it) }.map { it.first } } suspend fun follow(account: MultiAccountData): Result, MultiMError> { + Logger.debug("Account Api","Multi account account api follow with MultiAccountData") return getImpl(account) { follow(it) } } override suspend fun unfollow(account: Account): Result { + Logger.debug("Account Api","Multi account account api unfollow") return getImpl2(account) { unfollow(it) }.map { it.first } } override suspend fun profile(account: Account): Result { + Logger.debug("Account Api","Multi account account api profile") return getImpl2(account) { profile(it) } .flatMap { it.first.map { profile -> @@ -57,6 +63,7 @@ class MultiAccountAccountApi(private val multiAccountApiBase: MultiAccountApiBas account: Account, includeRepost: Boolean ): Result, MultiMError> { + Logger.debug("Account Api","Multi account account api statuses") return getImpl2(account) { statuses( it, @@ -78,30 +85,37 @@ class MultiAccountAccountApi(private val multiAccountApiBase: MultiAccountApiBas myself: Account, other: Account ): Result { + Logger.debug("Account Api","Multi account account api relationships") return getImpl2(myself) { relationships(it, other) }.flatMap { it.first } } override suspend fun requestCancel(account: Account): Result { + Logger.debug("Account Api","Multi account account api requestCancel") return getImpl2(account) { requestCancel(it) }.map { it.first } } override suspend fun requestAccept(account: Account): Result { + Logger.debug("Account Api","Multi account account api requestAccept") return getImpl2(account) { requestAccept(account) }.map { it.first } } override suspend fun requestReject(account: Account): Result { + Logger.debug("Account Api","Multi account account api requestReject") return getImpl2(account) { requestReject(it) }.map { it.first } } suspend fun unfollow(account: MultiAccountData): Result, MultiMError> { + Logger.debug("Account Api","Multi account account api unfollow with MultiAccountData") return getImpl(account) { unfollow(it) } } suspend fun profile(account: MultiAccountData): Result, MultiMError> { + Logger.debug("Account Api","Multi account account api profile with MultiAccountData") return getImpl(account) { profile(it) } } suspend fun statuses(account: MultiAccountData): Result>, MultiMError> { + Logger.debug("Account Api","Multi account account api status with MultiAccountData") return getImpl(account) { statuses(it) } } @@ -109,18 +123,22 @@ class MultiAccountAccountApi(private val multiAccountApiBase: MultiAccountApiBas myself: MultiAccountData, other: MultiAccountData ): Result, MultiMError> { + Logger.debug("Account Api","Multi account account api relationships with MultiAccountData") return getImpl(myself) { relationships(it, other.innerData) } } suspend fun requestCancel(account: MultiAccountData): Result, MultiMError> { + Logger.debug("Account Api","Multi account account api requestCancel with MultiAccountData") return getImpl(account) { requestCancel(it) } } suspend fun requestAccept(account: MultiAccountData): Result, MultiMError> { + Logger.debug("Account Api","Multi account account api requestAccept with MultiAccountData") return getImpl(account) { requestAccept(it) } } suspend fun requestReject(account: MultiAccountData): Result, MultiMError> { + Logger.debug("Account Api","Multi account account api requestAccept with MultiAccountData") return getImpl(account) { requestReject(it) } } diff --git a/core/src/main/kotlin/dev/usbharu/multim/multi/MultiAccountApiBase.kt b/core/src/main/kotlin/dev/usbharu/multim/multi/MultiAccountApiBase.kt index 1020f52..1b4e0c8 100644 --- a/core/src/main/kotlin/dev/usbharu/multim/multi/MultiAccountApiBase.kt +++ b/core/src/main/kotlin/dev/usbharu/multim/multi/MultiAccountApiBase.kt @@ -1,8 +1,7 @@ package dev.usbharu.multim.multi -import com.github.michaelbull.result.Result -import com.github.michaelbull.result.map -import com.github.michaelbull.result.toResultOr +import com.github.michaelbull.result.* +import dev.usbharu.multim.Logger import dev.usbharu.multim.MultiM import dev.usbharu.multim.ServiceInfo import dev.usbharu.multim.api.createHttpClient @@ -21,30 +20,57 @@ class MultiAccountApiBase(val serviceList: List) { var mainClientHashCode: Int? = null suspend fun addAccount(url: String, token: String): Result { + Logger.info("Multi Account", "START Add account url:$url token:${"*".repeat(token.length)}") + val hashCode = (url + token).hashCode() - return MultiM.createClient(url, token, factory, httpClient).map { + + Logger.debug("Multi Account", "Account hashCode : $hashCode") + + val result = MultiM.createClient(url, token, factory, httpClient).map { apiClientMap[hashCode] = it }.map { if (mainClientHashCode == null) { mainClientHashCode = hashCode + + Logger.debug("Multi Account", "Main account is null! This account is set as the main account.") + } hashCode } + result.onFailure { + Logger.error( + "Multi Account", + "FAILURE Add account url:$url token:${"*".repeat(token.length)}", + it + ) + } + result.onSuccess { + Logger.info("Multi Account", "SUCCESS Add account url:$url") + } + return result } suspend fun addMainAccount(url: String, token: String): Result { - + Logger.info("Multi Account","Add account url:$url token:${"*".repeat(token.length)} as main account.") return addAccount(url, token).map { mainClientHashCode = it;it } } - fun getImpl(hashCode: Int? = mainClientHashCode): Result { + fun getImpl(hashCode: Int? = mainClientHashCode): Result { + Logger.debug("Multi Account","Get api client impl $hashCode") if (hashCode == null) { + Logger.warn("Multi Account","HashCode is null! Use main account.") return apiClientMap[mainClientHashCode].toResultOr { - MultiMError("Main Client not found : $mainClientHashCode",null, ErrorType.ILLEGAL_ARGUMENT) + Logger.warn("Multi Account","Main account client not found!") + MultiMError( + "Main Client not found : $mainClientHashCode", + null, + ErrorType.ILLEGAL_ARGUMENT + ) } } return apiClientMap[hashCode].toResultOr { - MultiMError("Api Client not found : $hashCode",null,ErrorType.ILLEGAL_ARGUMENT) + Logger.warn("Multi Account","Api client not found. $hashCode") + MultiMError("Api Client not found : $hashCode", null, ErrorType.ILLEGAL_ARGUMENT) } } } diff --git a/core/src/main/kotlin/dev/usbharu/multim/multi/MultiAccountEmojiApi.kt b/core/src/main/kotlin/dev/usbharu/multim/multi/MultiAccountEmojiApi.kt index 17b454b..1f0a25b 100644 --- a/core/src/main/kotlin/dev/usbharu/multim/multi/MultiAccountEmojiApi.kt +++ b/core/src/main/kotlin/dev/usbharu/multim/multi/MultiAccountEmojiApi.kt @@ -3,6 +3,7 @@ package dev.usbharu.multim.multi import com.github.michaelbull.result.Result import com.github.michaelbull.result.flatMap import com.github.michaelbull.result.map +import dev.usbharu.multim.Logger import dev.usbharu.multim.api.EmojiApi import dev.usbharu.multim.error.MultiMError import dev.usbharu.multim.error.MultiMResult @@ -10,18 +11,22 @@ import dev.usbharu.multim.model.Emoji class MultiAccountEmojiApi(val multiAccountApiBase: MultiAccountApiBase) : EmojiApi { override suspend fun get(name: String): MultiMResult { + Logger.debug("Emoji Api","Multi account emoji api get $name") return getImpl2(name) { get(it) }.flatMap { it.first } } override suspend fun findByName(name: String): MultiMResult> { + Logger.debug("Emoji Api","Multi account emoji api findByName $name") return getImpl2(name) { findByName(it) }.flatMap { it.first } } suspend fun get(name: MultiAccountData): MultiMResult> { + Logger.debug("Emoji Api","Multi account emoji api get $name with MultiAccountData") return getImpl(name) { get(it) } } suspend fun findByName(name: MultiAccountData): MultiMResult>> { + Logger.debug("Emoji Api","Multi account emoji api findByName $name with MultiAccountData") return getImpl(name) { findByName(it) } } diff --git a/core/src/main/kotlin/dev/usbharu/multim/multi/MultiAccountStatusApi.kt b/core/src/main/kotlin/dev/usbharu/multim/multi/MultiAccountStatusApi.kt index 951a821..484c618 100644 --- a/core/src/main/kotlin/dev/usbharu/multim/multi/MultiAccountStatusApi.kt +++ b/core/src/main/kotlin/dev/usbharu/multim/multi/MultiAccountStatusApi.kt @@ -3,6 +3,7 @@ package dev.usbharu.multim.multi import com.github.michaelbull.result.Result import com.github.michaelbull.result.flatMap import com.github.michaelbull.result.map +import dev.usbharu.multim.Logger import dev.usbharu.multim.api.StatusApi import dev.usbharu.multim.error.MultiMError import dev.usbharu.multim.model.* @@ -10,49 +11,76 @@ import dev.usbharu.multim.multi.model.MultiAccountReaction import dev.usbharu.multim.multi.model.MultiAccountStatus class MultiAccountStatusApi(private val multiAccountApiBase: MultiAccountApiBase) : StatusApi { - suspend fun post(status: MultiAccountData): Result, MultiMError> = - getImpl(status) { post(it) } + suspend fun post(status: MultiAccountData): Result, MultiMError> { + Logger.debug("Status Api","Multi account status api post with MultiAccountData") + return getImpl(status) { post(it) } + } - suspend fun delete(id: MultiAccountData): Result, MultiMError> = - getImpl(id) { delete(it) } + suspend fun delete(id: MultiAccountData): Result, MultiMError> { + Logger.debug("Status Api","Multi account status api delete with MultiAccountData") + return getImpl(id) { delete(it) } + } - suspend fun findById(id: MultiAccountData): Result, MultiMError> = - getImpl(id) { findById(it) } + suspend fun findById(id: MultiAccountData): Result, MultiMError> { + Logger.debug("Status Api","Multi account status api findById with MultiAccountData") + return getImpl(id) { findById(it) } + } suspend fun addReaction( id: MultiAccountData, reaction: MultiAccountData - ): Result, MultiMError> = - getImpl(id) { addReaction(it, reaction.innerData) } + ): Result, MultiMError> { + Logger.debug("Status Api","Multi account status api addReaction with MultiAccountData") + return getImpl(id) { addReaction(it, reaction.innerData) } + } suspend fun removeReaction( id: MultiAccountData, reaction: MultiAccountData - ): Result, MultiMError> = - getImpl(id) { removeReaction(it, reaction.innerData) } + ): Result, MultiMError> { + Logger.debug("Status Api","Multi account status api removeReaction with MultiAccountData") + return getImpl(id) { removeReaction(it, reaction.innerData) } + } - suspend fun reactions(id: MultiAccountData): Result>, MultiMError> = - getImpl(id) { reactions(it) } + suspend fun reactions(id: MultiAccountData): Result>, MultiMError> { + Logger.debug("Status Api","Multi account status api reactions with MultiAccountData") + return getImpl(id) { reactions(it) } + } - suspend fun replies(id: MultiAccountData): Result>, MultiMError> = - getImpl(id) { replies(it) } + suspend fun replies(id: MultiAccountData): Result>, MultiMError> { + Logger.debug("Status Api","Multi account status api replies with MultiAccountData") + return getImpl(id) { replies(it) } + } - suspend fun repost(id: MultiAccountData): Result, MultiMError> = - getImpl(id) { repost(it) } + suspend fun repost(id: MultiAccountData): Result, MultiMError> { + Logger.debug("Status Api","Multi account status api repost with MultiAccountData") + return getImpl(id) { repost(it) } + } - suspend fun unRepost(id: MultiAccountData): Result, MultiMError> = - getImpl(id) { unRepost(it) } + suspend fun unRepost(id: MultiAccountData): Result, MultiMError> { + Logger.debug("Status Api","Multi account status api unRepost with MultiAccountData") + return getImpl(id) { unRepost(it) } + } suspend fun replyTo( id: MultiAccountData, status: MultiAccountData - ): Result, MultiMError> = getImpl(id) { replyTo(it, status.innerData) } + ): Result, MultiMError> { + Logger.debug("Status Api","Multi account status api replyTo with MultiAccountData") + return getImpl(id) { replyTo(it, status.innerData) } + } - suspend fun addToBookmarks(id: MultiAccountData): Result, MultiMError> = - getImpl(id) { addToBookmarks(it) } + suspend fun addToBookmarks(id: MultiAccountData): Result, MultiMError> { + Logger.debug("Status Api","Multi account status api addToBookmarks with MultiAccountData") + return getImpl(id) { addToBookmarks(it) } + } - suspend fun removeFromBookmarks(id: MultiAccountData): Result, MultiMError> = - getImpl(id) { removeFromBookmarks(it) } + suspend fun removeFromBookmarks(id: MultiAccountData): Result, MultiMError> { + Logger.debug("Status Api","Multi account status api removeFromBookmarks with MultiAccountData") + return getImpl(id) { removeFromBookmarks(it) } + } - suspend fun getPreviousAndNext(id: MultiAccountData): Result, MultiMError> = - getImpl(id) { getPreviousAndNext(it) } + suspend fun getPreviousAndNext(id: MultiAccountData): Result, MultiMError> { + Logger.debug("Status Api","Multi account status api getPreviousAndNext with MultiAccountData") + return getImpl(id) { getPreviousAndNext(it) } + } private suspend fun getImpl( apiData: MultiAccountData, callback: suspend StatusApi.(T) -> Result @@ -79,6 +107,7 @@ class MultiAccountStatusApi(private val multiAccountApiBase: MultiAccountApiBase override suspend fun post(status: StatusForPost): Result { + Logger.debug("Status Api","Multi account status api post") return getImpl2(status) { post(it) }.flatMap { it.first.map { iStatus -> (iStatus to it.second).toMultiAccount() @@ -88,24 +117,29 @@ class MultiAccountStatusApi(private val multiAccountApiBase: MultiAccountApiBase } override suspend fun delete(id: StatusId): Result { + Logger.debug("Status Api","Multi account status api delete") return getImpl2(id) { delete(it) }.map { it.first } } override suspend fun findById(id: StatusId): Result { + Logger.debug("Status Api","Multi account status api findById") return getImpl2(id) { findById(it) }.flatMap { it.first.map { iStatus -> (iStatus to it.second).toMultiAccount() } } } override suspend fun addReaction(id: StatusId, reaction: Reaction): Result { + Logger.debug("Status Api","Multi account status api addReaction") return getImpl2(id) { addReaction(it, reaction) }.map { it.first } } override suspend fun removeReaction( id: StatusId, reaction: Reaction? ): Result { + Logger.debug("Status Api","Multi account status api removeReaction") return getImpl2(id) { removeReaction(it, reaction) }.map { it.first } } override suspend fun reactions(id: StatusId): Result, MultiMError> { + Logger.debug("Status Api","Multi account status api reactions") return getImpl2(id) { reactions(it) }.let { it.flatMap { it.first.map { map -> @@ -120,6 +154,7 @@ class MultiAccountStatusApi(private val multiAccountApiBase: MultiAccountApiBase } override suspend fun replies(id: StatusId): Result, MultiMError> { + Logger.debug("Status Api","Multi account status api replies") return getImpl2(id) { replies(it) }.flatMap { it.first.map { statusList -> statusList.map { status -> @@ -132,14 +167,17 @@ class MultiAccountStatusApi(private val multiAccountApiBase: MultiAccountApiBase } override suspend fun repost(id: StatusId): Result { + Logger.debug("Status Api","Multi account status api repost") return getImpl2(id) { repost(it) }.flatMap { it.first.map { iStatus -> (iStatus to it.second).toMultiAccount() } } } override suspend fun unRepost(id: StatusId): Result { + Logger.debug("Status Api","Multi account status api unRepost") return getImpl2(id) { unRepost(it) }.map { it.first } } override suspend fun replyTo(id: StatusId, status: StatusForPost): Result { + Logger.debug("Status Api","Multi account status api replyTo") return getImpl2(status) { replyTo( id, it @@ -148,15 +186,18 @@ class MultiAccountStatusApi(private val multiAccountApiBase: MultiAccountApiBase } override suspend fun addToBookmarks(id: StatusId): Result { + Logger.debug("Status Api","Multi account status api addToBookmarks") return getImpl2(id) { addToBookmarks(it) }.map { it.first } } override suspend fun removeFromBookmarks(id: StatusId): Result { + Logger.debug("Status Api","Multi account status api removeFromBookmarks") return getImpl2(id) { removeFromBookmarks(it) }.map { it.first } } override suspend fun getPreviousAndNext(id: StatusId): Result { - TODO("Not yet implemented") + Logger.debug("Status Api","Multi account status api getPreviousAndNext") + return getImpl2(id){getPreviousAndNext(it)}.flatMap { it.first } } private fun Pair.toMultiAccount(): MultiAccountStatus { diff --git a/core/src/main/kotlin/dev/usbharu/multim/multi/MultiAccountTimelineApi.kt b/core/src/main/kotlin/dev/usbharu/multim/multi/MultiAccountTimelineApi.kt index 652bd50..64d58aa 100644 --- a/core/src/main/kotlin/dev/usbharu/multim/multi/MultiAccountTimelineApi.kt +++ b/core/src/main/kotlin/dev/usbharu/multim/multi/MultiAccountTimelineApi.kt @@ -3,6 +3,7 @@ package dev.usbharu.multim.multi import com.github.michaelbull.result.Result import com.github.michaelbull.result.flatMap import com.github.michaelbull.result.map +import dev.usbharu.multim.Logger import dev.usbharu.multim.api.TimelineApi import dev.usbharu.multim.error.MultiMError import dev.usbharu.multim.model.Status @@ -12,10 +13,12 @@ import dev.usbharu.multim.multi.model.MultiAccountStatus class MultiAccountTimelineApi(private val multiAccountApiBase: MultiAccountApiBase) : TimelineApi { suspend fun availableTimelines(id: MultiAccountData<*>): Result>, MultiMError> { + Logger.debug("Timeline Api","Multi account timeline api availableTimelines with MultiAccountData") return getImpl(id) { availableTimelines() } } suspend fun availableTimelines(hashCode: Int): Result>, MultiMError> { + Logger.debug("Timeline Api","Multi account timeline api availableTimelines") return multiAccountApiBase.getImpl(hashCode) .flatMap { it.timelineApi.availableTimelines() } .map { MultiAccountDataImpl(it, hashCode) } @@ -26,11 +29,12 @@ class MultiAccountTimelineApi(private val multiAccountApiBase: MultiAccountApiBa timeline: MultiAccountData, callback: MultiAccountData<(List) -> Unit> ): Result, MultiMError> { - + Logger.debug("Timeline Api","Multi account timeline api listen with MultiAccountData") return getImpl(timeline) { listen(it, callback.innerData as (List) -> Unit) } } suspend fun connect(timeline: MultiAccountData): Result, MultiMError> { + Logger.debug("Timeline Api","Multi account timeline api connect with MultiAccountData") return getImpl(timeline) { connect(it) } } @@ -38,6 +42,7 @@ class MultiAccountTimelineApi(private val multiAccountApiBase: MultiAccountApiBa timeline: MultiAccountData, force: Boolean = false ): Result, MultiMError> { + Logger.debug("Timeline Api","Multi account timeline api disconnect with MultiAccountData") return getImpl(timeline) { disconnect(it, force) } } @@ -64,11 +69,13 @@ class MultiAccountTimelineApi(private val multiAccountApiBase: MultiAccountApiBa } private fun timelineApi(id: T): Result { + Logger.debug("Timeline Api","Multi account timeline api timelineApi with MultiAccountData") return multiAccountApiBase.getImpl((id as? MultiAccountData<*>)?.hashCode) .map { it.timelineApi } } override suspend fun availableTimelines(): Result, MultiMError> { + Logger.debug("Timeline Api","Multi account timeline api availableTimelines") TODO("Not yet implemented") } @@ -76,14 +83,17 @@ class MultiAccountTimelineApi(private val multiAccountApiBase: MultiAccountApiBa timeline: Timeline, callback: (List) -> Unit ): Result { + Logger.debug("Timeline Api","Multi account timeline api listen") return getImpl2(timeline) { listen(it, callback) }.map { it.first } } override suspend fun connect(timeline: Timeline): Result { + Logger.debug("Timeline Api","Multi account timeline api connect") return getImpl2(timeline) { connect(it) }.map { it.first } } override suspend fun disconnect(timeline: Timeline, force: Boolean): Result { + Logger.debug("Timeline Api","Multi account timeline api disconnect") return getImpl2(timeline) { disconnect(it, force) }.map { it.first } } diff --git a/impl/misskey/src/test/kotlin/dev/usbharu/multim/v12/api/NotesTest.kt b/impl/misskey/src/test/kotlin/dev/usbharu/multim/v12/api/NotesTest.kt index 792b4f2..1e36803 100644 --- a/impl/misskey/src/test/kotlin/dev/usbharu/multim/v12/api/NotesTest.kt +++ b/impl/misskey/src/test/kotlin/dev/usbharu/multim/v12/api/NotesTest.kt @@ -268,7 +268,7 @@ class NotesTestE2E { ) val deleteNote = when (create) { is Ok -> create.value.createdNote.id - is Err -> fail(create.error.message, create.error.throwable) + is Err -> fail(create.error.message, create.error._throwable) } notes.delete(NotesDeleteRequest(deleteNote)) assertInstanceOf(Err::class.java,notes.show(NotesShowRequest(deleteNote))) @@ -319,7 +319,7 @@ class NotesTestE2E { val create = when (result) { is Ok -> result.value - is Err -> fail(result.error.message, result.error.throwable) + is Err -> fail(result.error.message, result.error._throwable) } notes.Favorites().create(NotesFavoritesCreateRequest(create.createdNote.id)) assertTrue(notes.state(NotesStateRequest(create.createdNote.id)).get()?.isFavorited == true)