diff --git a/horta.properties.example b/horta.properties.example index 6a9c87f..3fe1107 100644 --- a/horta.properties.example +++ b/horta.properties.example @@ -32,4 +32,6 @@ twitter.auth.consumerSecret=aa twitter.auth.token=aa twitter.auth.tokenSecret=aa +pet.rooms=room1,room3 + loglist.url = https://loglist.net diff --git a/src/main/scala/ru/org/codingteam/horta/configuration/Configuration.scala b/src/main/scala/ru/org/codingteam/horta/configuration/Configuration.scala index 0162141..84f6acc 100644 --- a/src/main/scala/ru/org/codingteam/horta/configuration/Configuration.scala +++ b/src/main/scala/ru/org/codingteam/horta/configuration/Configuration.scala @@ -46,15 +46,15 @@ object Configuration { lazy val dftMessage = properties.getProperty("message") lazy val roomIds = Option(properties.getProperty("rooms")).map(_.split(",")).getOrElse(Array()) - lazy val roomDescriptors = roomIds map { - case rid => RoomDescriptor( + lazy val roomDescriptors = roomIds.map({ + case rid => (rid, RoomDescriptor( rid, properties.getProperty(rid + ".room"), LocaleDefinition(properties.getProperty(rid + ".locale", defaultLocalization.name)), properties.getProperty(rid + ".nickname", dftName), properties.getProperty(rid + ".message", dftMessage), - properties.getProperty(rid + ".events", "")) - } + properties.getProperty(rid + ".events", ""))) + }).toMap lazy val markovMessagesPerMinute = properties.getProperty("markov_messages_per_minute", "5").toInt lazy val markovMessageWordLimit = properties.getProperty("markov_message_word_limit", "30").toInt @@ -67,6 +67,9 @@ object Configuration { lazy val loglistUrl = properties.getProperty("loglist.url", "https://loglist.net") + lazy val petRoomNames = properties.getProperty("pet.rooms", "").split(',').map(_.trim) + lazy val petRoomIds = petRoomNames.map(roomDescriptors).map(_.room).toSet + def apply(key: String): String = { properties.getProperty(key) } diff --git a/src/main/scala/ru/org/codingteam/horta/plugins/TwitterPlugin.scala b/src/main/scala/ru/org/codingteam/horta/plugins/TwitterPlugin.scala index dadbc21..fa8a514 100644 --- a/src/main/scala/ru/org/codingteam/horta/plugins/TwitterPlugin.scala +++ b/src/main/scala/ru/org/codingteam/horta/plugins/TwitterPlugin.scala @@ -56,7 +56,7 @@ class TwitterPlugin extends EventProcessor with RoomProcessor with ActorLogging * @param actor actor representing the room. */ override protected def processRoomJoin(time: DateTime, roomJID: String, actor: ActorRef): Unit = { - Configuration.roomDescriptors find { rd => roomJID.equals(rd.room) } filter { + Configuration.roomDescriptors.values find { rd => roomJID.equals(rd.room) } filter { _.isEventEnabled("twitter") } match { case Some(_) => diff --git a/src/main/scala/ru/org/codingteam/horta/plugins/markov/MarkovPlugin.scala b/src/main/scala/ru/org/codingteam/horta/plugins/markov/MarkovPlugin.scala index e603eb4..23c7d08 100644 --- a/src/main/scala/ru/org/codingteam/horta/plugins/markov/MarkovPlugin.scala +++ b/src/main/scala/ru/org/codingteam/horta/plugins/markov/MarkovPlugin.scala @@ -69,7 +69,7 @@ class MarkovPlugin() extends BasePlugin } def isMyself(credential: Credential): Boolean = { - (Configuration.roomDescriptors find { rd => rd.room == credential.roomId.getOrElse("") } map { rd => rd.nickname } getOrElse (Configuration.dftName)) == credential.name + (Configuration.roomDescriptors.values find { rd => rd.room == credential.roomId.getOrElse("") } map { rd => rd.nickname } getOrElse (Configuration.dftName)) == credential.name } def generatePhrase(credential: Credential, arguments: Array[String]) { diff --git a/src/main/scala/ru/org/codingteam/horta/plugins/pet/PetPlugin.scala b/src/main/scala/ru/org/codingteam/horta/plugins/pet/PetPlugin.scala index 7028cd5..9f84415 100644 --- a/src/main/scala/ru/org/codingteam/horta/plugins/pet/PetPlugin.scala +++ b/src/main/scala/ru/org/codingteam/horta/plugins/pet/PetPlugin.scala @@ -4,6 +4,7 @@ import akka.actor.{ActorRef, Props} import akka.pattern.ask import akka.util.Timeout import org.joda.time.DateTime +import ru.org.codingteam.horta.configuration.Configuration import ru.org.codingteam.horta.localization.Localization import ru.org.codingteam.horta.plugins._ import ru.org.codingteam.horta.plugins.pet.commands._ @@ -58,24 +59,26 @@ class PetPlugin extends BasePlugin with CommandProcessor with RoomProcessor with credential.roomId match { case Some(room) => - val pet = initializePet(room, location) - - // (isPrivate, text): - val responseF: Future[(Boolean, String)] = arguments match { - case Array(PetCommandMatcher(command), args@_*) => - (pet ? Pet.ExecuteCommand(command, credential, args.toArray)).mapTo[String].map(s => (false, s)) - case Array("transactions") => - withDatabase(_.readTransactions(credential.roomId.get, credential.name)) map { case transactions => - (true, transactions.mkString("\n")) + initializePet(room, location) match { + case Some(pet) => + // (isPrivate, text): + val responseF: Future[(Boolean, String)] = arguments match { + case Array(PetCommandMatcher(command), args@_*) => + (pet ? Pet.ExecuteCommand(command, credential, args.toArray)).mapTo[String].map(s => (false, s)) + case Array("transactions") => + withDatabase(_.readTransactions(credential.roomId.get, credential.name)) map { case transactions => + (true, transactions.mkString("\n")) + } + case _ => Future.successful((false, Localization.localize("Try $pet help.")(credential))) } - case _ => Future.successful((false, Localization.localize("Try $pet help.")(credential))) - } - for (response <- responseF) { - response match { - case (true, message) => Protocol.sendPrivateResponse(location, credential, message) - case (false, message) => Protocol.sendResponse(location, credential, message) - } + for (response <- responseF) { + response match { + case (true, message) => Protocol.sendPrivateResponse(location, credential, message) + case (false, message) => Protocol.sendResponse(location, credential, message) + } + } + case None => } case None => } @@ -94,16 +97,19 @@ class PetPlugin extends BasePlugin with CommandProcessor with RoomProcessor with } } - private def initializePet(roomId: String, location: ActorRef): ActorRef = { - pets.get(roomId) match { - case Some(actor) => actor - case None => - val actor = context.actorOf(Props(classOf[Pet], roomId, location)) - pets = pets.updated(roomId, actor) - actor + private def initializePet(roomId: String, location: ActorRef): Option[ActorRef] = { + if (!Configuration.petRoomIds.contains(roomId)) { + None + } else { + pets.get(roomId) match { + case Some(actor) => Some(actor) + case None => + val actor = context.actorOf(Props(classOf[Pet], roomId, location)) + pets = pets.updated(roomId, actor) + Some(actor) + } } } - } object PetPlugin { diff --git a/src/main/scala/ru/org/codingteam/horta/protocol/jabber/JabberProtocol.scala b/src/main/scala/ru/org/codingteam/horta/protocol/jabber/JabberProtocol.scala index 6410d86..4caae8d 100644 --- a/src/main/scala/ru/org/codingteam/horta/protocol/jabber/JabberProtocol.scala +++ b/src/main/scala/ru/org/codingteam/horta/protocol/jabber/JabberProtocol.scala @@ -166,7 +166,7 @@ class JabberProtocol() extends Actor with ActorLogging { connection.login(Configuration.login, Configuration.password) log.info("Login succeed") - Configuration.roomDescriptors foreach { + Configuration.roomDescriptors.values foreach { case rd => if (rd.room != null) self ! JoinRoom(rd.room, rd.locale, rd.nickname, Option(rd.message)) else log.warning(s"No JID given for room ${rd.id}") diff --git a/src/test/scala/ru/org/codingteam/horta/plugins/pet/PetPluginSpec.scala b/src/test/scala/ru/org/codingteam/horta/plugins/pet/PetPluginSpec.scala new file mode 100644 index 0000000..e74bc59 --- /dev/null +++ b/src/test/scala/ru/org/codingteam/horta/plugins/pet/PetPluginSpec.scala @@ -0,0 +1,26 @@ +package ru.org.codingteam.horta.plugins.pet + +import akka.testkit.TestActorRef +import ru.org.codingteam.horta.core.Clock +import ru.org.codingteam.horta.test.TestKitSpec + +class PetPluginSpec extends TestKitSpec { + + def createPlugin() = TestActorRef[PetPlugin].underlyingActor + + "PetPlugin" should { + "create a pet for room included in config" in { + val plugin = createPlugin() + val room = "bar@example.com" + plugin.processRoomJoin(Clock.now, room, testActor) + plugin.pets should contain key room + } + + "not create a pet for room excluded from config" in { + val plugin = createPlugin() + val room = "baz@example.com" + plugin.processRoomJoin(Clock.now, room, testActor) + plugin.pets shouldNot contain key room + } + } +} diff --git a/src/test/scala/ru/org/codingteam/horta/test/TestKitSpec.scala b/src/test/scala/ru/org/codingteam/horta/test/TestKitSpec.scala index ecca651..cb5e350 100644 --- a/src/test/scala/ru/org/codingteam/horta/test/TestKitSpec.scala +++ b/src/test/scala/ru/org/codingteam/horta/test/TestKitSpec.scala @@ -20,11 +20,11 @@ abstract class TestKitSpec extends TestKit(ActorSystem("TestSystem", ConfigFacto |akka.actor.deployment { |} """.stripMargin))) -with ImplicitSender -with WordSpecLike -with Matchers -with OptionValues -with Eventually { + with ImplicitSender + with WordSpecLike + with Matchers + with OptionValues + with Eventually { implicit val timeout = Timeout(15.seconds) Configuration.initialize( @@ -32,7 +32,14 @@ with Eventually { |storage.url=jdbc:h2:hell_test;DB_CLOSE_DELAY=-1 |storage.user=sa |storage.password= - |""".stripMargin) + | + |rooms=room1,room2,room3 + |room1.room=foo@example.com + |room2.room=bar@example.com + |room3.room=baz@example.com + | + |pet.rooms=room1,room2 + """.stripMargin) val pluginProps = List[Props]() val core = system.actorOf(Props(new Core(List(Props[LogPlugin]), List())), "core")