Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
94 changes: 94 additions & 0 deletions core/src/main/kotlin/dev/usbharu/multim/Logger.kt
Original file line number Diff line number Diff line change
@@ -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)
}
}
}
37 changes: 29 additions & 8 deletions core/src/main/kotlin/dev/usbharu/multim/MultiM.kt
Original file line number Diff line number Diff line change
@@ -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

Expand All @@ -34,37 +35,57 @@ object MultiM {
token: String,
factory: PlatformApiFactory,
httpClient: HttpClient = httpClientWithJson
): Result<MultiMApis,MultiMError> {
): Result<MultiMApis, MultiMError> {
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<ServiceInfo> = 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 {
isLenient = true
ignoreUnknownKeys = true
}

val httpClient = HttpClient(CIO){
val httpClient = HttpClient(CIO) {
expectSuccess = true
}

val httpClientWithLogger = httpClient.config {
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
}
}

val httpClientWithJson = httpClientWithLogger.config {
install(ContentNegotiation){
install(ContentNegotiation) {
json(json)
}
}
Expand Down
10 changes: 10 additions & 0 deletions core/src/main/kotlin/dev/usbharu/multim/api/AccountApi.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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.*
Expand Down Expand Up @@ -31,44 +32,53 @@ object NotImplAccountApi : AccountApi {
since: StatusId?,
until: StatusId?
): Result<List<Status>, 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<Unit, MultiMError> {
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<Unit, MultiMError> {
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<Profile, MultiMError> {
Logger.debug("Account Api","Not impl account api. profile.")
return Err(MultiMError("profile not implements",null,ErrorType.NOT_IMPL))
}

override suspend fun statuses(
account: Account,
includeRepost: Boolean
): Result<List<Status>, MultiMError> {
Logger.debug("Account Api","Not impl account api. statuses.")
return Err(MultiMError("statuses not implements",null,ErrorType.NOT_IMPL))
}

override suspend fun relationships(
myself: Account,
other: Account
): Result<Relation, MultiMError> {
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<Unit, MultiMError> {
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<Unit, MultiMError> {
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<Unit, MultiMError> {
Logger.debug("Account Api","Not impl account api. requestReject.")
return Err(MultiMError("requestReject not implements",null,ErrorType.NOT_IMPL))
}
}
45 changes: 40 additions & 5 deletions core/src/main/kotlin/dev/usbharu/multim/api/ApiClient.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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.*
Expand All @@ -22,23 +26,36 @@ abstract class ApiClient(var baseUrl: String, val client: HttpClient) {
path: String,
baseUrl: String = this.baseUrl
): Result<R, ThrowableError> {
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<R> { 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 <reified T, reified R> post(
content: T,
path: String,
baseUrl: String = this.baseUrl
): Result<R, ThrowableError> {
Logger.trace("Api Client", "Post with request body to $baseUrl$path ")
val post =
try {
client.post(baseUrl + path) {
Expand All @@ -52,36 +69,54 @@ abstract class ApiClient(var baseUrl: String, val client: HttpClient) {
}
return runCatching<R> { 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 <reified T> postWithoutResponse(
content: T,
path: String,
baseUrl: String = this.baseUrl
): Result<Unit, ThrowableError> {
Logger.trace("Api Client", "Post without response $baseUrl$path")
return runCatching<Unit> {
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<HttpResponse, ThrowableError> {
Logger.trace("Api Client", "Get $baseUrl$path")
return runCatching<HttpResponse> {
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)
}
3 changes: 3 additions & 0 deletions core/src/main/kotlin/dev/usbharu/multim/api/EmojiApi.kt
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -14,10 +15,12 @@ interface EmojiApi {

object NotImplEmojiApi : EmojiApi {
override suspend fun get(name: String): MultiMResult<Emoji> {
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<List<Emoji>> {
Logger.debug("Emoji Api","Not impl emoji api findByName $name")
return Err(MultiMError("emoji findByName not implements",null,ErrorType.NOT_IMPL))
}
}
Loading