diff --git a/gradle.properties b/gradle.properties index 1d02577..1e4944c 100644 --- a/gradle.properties +++ b/gradle.properties @@ -5,7 +5,7 @@ MORNY_ARCHIVE_NAME = morny-coeur MORNY_CODE_STORE = https://github.com/Eyre-S/Coeur-Morny-Cono MORNY_COMMIT_PATH = https://github.com/Eyre-S/Coeur-Morny-Cono/commit/%s -VERSION = 1.3.0-dev8 +VERSION = 1.3.0-dev9 USE_DELTA = false VERSION_DELTA = diff --git a/src/main/scala/cc/sukazyo/cono/morny/MornyCoeur.scala b/src/main/scala/cc/sukazyo/cono/morny/MornyCoeur.scala index f88d9b4..3f3f2d4 100644 --- a/src/main/scala/cc/sukazyo/cono/morny/MornyCoeur.scala +++ b/src/main/scala/cc/sukazyo/cono/morny/MornyCoeur.scala @@ -99,6 +99,14 @@ class MornyCoeur (using val config: MornyConfig) { import com.pengrad.telegrambot.TelegramException account.setUpdatesListener(eventManager, (e: TelegramException) => { + // This function intended to catch exceptions on update + // fetching controlled by Telegram API Client. So that + // it won't be directly printed to STDOUT without Morny's + // logger. And it can be reported when needed. + // TelegramException can either contains a caused that infers + // a lower level client exception (network err or others); + // nor contains a response that means API request failed. + if (e.response != null) { import com.google.gson.GsonBuilder logger error @@ -106,6 +114,7 @@ class MornyCoeur (using val config: MornyConfig) { | server responses: |${GsonBuilder().setPrettyPrinting().create.toJson(e.response) indent 4} |""".stripMargin + this.daemons.reporter.exception(e, "Failed get updates.") } if (e.getCause != null) { @@ -119,15 +128,17 @@ class MornyCoeur (using val config: MornyConfig) { import scala.collection.mutable val log = mutable.ArrayBuffer(s"Failed get updates: Network Error") var current: Throwable = e_timeout - log += s" due to: ${current.getMessage}" + log += s" due to: ${current.getClass.getSimpleName}: ${current.getMessage}" while (current.getCause != null) { current = current.getCause log += s" caused by: ${current.getClass.getSimpleName}: ${current.getMessage}" } logger error Message(log mkString "\n") case e_other => - logger error exceptionLog(e_other) - this.daemons.reporter exception e_other + logger error + s"""Failed get updates: + |${exceptionLog(e_other) indent 3}""".stripMargin + this.daemons.reporter.exception(e_other, "Failed get updates.") } }) diff --git a/src/main/scala/cc/sukazyo/cono/morny/daemon/MornyReport.scala b/src/main/scala/cc/sukazyo/cono/morny/daemon/MornyReport.scala index 307401a..2ede970 100644 --- a/src/main/scala/cc/sukazyo/cono/morny/daemon/MornyReport.scala +++ b/src/main/scala/cc/sukazyo/cono/morny/daemon/MornyReport.scala @@ -19,6 +19,7 @@ import com.pengrad.telegrambot.model.request.ParseMode import com.pengrad.telegrambot.model.User import com.pengrad.telegrambot.request.{BaseRequest, SendMessage} import com.pengrad.telegrambot.response.BaseResponse +import com.pengrad.telegrambot.TelegramException import java.time.ZoneId @@ -32,13 +33,20 @@ class MornyReport (using coeur: MornyCoeur) { if !enabled then return; try { coeur.account exec report - } catch case e: EventRuntimeException.ActionFailed => { - logger warn - s"""cannot execute report to telegram: - |${exceptionLog(e) indent 4} - | tg-api response: - |${(e.response toString) indent 4}""" - .stripMargin + } catch case e: EventRuntimeException => { + import EventRuntimeException.* + e match + case e: ActionFailed => + logger warn + s"""cannot execute report to telegram: + |${exceptionLog(e) indent 4} + | tg-api response: + |${(e.response toString) indent 4}""".stripMargin + case e: ClientFailed => + logger error + s"""failed when report to telegram: + |${exceptionLog(e.getCause) indent 4} + |""".stripMargin } } @@ -48,6 +56,10 @@ class MornyReport (using coeur: MornyCoeur) { // language=html "\n\ntg-api error:\n
%s
" .formatted(GsonBuilder().setPrettyPrinting().create.toJson(api.response)) + case tgErr: TelegramException if tgErr.response != null => + // language=html + "\n\ntg-api error:\n
%s
" + .formatted(GsonBuilder().setPrettyPrinting().create.toJson(tgErr.response)) case _ => "" executeReport(SendMessage( coeur.config.reportToChat, diff --git a/src/main/scala/cc/sukazyo/cono/morny/util/tgapi/TelegramExtensions.scala b/src/main/scala/cc/sukazyo/cono/morny/util/tgapi/TelegramExtensions.scala index 5e38eeb..f066792 100644 --- a/src/main/scala/cc/sukazyo/cono/morny/util/tgapi/TelegramExtensions.scala +++ b/src/main/scala/cc/sukazyo/cono/morny/util/tgapi/TelegramExtensions.scala @@ -12,13 +12,17 @@ object TelegramExtensions { object Bot { extension (bot: TelegramBot) { + @throws[EventRuntimeException] def exec [T <: BaseRequest[T, R], R <: BaseResponse] (request: T, onError_message: String = ""): R = { - val response = bot execute request - if response isOk then return response - throw EventRuntimeException.ActionFailed( - if onError_message isEmpty then response.errorCode toString else onError_message, - response - ) + try { + val response = bot execute request + if response isOk then return response + throw EventRuntimeException.ActionFailed( + if onError_message isEmpty then response.errorCode toString else onError_message, + response + ) + } catch case e: RuntimeException => + throw EventRuntimeException.ClientFailed(e) } }} diff --git a/src/main/scala/cc/sukazyo/cono/morny/util/tgapi/event/EventRuntimeException.scala b/src/main/scala/cc/sukazyo/cono/morny/util/tgapi/event/EventRuntimeException.scala index b44e7be..dfc3e86 100644 --- a/src/main/scala/cc/sukazyo/cono/morny/util/tgapi/event/EventRuntimeException.scala +++ b/src/main/scala/cc/sukazyo/cono/morny/util/tgapi/event/EventRuntimeException.scala @@ -2,8 +2,26 @@ package cc.sukazyo.cono.morny.util.tgapi.event import com.pengrad.telegrambot.response.BaseResponse -class EventRuntimeException (message: String) extends RuntimeException(message) +/** All possible exception when do Telegram Request. + * + * Contains following detailed exceptions: + * - [[EventRuntimeException.ClientFailed]] + * - [[EventRuntimeException.ActionFailed]] + */ +abstract class EventRuntimeException (message: String) extends RuntimeException(message) object EventRuntimeException { + /** Telegram API request failed due to the response code is not 200 OK. + * @param response Raw API response object. + */ class ActionFailed (message: String, val response: BaseResponse) extends EventRuntimeException(message) + /** Client exception occurred when sending request. + * + * It may be some network exception, or parsing API response exception. + * + * The client exception is stored in [[getCause]]. + */ + class ClientFailed (caused: Exception) extends EventRuntimeException("API client failed.") { + this.initCause(caused) + } }