diff --git a/src/main/scala/org/codeoverflow/chatoverflow/requirement/service/twitch/chat/TwitchChatConnectListener.scala b/src/main/scala/org/codeoverflow/chatoverflow/requirement/service/twitch/chat/TwitchChatConnectListener.scala new file mode 100644 index 00000000..e3a74bfa --- /dev/null +++ b/src/main/scala/org/codeoverflow/chatoverflow/requirement/service/twitch/chat/TwitchChatConnectListener.scala @@ -0,0 +1,25 @@ +package org.codeoverflow.chatoverflow.requirement.service.twitch.chat + +import org.pircbotx.hooks.events.{ConnectAttemptFailedEvent, ConnectEvent, NoticeEvent} +import org.pircbotx.hooks.{Event, ListenerAdapter} + +/** + * Handles connection events for the TwitchChatConnector. + * Calls the callback function once the bot connected and reports connection errors. + * @param fn the callback which will be called once suitable event has been received. + * The first param informs whether the connection could be established successfully + * and the second param includes a error description if something has gone wrong. + */ +class TwitchChatConnectListener(fn: (Boolean, String) => Unit) extends ListenerAdapter { + override def onEvent(event: Event): Unit = { + event match { + case _: ConnectEvent => fn(true, "") + case e: ConnectAttemptFailedEvent => fn(false, "couldn't connect to irc chat server") + case e: NoticeEvent => + if (e.getNotice.contains("authentication failed")) { + fn(false, "authentication failed") + } + case _ => + } + } +} diff --git a/src/main/scala/org/codeoverflow/chatoverflow/requirement/service/twitch/chat/TwitchChatConnector.scala b/src/main/scala/org/codeoverflow/chatoverflow/requirement/service/twitch/chat/TwitchChatConnector.scala index 3ee7107f..ebd1fb06 100644 --- a/src/main/scala/org/codeoverflow/chatoverflow/requirement/service/twitch/chat/TwitchChatConnector.scala +++ b/src/main/scala/org/codeoverflow/chatoverflow/requirement/service/twitch/chat/TwitchChatConnector.scala @@ -15,10 +15,12 @@ import scala.collection.mutable.ListBuffer */ class TwitchChatConnector(override val sourceIdentifier: String) extends Connector(sourceIdentifier) with WithLogger { private val twitchChatListener = new TwitchChatListener + private val connectionListener = new TwitchChatConnectListener(onConnect) private val oauthKey = "oauth" override protected var requiredCredentialKeys: List[String] = List(oauthKey) override protected var optionalCredentialKeys: List[String] = List() private var bot: PircBotX = _ + private var status: Option[(Boolean, String)] = None private val channels = ListBuffer[String]() def addMessageEventListener(listener: MessageEvent => Unit): Unit = { @@ -63,6 +65,7 @@ class TwitchChatConnector(override val sourceIdentifier: String) extends Connect .setName(credentials.get.credentialsIdentifier) .setServerPassword(password.getOrElse("")) .addListener(twitchChatListener) + .addListener(connectionListener) .buildConfiguration() } else { logger error "No credentials set!" @@ -71,33 +74,47 @@ class TwitchChatConnector(override val sourceIdentifier: String) extends Connect } + /** + * Gets called by the TwitchChatConnectListener when the bot has connected. + * Saves the passed information into the status variable. + */ + private def onConnect(success: Boolean, msg: String): Unit = { + status.synchronized { + // tell the thread which starts the connector that the status has been reported + status.notify() + status = Some((success, msg)) + } + } + /** * Starts the connector, e.g. creates a connection with its platform. */ override def start(): Boolean = { bot = new PircBotX(getConfig) startBot() - true } - private def startBot(): Unit = { - - var errorCount = 0 - + private def startBot(): Boolean = { new Thread(() => { bot.startBot() }).start() - while (bot.getState != PircBotX.State.CONNECTED && errorCount < 30) { - logger info "Waiting while the bot is connecting..." - Thread.sleep(100) - errorCount += 1 + logger info "Waiting while the bot is connecting and logging in..." + status.synchronized { + status.wait(10000) + } + + if (status.isEmpty) { + logger error "Bot couldn't connect within timeout of 10 seconds." + return false } - if (errorCount >= 30) { - logger error "Fatal. Unable to start bot." + val (success, msg) = status.get + if (!success) { + logger error s"Bot couldn't connect. Reason: $msg." } + success } /** @@ -106,6 +123,8 @@ class TwitchChatConnector(override val sourceIdentifier: String) extends Connect override def stop(): Boolean = { bot.sendIRC().quitServer() bot.close() + status = None + channels.clear() true } }