mirror of
https://github.com/dyrkin/luxmed-bot.git
synced 2025-12-31 01:57:28 +01:00
Use "conversation fsm" for book and chat actors
This commit is contained in:
@@ -34,7 +34,9 @@ import com.lbs.server.service.DataService
|
||||
|
||||
class Account(val userId: UserId, bot: Bot, dataService: DataService, val localization: Localization, router: ActorRef) extends Conversation[Unit] with Localizable {
|
||||
|
||||
def askAction: QA =
|
||||
entryPoint(askAction)
|
||||
|
||||
def askAction: Step =
|
||||
question { _ =>
|
||||
val credentials = dataService.getUserCredentials(userId.userId)
|
||||
val currentAccount = credentials.find(c => c.accountId == userId.accountId).getOrElse(sys.error("Can't determine current account"))
|
||||
@@ -68,8 +70,6 @@ class Account(val userId: UserId, bot: Bot, dataService: DataService, val locali
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
entryPoint(askAction)
|
||||
}
|
||||
|
||||
object Account {
|
||||
|
||||
@@ -26,8 +26,8 @@ package com.lbs.server.actor
|
||||
import akka.actor.{Actor, ActorRef, PoisonPill, Props}
|
||||
import com.lbs.bot.model.{Command, MessageSource}
|
||||
import com.lbs.common.Logger
|
||||
import com.lbs.server.actor.Chat.Init
|
||||
import com.lbs.server.actor.Login.{LoggedIn, UserId}
|
||||
import com.lbs.server.actor.conversation.Conversation.{InitConversation, StartConversation}
|
||||
import com.lbs.server.service.DataService
|
||||
import com.lbs.server.util.MessageExtractors._
|
||||
|
||||
@@ -47,7 +47,8 @@ class Auth(val source: MessageSource, dataService: DataService, unauthorizedHelp
|
||||
unauthorizedHelpActor ! cmd
|
||||
case cmd@Command(_, Text("/login"), _) =>
|
||||
userId = None
|
||||
loginActor ! Init
|
||||
loginActor ! InitConversation
|
||||
loginActor ! StartConversation
|
||||
loginActor ! cmd
|
||||
case cmd: Command if userId.isEmpty =>
|
||||
loginActor ! cmd
|
||||
|
||||
@@ -30,170 +30,153 @@ import com.lbs.api.json.model._
|
||||
import com.lbs.bot._
|
||||
import com.lbs.bot.model.{Button, Command}
|
||||
import com.lbs.server.actor.Book._
|
||||
import com.lbs.server.actor.Chat.Init
|
||||
import com.lbs.server.actor.DatePicker.{DateFromMode, DateToMode}
|
||||
import com.lbs.server.actor.Login.UserId
|
||||
import com.lbs.server.actor.StaticData.StaticDataConfig
|
||||
import com.lbs.server.actor.conversation.Conversation
|
||||
import com.lbs.server.actor.conversation.Conversation.{InitConversation, StartConversation}
|
||||
import com.lbs.server.lang.{Localizable, Localization}
|
||||
import com.lbs.server.repository.model.Monitoring
|
||||
import com.lbs.server.service.{ApiService, DataService, MonitoringService}
|
||||
import com.lbs.server.util.ServerModelConverters._
|
||||
|
||||
import scala.util.{Failure, Success, Try}
|
||||
|
||||
class Book(val userId: UserId, bot: Bot, apiService: ApiService, dataService: DataService, monitoringService: MonitoringService,
|
||||
val localization: Localization, datePickerActorFactory: ByUserIdWithOriginatorActorFactory, staticDataActorFactory: ByUserIdWithOriginatorActorFactory,
|
||||
termsPagerActorFactory: ByUserIdWithOriginatorActorFactory) extends SafeFSM[FSMState, FSMData] with StaticDataForBooking with Localizable {
|
||||
termsPagerActorFactory: ByUserIdWithOriginatorActorFactory) extends Conversation[BookingData] with StaticDataForBooking with Localizable {
|
||||
|
||||
private val datePicker = datePickerActorFactory(userId, self)
|
||||
protected val staticData = staticDataActorFactory(userId, self)
|
||||
private[actor] val staticData = staticDataActorFactory(userId, self)
|
||||
private val termsPager = termsPagerActorFactory(userId, self)
|
||||
|
||||
startWith(RequestCity, BookingData())
|
||||
entryPoint(askCity, BookingData())
|
||||
|
||||
requestStaticData(RequestCity, AwaitCity, cityConfig) { bd: BookingData =>
|
||||
withFunctions(
|
||||
latestOptions = dataService.getLatestCities(userId.accountId),
|
||||
staticOptions = apiService.getAllCities(userId.accountId),
|
||||
applyId = id => bd.copy(cityId = id))
|
||||
}(requestNext = RequestClinic)
|
||||
private def askCity: Step =
|
||||
staticData(cityConfig) { bd: BookingData =>
|
||||
withFunctions(
|
||||
latestOptions = dataService.getLatestCities(userId.accountId),
|
||||
staticOptions = apiService.getAllCities(userId.accountId),
|
||||
applyId = id => bd.copy(cityId = id))
|
||||
}(requestNext = askClinic)
|
||||
|
||||
requestStaticData(RequestClinic, AwaitClinic, clinicConfig) { bd: BookingData =>
|
||||
withFunctions(
|
||||
latestOptions = dataService.getLatestClinicsByCityId(userId.accountId, bd.cityId.id),
|
||||
staticOptions = apiService.getAllClinics(userId.accountId, bd.cityId.id),
|
||||
applyId = id => bd.copy(clinicId = id))
|
||||
}(requestNext = RequestService)
|
||||
private def askClinic: Step =
|
||||
staticData(clinicConfig) { bd: BookingData =>
|
||||
withFunctions(
|
||||
latestOptions = dataService.getLatestClinicsByCityId(userId.accountId, bd.cityId.id),
|
||||
staticOptions = apiService.getAllClinics(userId.accountId, bd.cityId.id),
|
||||
applyId = id => bd.copy(clinicId = id))
|
||||
}(requestNext = askService)
|
||||
|
||||
requestStaticData(RequestService, AwaitService, serviceConfig) { bd: BookingData =>
|
||||
withFunctions(
|
||||
latestOptions = dataService.getLatestServicesByCityIdAndClinicId(userId.accountId, bd.cityId.id, bd.clinicId.optionalId),
|
||||
staticOptions = apiService.getAllServices(userId.accountId, bd.cityId.id, bd.clinicId.optionalId),
|
||||
applyId = id => bd.copy(serviceId = id))
|
||||
}(requestNext = RequestDoctor)
|
||||
private def askService: Step =
|
||||
staticData(serviceConfig) { bd: BookingData =>
|
||||
withFunctions(
|
||||
latestOptions = dataService.getLatestServicesByCityIdAndClinicId(userId.accountId, bd.cityId.id, bd.clinicId.optionalId),
|
||||
staticOptions = apiService.getAllServices(userId.accountId, bd.cityId.id, bd.clinicId.optionalId),
|
||||
applyId = id => bd.copy(serviceId = id))
|
||||
}(requestNext = askDoctor)
|
||||
|
||||
requestStaticData(RequestDoctor, AwaitDoctor, doctorConfig) { bd: BookingData =>
|
||||
withFunctions(
|
||||
latestOptions = dataService.getLatestDoctorsByCityIdAndClinicIdAndServiceId(userId.accountId, bd.cityId.id, bd.clinicId.optionalId, bd.serviceId.id),
|
||||
staticOptions = apiService.getAllDoctors(userId.accountId, bd.cityId.id, bd.clinicId.optionalId, bd.serviceId.id),
|
||||
applyId = id => bd.copy(doctorId = id))
|
||||
}(requestNext = RequestDateFrom)
|
||||
private def askDoctor: Step =
|
||||
staticData(doctorConfig) { bd: BookingData =>
|
||||
withFunctions(
|
||||
latestOptions = dataService.getLatestDoctorsByCityIdAndClinicIdAndServiceId(userId.accountId, bd.cityId.id, bd.clinicId.optionalId, bd.serviceId.id),
|
||||
staticOptions = apiService.getAllDoctors(userId.accountId, bd.cityId.id, bd.clinicId.optionalId, bd.serviceId.id),
|
||||
applyId = id => bd.copy(doctorId = id))
|
||||
}(requestNext = requestDateFrom)
|
||||
|
||||
whenSafe(RequestDateFrom) {
|
||||
case Event(_, bookingData: BookingData) =>
|
||||
private def requestDateFrom: Step =
|
||||
question { bookingData =>
|
||||
datePicker ! InitConversation
|
||||
datePicker ! StartConversation
|
||||
datePicker ! DateFromMode
|
||||
datePicker ! bookingData.dateFrom
|
||||
goto(AwaitDateFrom)
|
||||
}
|
||||
} answer {
|
||||
case Msg(cmd: Command, _) =>
|
||||
datePicker ! cmd
|
||||
stay()
|
||||
case Msg(date: ZonedDateTime, bookingData: BookingData) =>
|
||||
goto(requestDateTo) using bookingData.copy(dateFrom = date)
|
||||
}
|
||||
|
||||
whenSafe(AwaitDateFrom) {
|
||||
case Event(cmd: Command, _) =>
|
||||
datePicker ! cmd
|
||||
stay()
|
||||
case Event(date: ZonedDateTime, bookingData: BookingData) =>
|
||||
invokeNext()
|
||||
goto(RequestDateTo) using bookingData.copy(dateFrom = date)
|
||||
}
|
||||
|
||||
whenSafe(RequestDateTo) {
|
||||
case Event(_, bookingData: BookingData) =>
|
||||
private def requestDateTo: Step =
|
||||
question { bookingData =>
|
||||
datePicker ! InitConversation
|
||||
datePicker ! StartConversation
|
||||
datePicker ! DateToMode
|
||||
datePicker ! bookingData.dateFrom.plusDays(1)
|
||||
goto(AwaitDateTo)
|
||||
}
|
||||
} answer {
|
||||
case Msg(cmd: Command, _) =>
|
||||
datePicker ! cmd
|
||||
stay()
|
||||
case Msg(date: ZonedDateTime, bookingData: BookingData) =>
|
||||
goto(requestDayTime) using bookingData.copy(dateTo = date)
|
||||
}
|
||||
|
||||
whenSafe(AwaitDateTo) {
|
||||
case Event(cmd: Command, _) =>
|
||||
datePicker ! cmd
|
||||
stay()
|
||||
case Event(date: ZonedDateTime, bookingData: BookingData) =>
|
||||
invokeNext()
|
||||
goto(RequestDayTime) using bookingData.copy(dateTo = date)
|
||||
}
|
||||
|
||||
whenSafe(RequestDayTime) {
|
||||
case Event(Next, _: BookingData) =>
|
||||
private def requestDayTime: Step =
|
||||
question { _ =>
|
||||
bot.sendMessage(userId.source, lang.chooseTimeOfDay,
|
||||
inlineKeyboard = createInlineKeyboard(lang.timeOfDay.map { case (id, label) => Button(label, id.toString) }.toSeq, columns = 1))
|
||||
goto(AwaitDayTime)
|
||||
}
|
||||
} answer {
|
||||
case Msg(Command(_, msg, Some(timeIdStr)), bookingData: BookingData) =>
|
||||
val timeId = timeIdStr.toInt
|
||||
bot.sendEditMessage(userId.source, msg.messageId, lang.preferredTimeIs(timeId))
|
||||
goto(requestAction) using bookingData.copy(timeOfDay = timeId)
|
||||
}
|
||||
|
||||
whenSafe(AwaitDayTime) {
|
||||
case Event(Command(_, msg, Some(timeIdStr)), bookingData: BookingData) =>
|
||||
invokeNext()
|
||||
val timeId = timeIdStr.toInt
|
||||
bot.sendEditMessage(userId.source, msg.messageId, lang.preferredTimeIs(timeId))
|
||||
goto(RequestAction) using bookingData.copy(timeOfDay = timeId)
|
||||
}
|
||||
|
||||
whenSafe(RequestAction) {
|
||||
case Event(Next, bookingData: BookingData) =>
|
||||
private def requestAction: Step =
|
||||
question { bookingData =>
|
||||
dataService.storeAppointment(userId.accountId, bookingData)
|
||||
bot.sendMessage(userId.source,
|
||||
lang.bookingSummary(bookingData),
|
||||
inlineKeyboard = createInlineKeyboard(Seq(Button(lang.findTerms, Tags.FindTerms), Button(lang.modifyDate, Tags.ModifyDate))))
|
||||
goto(AwaitAction)
|
||||
}
|
||||
} answer {
|
||||
case Msg(Command(_, _, Some(Tags.FindTerms)), _) =>
|
||||
goto(requestTerm)
|
||||
case Msg(Command(_, _, Some(Tags.ModifyDate)), _) =>
|
||||
goto(requestDateFrom)
|
||||
}
|
||||
|
||||
whenSafe(AwaitAction) {
|
||||
case Event(Command(_, _, Some(Tags.FindTerms)), _) =>
|
||||
invokeNext()
|
||||
goto(RequestTerm)
|
||||
case Event(Command(_, _, Some(Tags.ModifyDate)), _) =>
|
||||
invokeNext()
|
||||
goto(RequestDateFrom)
|
||||
}
|
||||
|
||||
whenSafe(RequestTerm) {
|
||||
case Event(Next, bookingData: BookingData) =>
|
||||
private def requestTerm: Step =
|
||||
question { bookingData =>
|
||||
val availableTerms = apiService.getAvailableTerms(userId.accountId, bookingData.cityId.id,
|
||||
bookingData.clinicId.optionalId, bookingData.serviceId.id, bookingData.doctorId.optionalId,
|
||||
bookingData.dateFrom, Some(bookingData.dateTo), timeOfDay = bookingData.timeOfDay)
|
||||
termsPager ! InitConversation
|
||||
termsPager ! StartConversation
|
||||
termsPager ! availableTerms
|
||||
goto(AwaitTerm)
|
||||
}
|
||||
} answer {
|
||||
case Msg(cmd: Command, _) =>
|
||||
termsPager ! cmd
|
||||
stay()
|
||||
case Msg(term: AvailableVisitsTermPresentation, bookingData) =>
|
||||
val response = apiService.temporaryReservation(userId.accountId, term.mapTo[TemporaryReservationRequest], term.mapTo[ValuationsRequest])
|
||||
response match {
|
||||
case Left(ex) =>
|
||||
bot.sendMessage(userId.source, ex.getMessage)
|
||||
end()
|
||||
case Right((temporaryReservation, valuations)) =>
|
||||
bot.sendMessage(userId.source, lang.confirmAppointment(term, valuations),
|
||||
inlineKeyboard = createInlineKeyboard(Seq(Button(lang.cancel, Tags.Cancel), Button(lang.book, Tags.Book))))
|
||||
goto(awaitReservation) using bookingData.copy(term = Some(term), temporaryReservationId = Some(temporaryReservation.id), valuations = Some(valuations))
|
||||
}
|
||||
case Msg(Pager.NoItemsFound, _) =>
|
||||
goto(askNoTermsAction)
|
||||
}
|
||||
|
||||
whenSafe(AwaitTerm) {
|
||||
case Event(Command(_, _, Some(Tags.ModifyDate)), _) =>
|
||||
invokeNext()
|
||||
goto(RequestDateFrom)
|
||||
case Event(Command(_, _, Some(Tags.CreateMonitoring)), _) =>
|
||||
invokeNext()
|
||||
goto(AskMonitoringOptions)
|
||||
case Event(cmd: Command, _) =>
|
||||
termsPager ! cmd
|
||||
stay()
|
||||
case Event(term: AvailableVisitsTermPresentation, _) =>
|
||||
self ! term
|
||||
goto(RequestReservation)
|
||||
case Event(Pager.NoItemsFound, _) =>
|
||||
private def askNoTermsAction: Step =
|
||||
question { _ =>
|
||||
bot.sendMessage(userId.source, lang.noTermsFound, inlineKeyboard =
|
||||
createInlineKeyboard(Seq(Button(lang.modifyDate, Tags.ModifyDate), Button(lang.createMonitoring, Tags.CreateMonitoring))))
|
||||
stay()
|
||||
}
|
||||
} answer {
|
||||
case Msg(Command(_, _, Some(Tags.ModifyDate)), _) =>
|
||||
goto(requestDateFrom)
|
||||
case Msg(Command(_, _, Some(Tags.CreateMonitoring)), _) =>
|
||||
goto(askMonitoringOptions)
|
||||
}
|
||||
|
||||
whenSafe(RequestReservation) {
|
||||
case Event(term: AvailableVisitsTermPresentation, bookingData: BookingData) =>
|
||||
val response = apiService.temporaryReservation(userId.accountId, term.mapTo[TemporaryReservationRequest], term.mapTo[ValuationsRequest])
|
||||
response match {
|
||||
case Left(ex) =>
|
||||
bot.sendMessage(userId.source, ex.getMessage)
|
||||
invokeNext()
|
||||
stay()
|
||||
case Right((temporaryReservation, valuations)) =>
|
||||
bot.sendMessage(userId.source, lang.confirmAppointment(term, valuations),
|
||||
inlineKeyboard = createInlineKeyboard(Seq(Button(lang.cancel, Tags.Cancel), Button(lang.book, Tags.Book))))
|
||||
goto(AwaitReservation) using bookingData.copy(term = Some(term), temporaryReservationId = Some(temporaryReservation.id), valuations = Some(valuations))
|
||||
}
|
||||
}
|
||||
|
||||
whenSafe(AwaitReservation) {
|
||||
case Event(Command(_, _, Some(Tags.Cancel)), bookingData: BookingData) =>
|
||||
private def awaitReservation: Step = monologue {
|
||||
case Msg(Command(_, _, Some(Tags.Cancel)), bookingData: BookingData) =>
|
||||
apiService.deleteTemporaryReservation(userId.accountId, bookingData.temporaryReservationId.get)
|
||||
stay()
|
||||
case Event(Command(_, _, Some(Tags.Book)), bookingData: BookingData) =>
|
||||
case Msg(Command(_, _, Some(Tags.Book)), bookingData: BookingData) =>
|
||||
val reservationRequestMaybe = for {
|
||||
tmpReservationId <- bookingData.temporaryReservationId
|
||||
valuations <- bookingData.valuations
|
||||
@@ -205,49 +188,41 @@ class Book(val userId: UserId, bot: Bot, apiService: ApiService, dataService: Da
|
||||
case Some(reservationRequest) =>
|
||||
apiService.reservation(userId.accountId, reservationRequest) match {
|
||||
case Left(ex) =>
|
||||
error("Error during reservation", ex)
|
||||
bot.sendMessage(userId.source, ex.getMessage)
|
||||
invokeNext()
|
||||
stay()
|
||||
end()
|
||||
case Right(success) =>
|
||||
log.debug(s"Successfully confirmed: $success")
|
||||
debug(s"Successfully confirmed: $success")
|
||||
bot.sendMessage(userId.source, lang.appointmentIsConfirmed)
|
||||
stay()
|
||||
end()
|
||||
}
|
||||
case _ => sys.error(s"Can not prepare reservation request using booking data $bookingData")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
whenSafe(AskMonitoringOptions) {
|
||||
case Event(Next, _) =>
|
||||
private def askMonitoringOptions: Step =
|
||||
question { _ =>
|
||||
bot.sendMessage(userId.source, lang.chooseTypeOfMonitoring,
|
||||
inlineKeyboard = createInlineKeyboard(Seq(Button(lang.bookByApplication, Tags.BookByApplication), Button(lang.bookManually, Tags.BookManually)), columns = 1))
|
||||
stay()
|
||||
case Event(Command(_, _, Some(autobookStr)), bookingData: BookingData) =>
|
||||
val autobook = autobookStr.toBoolean
|
||||
invokeNext()
|
||||
goto(CreateMonitoring) using bookingData.copy(autobook = autobook)
|
||||
}
|
||||
} answer {
|
||||
case Msg(Command(_, _, Some(autobookStr)), bookingData: BookingData) =>
|
||||
val autobook = autobookStr.toBoolean
|
||||
goto(createMonitoring) using bookingData.copy(autobook = autobook)
|
||||
}
|
||||
|
||||
whenSafe(CreateMonitoring) {
|
||||
case Event(Next, bookingData: BookingData) =>
|
||||
private def createMonitoring: Step =
|
||||
internalConfig { bookingData =>
|
||||
debug(s"Creating monitoring for $bookingData")
|
||||
Try(monitoringService.createMonitoring((userId -> bookingData).mapTo[Monitoring])) match {
|
||||
case Success(_) => bot.sendMessage(userId.source, lang.monitoringHasBeenCreated)
|
||||
case Failure(ex) =>
|
||||
try {
|
||||
monitoringService.createMonitoring((userId -> bookingData).mapTo[Monitoring])
|
||||
bot.sendMessage(userId.source, lang.monitoringHasBeenCreated)
|
||||
} catch {
|
||||
case ex: Exception =>
|
||||
error("Unable to create monitoring", ex)
|
||||
bot.sendMessage(userId.source, lang.unableToCreateMonitoring)
|
||||
}
|
||||
goto(RequestCity) using BookingData()
|
||||
}
|
||||
|
||||
whenUnhandledSafe {
|
||||
case Event(Init, _) =>
|
||||
reinit()
|
||||
case e: Event =>
|
||||
error(s"Unhandled event in state:$stateName. Event: $e")
|
||||
stay()
|
||||
}
|
||||
end()
|
||||
}
|
||||
|
||||
private def cityConfig = StaticDataConfig(lang.city, "Wrocław", isAnyAllowed = false)
|
||||
|
||||
@@ -257,16 +232,6 @@ class Book(val userId: UserId, bot: Bot, apiService: ApiService, dataService: Da
|
||||
|
||||
private def doctorConfig = StaticDataConfig(lang.doctor, "Bartniak", isAnyAllowed = true)
|
||||
|
||||
private def reinit() = {
|
||||
invokeNext()
|
||||
datePicker ! InitConversation
|
||||
staticData ! InitConversation
|
||||
termsPager ! Init
|
||||
goto(RequestCity) using BookingData()
|
||||
}
|
||||
|
||||
initialize()
|
||||
|
||||
override def postStop(): Unit = {
|
||||
datePicker ! PoisonPill
|
||||
staticData ! PoisonPill
|
||||
@@ -283,54 +248,10 @@ object Book {
|
||||
Props(new Book(userId, bot, apiService, dataService, monitoringService, localization, datePickerActorFactory,
|
||||
staticDataActorFactory, termsPagerActorFactory))
|
||||
|
||||
object RequestCity extends FSMState
|
||||
|
||||
object AwaitCity extends FSMState
|
||||
|
||||
object RequestClinic extends FSMState
|
||||
|
||||
object AwaitClinic extends FSMState
|
||||
|
||||
object RequestService extends FSMState
|
||||
|
||||
object AwaitService extends FSMState
|
||||
|
||||
object RequestDoctor extends FSMState
|
||||
|
||||
object AwaitDoctor extends FSMState
|
||||
|
||||
object CreateMonitoring extends FSMState
|
||||
|
||||
object AskMonitoringOptions extends FSMState
|
||||
|
||||
object RequestDateFrom extends FSMState
|
||||
|
||||
object AwaitDateFrom extends FSMState
|
||||
|
||||
object RequestDateTo extends FSMState
|
||||
|
||||
object AwaitDateTo extends FSMState
|
||||
|
||||
object RequestDayTime extends FSMState
|
||||
|
||||
object AwaitDayTime extends FSMState
|
||||
|
||||
object RequestAction extends FSMState
|
||||
|
||||
object AwaitAction extends FSMState
|
||||
|
||||
object RequestTerm extends FSMState
|
||||
|
||||
object AwaitTerm extends FSMState
|
||||
|
||||
object RequestReservation extends FSMState
|
||||
|
||||
object AwaitReservation extends FSMState
|
||||
|
||||
case class BookingData(cityId: IdName = null, clinicId: IdName = null,
|
||||
serviceId: IdName = null, doctorId: IdName = null, dateFrom: ZonedDateTime = ZonedDateTime.now(),
|
||||
dateTo: ZonedDateTime = ZonedDateTime.now().plusDays(1L), timeOfDay: Int = 0, autobook: Boolean = false, term: Option[AvailableVisitsTermPresentation] = None,
|
||||
temporaryReservationId: Option[Long] = None, valuations: Option[ValuationsResponse] = None) extends FSMData
|
||||
temporaryReservationId: Option[Long] = None, valuations: Option[ValuationsResponse] = None)
|
||||
|
||||
object Tags {
|
||||
val Cancel = "cancel"
|
||||
|
||||
@@ -51,7 +51,7 @@ class Bug(val userId: UserId, bot: Bot, dataService: DataService, bugPagerActorF
|
||||
goto(displaySubmittedBugs)
|
||||
}
|
||||
|
||||
def displaySubmittedBugs: IC =
|
||||
def displaySubmittedBugs: Step =
|
||||
internalConfig { _ =>
|
||||
val bugs = dataService.getBugs(userId.userId)
|
||||
bugPager ! InitConversation
|
||||
@@ -60,7 +60,7 @@ class Bug(val userId: UserId, bot: Bot, dataService: DataService, bugPagerActorF
|
||||
goto(processResponseFromPager)
|
||||
}
|
||||
|
||||
def processResponseFromPager: M =
|
||||
def processResponseFromPager: Step =
|
||||
monologue {
|
||||
case Msg(cmd: Command, _) =>
|
||||
bugPager ! cmd
|
||||
|
||||
@@ -28,6 +28,7 @@ import com.lbs.bot.model.Command
|
||||
import com.lbs.common.Logger
|
||||
import com.lbs.server.actor.Chat._
|
||||
import com.lbs.server.actor.Login.UserId
|
||||
import com.lbs.server.actor.conversation.Conversation
|
||||
import com.lbs.server.actor.conversation.Conversation.{InitConversation, StartConversation}
|
||||
import com.lbs.server.service.{DataService, MonitoringService}
|
||||
import com.lbs.server.util.MessageExtractors._
|
||||
@@ -37,7 +38,7 @@ import scala.util.matching.Regex
|
||||
class Chat(val userId: UserId, dataService: DataService, monitoringService: MonitoringService, bookingActorFactory: ByUserIdActorFactory, helpActorFactory: ByUserIdActorFactory,
|
||||
monitoringsActorFactory: ByUserIdActorFactory, historyActorFactory: ByUserIdActorFactory,
|
||||
visitsActorFactory: ByUserIdActorFactory, settingsActorFactory: ByUserIdActorFactory,
|
||||
bugActorFactory: ByUserIdActorFactory, accountActorFactory: ByUserIdActorFactory) extends SafeFSM[FSMState, FSMData] with Logger {
|
||||
bugActorFactory: ByUserIdActorFactory, accountActorFactory: ByUserIdActorFactory) extends Conversation[Unit] with Logger {
|
||||
|
||||
private val bookingActor = bookingActorFactory(userId)
|
||||
private val helpActor = helpActorFactory(userId)
|
||||
@@ -48,124 +49,115 @@ class Chat(val userId: UserId, dataService: DataService, monitoringService: Moni
|
||||
private val bugActor = bugActorFactory(userId)
|
||||
private val accountActor = accountActorFactory(userId)
|
||||
|
||||
startWith(HelpChat, null)
|
||||
entryPoint(helpChat)
|
||||
|
||||
when(HelpChat, helpActor) {
|
||||
case Event(cmd@Command(_, Text("/help"), _), _) =>
|
||||
private def helpChat: Step = actorDialogue(helpActor) {
|
||||
case Msg(cmd@Command(_, Text("/help"), _), _) =>
|
||||
helpActor ! cmd
|
||||
stay()
|
||||
case Event(cmd@Command(_, Text("/start"), _), _) =>
|
||||
case Msg(cmd@Command(_, Text("/start"), _), _) =>
|
||||
helpActor ! cmd
|
||||
stay()
|
||||
}
|
||||
|
||||
when(BookChat, bookingActor) {
|
||||
case Event(Command(_, Text("/book"), _), _) =>
|
||||
bookingActor ! Init
|
||||
private def bookChat: Step = actorDialogue(bookingActor) {
|
||||
case Msg(Command(_, Text("/book"), _), _) =>
|
||||
bookingActor ! InitConversation
|
||||
bookingActor ! StartConversation
|
||||
stay()
|
||||
}
|
||||
|
||||
when(HistoryChat, historyActor) {
|
||||
case Event(Command(_, Text("/history"), _), _) =>
|
||||
private def historyChat: Step = actorDialogue(historyActor) {
|
||||
case Msg(Command(_, Text("/history"), _), _) =>
|
||||
historyActor ! InitConversation
|
||||
historyActor ! StartConversation
|
||||
stay()
|
||||
}
|
||||
|
||||
when(VisitsChat, visitsActor) {
|
||||
case Event(Command(_, Text("/reserved"), _), _) =>
|
||||
private def visitsChat: Step = actorDialogue(visitsActor) {
|
||||
case Msg(Command(_, Text("/reserved"), _), _) =>
|
||||
visitsActor ! InitConversation
|
||||
visitsActor ! StartConversation
|
||||
stay()
|
||||
}
|
||||
|
||||
when(BugChat, bugActor) {
|
||||
case Event(Command(_, Text("/bug"), _), _) =>
|
||||
private def bugChat: Step = actorDialogue(bugActor) {
|
||||
case Msg(Command(_, Text("/bug"), _), _) =>
|
||||
bugActor ! InitConversation
|
||||
bugActor ! StartConversation
|
||||
goto(BugChat)
|
||||
stay()
|
||||
}
|
||||
|
||||
when(MonitoringsChat, monitoringsActor) {
|
||||
case Event(Command(_, Text("/monitorings"), _), _) =>
|
||||
private def monitoringsChat: Step = actorDialogue(monitoringsActor) {
|
||||
case Msg(Command(_, Text("/monitorings"), _), _) =>
|
||||
monitoringsActor ! InitConversation
|
||||
monitoringsActor ! StartConversation
|
||||
stay()
|
||||
}
|
||||
|
||||
when(SettingsChat, settingsActor) {
|
||||
case Event(Command(_, Text("/settings"), _), _) =>
|
||||
private def settingsChat: Step = actorDialogue(settingsActor) {
|
||||
case Msg(Command(_, Text("/settings"), _), _) =>
|
||||
settingsActor ! InitConversation
|
||||
settingsActor ! StartConversation
|
||||
stay()
|
||||
}
|
||||
|
||||
when(AccountChat, accountActor) {
|
||||
case Event(Command(_, Text("/accounts"), _), _) =>
|
||||
private def accountChat: Step = actorDialogue(accountActor) {
|
||||
case Msg(Command(_, Text("/accounts"), _), _) =>
|
||||
accountActor ! InitConversation
|
||||
accountActor ! StartConversation
|
||||
stay()
|
||||
}
|
||||
|
||||
private def when(state: FSMState, actor: ActorRef)(mainStateFunction: StateFunction): Unit = {
|
||||
whenSafe(state) {
|
||||
case event: Event =>
|
||||
private def actorDialogue(actor: ActorRef)(mainStateFunction: AnswerFn): Step =
|
||||
monologue {
|
||||
case event: Msg =>
|
||||
if (mainStateFunction.isDefinedAt(event)) mainStateFunction(event)
|
||||
else {
|
||||
val secondaryStateFunction = secondaryState(actor)
|
||||
if (secondaryStateFunction.isDefinedAt(event)) secondaryStateFunction(event)
|
||||
else eventHandler(event)
|
||||
secondaryStateFunction(event)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private def secondaryState(actor: ActorRef): StateFunction = {
|
||||
case Event(cmd@Command(_, Text("/bug"), _), _) =>
|
||||
private def secondaryState(actor: ActorRef): AnswerFn = {
|
||||
case Msg(cmd@Command(_, Text("/bug"), _), _) =>
|
||||
self ! cmd
|
||||
goto(BugChat)
|
||||
case Event(cmd@Command(_, Text("/help"), _), _) =>
|
||||
goto(bugChat)
|
||||
case Msg(cmd@Command(_, Text("/help"), _), _) =>
|
||||
self ! cmd
|
||||
goto(HelpChat)
|
||||
case Event(cmd@Command(_, Text("/start"), _), _) =>
|
||||
goto(helpChat)
|
||||
case Msg(cmd@Command(_, Text("/start"), _), _) =>
|
||||
self ! cmd
|
||||
goto(HelpChat)
|
||||
case Event(cmd@Command(_, Text("/book"), _), _) =>
|
||||
goto(helpChat)
|
||||
case Msg(cmd@Command(_, Text("/book"), _), _) =>
|
||||
self ! cmd
|
||||
goto(BookChat)
|
||||
case Event(cmd@Command(_, Text("/monitorings"), _), _) =>
|
||||
goto(bookChat)
|
||||
case Msg(cmd@Command(_, Text("/monitorings"), _), _) =>
|
||||
self ! cmd
|
||||
goto(MonitoringsChat)
|
||||
case Event(cmd@Command(_, Text("/history"), _), _) =>
|
||||
goto(monitoringsChat)
|
||||
case Msg(cmd@Command(_, Text("/history"), _), _) =>
|
||||
self ! cmd
|
||||
goto(HistoryChat)
|
||||
case Event(cmd@Command(_, Text("/reserved"), _), _) =>
|
||||
goto(historyChat)
|
||||
case Msg(cmd@Command(_, Text("/reserved"), _), _) =>
|
||||
self ! cmd
|
||||
goto(VisitsChat)
|
||||
case Event(cmd@Command(_, Text("/settings"), _), _) =>
|
||||
goto(visitsChat)
|
||||
case Msg(cmd@Command(_, Text("/settings"), _), _) =>
|
||||
self ! cmd
|
||||
goto(SettingsChat)
|
||||
case Event(cmd@Command(_, Text("/accounts"), _), _) =>
|
||||
goto(settingsChat)
|
||||
case Msg(cmd@Command(_, Text("/accounts"), _), _) =>
|
||||
self ! cmd
|
||||
goto(AccountChat)
|
||||
case Event(cmd@Command(_, Text(MonitoringId(monitoringIdStr, scheduleIdStr, timeStr)), _), _) =>
|
||||
goto(accountChat)
|
||||
case Msg(cmd@Command(_, Text(MonitoringId(monitoringIdStr, scheduleIdStr, timeStr)), _), _) =>
|
||||
val monitoringId = monitoringIdStr.toLong
|
||||
val scheduleId = scheduleIdStr.toLong
|
||||
val time = timeStr.toLong
|
||||
monitoringService.bookAppointmentByScheduleId(userId.accountId, monitoringId, scheduleId, time)
|
||||
stay()
|
||||
case Event(cmd: Command, _) =>
|
||||
case Msg(cmd: Command, _) =>
|
||||
actor ! cmd
|
||||
stay()
|
||||
}
|
||||
|
||||
whenUnhandledSafe {
|
||||
case e: Event =>
|
||||
debug(s"Unhandled event in state:$stateName. Event: $e")
|
||||
stay()
|
||||
}
|
||||
|
||||
initialize()
|
||||
|
||||
override def postStop(): Unit = {
|
||||
bookingActor ! PoisonPill
|
||||
helpActor ! PoisonPill
|
||||
@@ -187,24 +179,6 @@ object Chat {
|
||||
Props(new Chat(userId, dataService, monitoringService, bookingActorFactory, helpActorFactory, monitoringsActorFactory,
|
||||
historyActorFactory, visitsActorFactory, settingsActorFactory, bugActorFactory, accountActorFactory))
|
||||
|
||||
object HelpChat extends FSMState
|
||||
|
||||
object BookChat extends FSMState
|
||||
|
||||
object MonitoringsChat extends FSMState
|
||||
|
||||
object HistoryChat extends FSMState
|
||||
|
||||
object VisitsChat extends FSMState
|
||||
|
||||
object SettingsChat extends FSMState
|
||||
|
||||
object BugChat extends FSMState
|
||||
|
||||
object AccountChat extends FSMState
|
||||
|
||||
object Init
|
||||
|
||||
val MonitoringId: Regex = s"/reserve_(\\d+)_(\\d+)_(\\d+)".r
|
||||
|
||||
}
|
||||
@@ -48,7 +48,7 @@ class DatePicker(val userId: UserId, val bot: Bot, val localization: Localizatio
|
||||
|
||||
entryPoint(configure)
|
||||
|
||||
def configure: EC =
|
||||
def configure: Step =
|
||||
externalConfig {
|
||||
case Msg(newMode: Mode, _) =>
|
||||
mode = newMode
|
||||
@@ -57,7 +57,7 @@ class DatePicker(val userId: UserId, val bot: Bot, val localization: Localizatio
|
||||
goto(requestDate) using initialDate
|
||||
}
|
||||
|
||||
def requestDate: QA =
|
||||
def requestDate: Step =
|
||||
question { initialDate =>
|
||||
val message = mode match {
|
||||
case DateFromMode => lang.chooseDateFrom
|
||||
|
||||
@@ -34,7 +34,7 @@ class Help(val userId: UserId, bot: Bot, val localization: Localization) extends
|
||||
|
||||
entryPoint(displayHelp)
|
||||
|
||||
def displayHelp: M =
|
||||
def displayHelp: Step =
|
||||
monologue {
|
||||
case Msg(_: Command, _) =>
|
||||
bot.sendMessage(userId.source, lang.help)
|
||||
|
||||
@@ -39,7 +39,7 @@ class History(val userId: UserId, bot: Bot, apiService: ApiService, val localiza
|
||||
|
||||
entryPoint(prepareData)
|
||||
|
||||
def prepareData: IC =
|
||||
def prepareData: Step =
|
||||
internalConfig { _ =>
|
||||
val visits = apiService.visitsHistory(userId.accountId)
|
||||
historyPager ! InitConversation
|
||||
@@ -48,7 +48,7 @@ class History(val userId: UserId, bot: Bot, apiService: ApiService, val localiza
|
||||
goto(processResponseFromPager)
|
||||
}
|
||||
|
||||
def processResponseFromPager: M =
|
||||
def processResponseFromPager: Step =
|
||||
monologue {
|
||||
case Msg(cmd: Command, _) =>
|
||||
historyPager ! cmd
|
||||
|
||||
@@ -41,14 +41,14 @@ class Login(source: MessageSource, bot: Bot, dataService: DataService, apiServic
|
||||
|
||||
private var forwardCommand: ForwardCommand = _
|
||||
|
||||
def logIn: M =
|
||||
def logIn: Step =
|
||||
monologue {
|
||||
case Msg(cmd: Command, LoginData(None, None)) =>
|
||||
forwardCommand = ForwardCommand(cmd)
|
||||
goto(requestUsername)
|
||||
}
|
||||
|
||||
def requestUsername: QA =
|
||||
def requestUsername: Step =
|
||||
question { _ =>
|
||||
bot.sendMessage(source, lang.provideUsername)
|
||||
} answer {
|
||||
@@ -56,7 +56,7 @@ class Login(source: MessageSource, bot: Bot, dataService: DataService, apiServic
|
||||
goto(requestPassword) using LoginData(username = username)
|
||||
}
|
||||
|
||||
def requestPassword: QA =
|
||||
def requestPassword: Step =
|
||||
question { _ =>
|
||||
bot.sendMessage(source, lang.providePassword)
|
||||
} answer {
|
||||
@@ -64,7 +64,7 @@ class Login(source: MessageSource, bot: Bot, dataService: DataService, apiServic
|
||||
goto(processLoginInformation) using loginData.copy(password = password.map(textEncryptor.encrypt))
|
||||
}
|
||||
|
||||
def processLoginInformation: IC = {
|
||||
def processLoginInformation: Step = {
|
||||
internalConfig { case LoginData(Some(username), Some(password)) =>
|
||||
val loginResult = apiService.login(username, password)
|
||||
loginResult match {
|
||||
|
||||
@@ -40,7 +40,7 @@ class Monitorings(val userId: UserId, bot: Bot, monitoringService: MonitoringSer
|
||||
|
||||
entryPoint(prepareData)
|
||||
|
||||
def prepareData: IC =
|
||||
def prepareData: Step =
|
||||
internalConfig { _ =>
|
||||
val monitorings = monitoringService.getActiveMonitorings(userId.accountId)
|
||||
monitoringsPager ! InitConversation
|
||||
@@ -49,7 +49,7 @@ class Monitorings(val userId: UserId, bot: Bot, monitoringService: MonitoringSer
|
||||
goto(processResponseFromPager)
|
||||
}
|
||||
|
||||
def processResponseFromPager: M =
|
||||
def processResponseFromPager: Step =
|
||||
monologue {
|
||||
case Msg(cmd: Command, _) =>
|
||||
monitoringsPager ! cmd
|
||||
@@ -61,7 +61,7 @@ class Monitorings(val userId: UserId, bot: Bot, monitoringService: MonitoringSer
|
||||
goto(askToDeactivateMonitoring) using monitoring
|
||||
}
|
||||
|
||||
def askToDeactivateMonitoring: QA =
|
||||
def askToDeactivateMonitoring: Step =
|
||||
question { monitoring =>
|
||||
bot.sendMessage(userId.source, lang.deactivateMonitoring(monitoring), inlineKeyboard =
|
||||
createInlineKeyboard(Seq(Button(lang.no, Tags.No), Button(lang.yes, Tags.Yes))))
|
||||
|
||||
@@ -42,7 +42,7 @@ class Pager[Data](val userId: UserId, bot: Bot, makeMessage: (Data, Int, Int) =>
|
||||
|
||||
entryPoint(awaitForData)
|
||||
|
||||
private def awaitForData: EC =
|
||||
private def awaitForData: Step =
|
||||
externalConfig {
|
||||
case Msg(Left(error: Throwable), _) =>
|
||||
bot.sendMessage(userId.source, error.getMessage)
|
||||
@@ -54,7 +54,7 @@ class Pager[Data](val userId: UserId, bot: Bot, makeMessage: (Data, Int, Int) =>
|
||||
goto(displayPage) using Registry(0, items.grouped(Pager.PageSize).toList) -> None
|
||||
}
|
||||
|
||||
private def displayPage: QA =
|
||||
private def displayPage: Step =
|
||||
question { case (registry, massageIdMaybe) =>
|
||||
sendPage(registry.page, registry.pages, massageIdMaybe)
|
||||
} answer {
|
||||
|
||||
@@ -36,7 +36,7 @@ class Settings(val userId: UserId, bot: Bot, dataService: DataService, val local
|
||||
|
||||
entryPoint(askForAction)
|
||||
|
||||
def askForAction: QA =
|
||||
def askForAction: Step =
|
||||
question { _ =>
|
||||
bot.sendMessage(userId.source, lang.settingsHeader, inlineKeyboard =
|
||||
createInlineKeyboard(Seq(Button(lang.language, Tags.Language))))
|
||||
@@ -45,7 +45,7 @@ class Settings(val userId: UserId, bot: Bot, dataService: DataService, val local
|
||||
goto(askLanguage)
|
||||
}
|
||||
|
||||
def askLanguage: QA =
|
||||
def askLanguage: Step =
|
||||
question { _ =>
|
||||
bot.sendMessage(userId.source, lang.chooseLanguage,
|
||||
inlineKeyboard = createInlineKeyboard(Lang.Langs.map(l => Button(l.label, l.id)), columns = 1))
|
||||
|
||||
@@ -40,14 +40,14 @@ class StaticData(val userId: UserId, bot: Bot, val localization: Localization, o
|
||||
|
||||
entryPoint(AwaitConfig)
|
||||
|
||||
def AwaitConfig: EC =
|
||||
def AwaitConfig: Step =
|
||||
externalConfig {
|
||||
case Msg(newConfig: StaticDataConfig, _) =>
|
||||
config = newConfig
|
||||
goto(askForLatestOption)
|
||||
}
|
||||
|
||||
def askForLatestOption: QA =
|
||||
def askForLatestOption: Step =
|
||||
question { _ =>
|
||||
originator ! LatestOptions
|
||||
} answer {
|
||||
@@ -59,7 +59,7 @@ class StaticData(val userId: UserId, bot: Bot, val localization: Localization, o
|
||||
goto(askForUserInput) using callbackTags
|
||||
}
|
||||
|
||||
def askForUserInput: QA =
|
||||
def askForUserInput: Step =
|
||||
question { callbackTags =>
|
||||
bot.sendMessage(userId.source, lang.pleaseEnterStaticDataNameOrPrevious(config),
|
||||
inlineKeyboard = createInlineKeyboard(callbackTags, columns = 1))
|
||||
|
||||
@@ -28,41 +28,38 @@ import com.lbs.api.json.model.IdName
|
||||
import com.lbs.bot.model.Command
|
||||
import com.lbs.server.actor.Book.BookingData
|
||||
import com.lbs.server.actor.StaticData.{FindOptions, FoundOptions, LatestOptions, StaticDataConfig}
|
||||
import com.lbs.server.actor.conversation.Conversation
|
||||
import com.lbs.server.actor.conversation.Conversation.{InitConversation, StartConversation}
|
||||
|
||||
trait StaticDataForBooking extends SafeFSM[FSMState, FSMData] {
|
||||
trait StaticDataForBooking extends Conversation[BookingData] {
|
||||
|
||||
protected def staticData: ActorRef
|
||||
private[actor] def staticData: ActorRef
|
||||
|
||||
protected def withFunctions(latestOptions: => Seq[IdName], staticOptions: => Either[Throwable, List[IdName]], applyId: IdName => BookingData): FSMState => StateFunction = {
|
||||
nextState: FSMState => {
|
||||
case Event(cmd: Command, _) =>
|
||||
protected def withFunctions(latestOptions: => Seq[IdName], staticOptions: => Either[Throwable, List[IdName]], applyId: IdName => BookingData): Step => AnswerFn = {
|
||||
nextStep: Step => {
|
||||
case Msg(cmd: Command, _) =>
|
||||
staticData ! cmd
|
||||
stay()
|
||||
case Event(LatestOptions, _) =>
|
||||
case Msg(LatestOptions, _) =>
|
||||
staticData ! LatestOptions(latestOptions)
|
||||
stay()
|
||||
case Event(FindOptions(searchText), _) =>
|
||||
case Msg(FindOptions(searchText), _) =>
|
||||
staticData ! FoundOptions(filterOptions(staticOptions, searchText))
|
||||
stay()
|
||||
case Event(id: IdName, _) =>
|
||||
invokeNext()
|
||||
goto(nextState) using applyId(id)
|
||||
case Msg(id: IdName, _) =>
|
||||
goto(nextStep) using applyId(id)
|
||||
}
|
||||
}
|
||||
|
||||
protected def requestStaticData(requestState: FSMState, awaitState: FSMState, staticDataConfig: => StaticDataConfig)(functions: BookingData => FSMState => StateFunction)(requestNext: FSMState): Unit = {
|
||||
whenSafe(requestState) {
|
||||
case Event(_, _) =>
|
||||
staticData ! InitConversation
|
||||
staticData ! StartConversation
|
||||
staticData ! staticDataConfig
|
||||
goto(awaitState)
|
||||
}
|
||||
whenSafe(awaitState) {
|
||||
case event@Event(_, bookingData: BookingData) =>
|
||||
protected def staticData(staticDataConfig: => StaticDataConfig)(functions: BookingData => Step => AnswerFn)(requestNext: Step): Step = {
|
||||
question { _ =>
|
||||
staticData ! InitConversation
|
||||
staticData ! StartConversation
|
||||
staticData ! staticDataConfig
|
||||
} answer {
|
||||
case msg@Msg(_, bookingData: BookingData) =>
|
||||
val fn = functions(bookingData)(requestNext)
|
||||
if (fn.isDefinedAt(event)) fn(event) else eventHandler(event)
|
||||
fn(msg)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ class Visits(val userId: UserId, bot: Bot, apiService: ApiService, val localizat
|
||||
|
||||
entryPoint(prepareData)
|
||||
|
||||
def prepareData: IC =
|
||||
def prepareData: Step =
|
||||
internalConfig { _ =>
|
||||
val visits = apiService.reservedVisits(userId.accountId)
|
||||
reservedVisitsPager ! InitConversation
|
||||
@@ -50,7 +50,7 @@ class Visits(val userId: UserId, bot: Bot, apiService: ApiService, val localizat
|
||||
goto(processResponseFromPager)
|
||||
}
|
||||
|
||||
def processResponseFromPager: M =
|
||||
def processResponseFromPager: Step =
|
||||
monologue {
|
||||
case Msg(cmd: Command, _) =>
|
||||
reservedVisitsPager ! cmd
|
||||
@@ -62,7 +62,7 @@ class Visits(val userId: UserId, bot: Bot, apiService: ApiService, val localizat
|
||||
goto(askToCancelVisit) using visit
|
||||
}
|
||||
|
||||
def askToCancelVisit: QA =
|
||||
def askToCancelVisit: Step =
|
||||
question { visit =>
|
||||
bot.sendMessage(userId.source, lang.areYouSureToCancelAppointment(visit),
|
||||
inlineKeyboard = createInlineKeyboard(Seq(Button(lang.no, Tags.No), Button(lang.yes, Tags.Yes))))
|
||||
|
||||
@@ -29,14 +29,6 @@ trait Domain[D] {
|
||||
|
||||
private[conversation] case class Answer(answerFn: AnswerFn)
|
||||
|
||||
protected type QA = QuestionAnswer
|
||||
|
||||
protected type EC = ExternalConfiguration
|
||||
|
||||
protected type IC = InternalConfiguration
|
||||
|
||||
protected type M = Monologue
|
||||
|
||||
protected implicit class RichQuestion(question: Question) {
|
||||
def answer(answerFn: AnswerFn): QuestionAnswer = QuestionAnswer(question, Answer(answerFn))
|
||||
}
|
||||
|
||||
@@ -32,11 +32,4 @@ package object actor {
|
||||
type ByUserIdActorFactory = UserId => ActorRef
|
||||
type ByMessageSourceActorFactory = MessageSource => ActorRef
|
||||
type ByMessageSourceWithOriginatorActorFactory = (MessageSource, ActorRef) => ActorRef
|
||||
|
||||
def invokeNext()(implicit self: ActorRef): Unit = {
|
||||
self ! Next
|
||||
}
|
||||
|
||||
object Next
|
||||
|
||||
}
|
||||
|
||||
@@ -196,9 +196,9 @@ class MonitoringService extends Logger {
|
||||
debug(s"Deactivating monitoring [#$monitoringId]")
|
||||
if (!future.isCancelled) {
|
||||
future.cancel(true)
|
||||
monitoring.active = false
|
||||
dataService.saveMonitoring(monitoring)
|
||||
}
|
||||
monitoring.active = false
|
||||
dataService.saveMonitoring(monitoring)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -245,7 +245,6 @@ class MonitoringService extends Logger {
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
private def lang(userId: Long) = localization.lang(userId)
|
||||
|
||||
@PostConstruct
|
||||
|
||||
@@ -3,8 +3,8 @@ package com.lbs.server.actor
|
||||
import akka.actor.ActorRef
|
||||
import akka.testkit.TestProbe
|
||||
import com.lbs.bot.model.{Command, Message, MessageSource, TelegramMessageSourceSystem}
|
||||
import com.lbs.server.actor.Chat.Init
|
||||
import com.lbs.server.actor.Login.{ForwardCommand, LoggedIn, UserId}
|
||||
import com.lbs.server.actor.conversation.Conversation.{InitConversation, StartConversation}
|
||||
import com.lbs.server.service.DataService
|
||||
import org.mockito.Mockito._
|
||||
|
||||
@@ -42,7 +42,8 @@ class AuthSpec extends AkkaTestKit {
|
||||
"initialize dialogue with login actor on /login command" in {
|
||||
val cmd = Command(source, Message("1", Some("/login")))
|
||||
auth ! cmd
|
||||
loginActor.expectMsg(Init)
|
||||
loginActor.expectMsg(InitConversation)
|
||||
loginActor.expectMsg(StartConversation)
|
||||
loginActor.expectMsg(cmd)
|
||||
}
|
||||
|
||||
@@ -95,7 +96,8 @@ class AuthSpec extends AkkaTestKit {
|
||||
"initialize dialogue with login actor on /login command" in {
|
||||
val cmd = Command(source, Message("1", Some("/login")))
|
||||
auth ! cmd
|
||||
loginActor.expectMsg(Init)
|
||||
loginActor.expectMsg(InitConversation)
|
||||
loginActor.expectMsg(StartConversation)
|
||||
loginActor.expectMsg(cmd)
|
||||
}
|
||||
|
||||
|
||||
@@ -22,14 +22,14 @@ class ConversationSpec extends AkkaTestKit {
|
||||
|
||||
private var conf: String = _
|
||||
|
||||
def configure: EC =
|
||||
def configure: Step =
|
||||
externalConfig {
|
||||
case Msg(confStr: String, data) =>
|
||||
conf = confStr
|
||||
goto(askHello) using data.copy(configured = true)
|
||||
}
|
||||
|
||||
def askHello: QA =
|
||||
def askHello: Step =
|
||||
question { data =>
|
||||
self ! Hello
|
||||
} answer {
|
||||
@@ -37,7 +37,7 @@ class ConversationSpec extends AkkaTestKit {
|
||||
goto(askWorld) using data.copy(hello = "hello")
|
||||
}
|
||||
|
||||
def askWorld: QA =
|
||||
def askWorld: Step =
|
||||
question { data =>
|
||||
self ! World
|
||||
} answer {
|
||||
@@ -45,7 +45,7 @@ class ConversationSpec extends AkkaTestKit {
|
||||
goto(askDialogue) using data.copy(world = "world")
|
||||
}
|
||||
|
||||
def askDialogue: QA =
|
||||
def askDialogue: Step =
|
||||
question { data =>
|
||||
self ! Dialogue
|
||||
} answer {
|
||||
@@ -80,17 +80,17 @@ class ConversationSpec extends AkkaTestKit {
|
||||
|
||||
class TestActor(originator: ActorRef) extends Conversation[Data] {
|
||||
|
||||
def configure1: IC =
|
||||
def configure1: Step =
|
||||
internalConfig { _ =>
|
||||
goto(configure2) using Data(configured = true)
|
||||
}
|
||||
|
||||
def configure2: IC =
|
||||
def configure2: Step =
|
||||
internalConfig { data =>
|
||||
goto(askMessage2) using data.copy(message1 = "hello")
|
||||
}
|
||||
|
||||
def askMessage2: QA =
|
||||
def askMessage2: Step =
|
||||
question { _ =>
|
||||
self ! InvokeEnrichMessage
|
||||
} answer {
|
||||
|
||||
Reference in New Issue
Block a user