Skip to content

Commit

Permalink
#8 Integrated a geoadmin search library into the bot
Browse files Browse the repository at this point in the history
  • Loading branch information
sipakov committed Apr 14, 2023
1 parent 46defb8 commit 1c2da57
Show file tree
Hide file tree
Showing 5 changed files with 131 additions and 38 deletions.
12 changes: 6 additions & 6 deletions AlgoTecture.Data.Persistence.Ef/ApplicationDbContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -95,35 +95,35 @@ protected override void OnModelCreating(ModelBuilder modelBuilder)
SpaceId = 1,
Name = "Santa María",
SpacePropertyId = Guid.Parse("4c4f455c-bc98-47da-9f4b-9dcc25a17fe5"),
Description = "Description"
Description = "best boat in the world"
};
modelBuilder.Entity<Space>().HasData(new Space
{
Id = 1, Latitude = 38.705022, Longitude = -9.145460, SpaceAddress = "Lisbon, Lisboa-Cacilhas",
Id = 1, Latitude = 47.361812591552734, Longitude = 8.5370702743530273, SpaceAddress = "Mythenquai 7, 8002 Zürich",
SpaceProperty = JsonConvert.SerializeObject(newSpaceProperty1), UtilizationTypeId = 12
});
var newSpaceProperty2 = new SpaceProperty
{
SpaceId = 2,
Name = "Niña",
SpacePropertyId = Guid.Parse("7d2dc2f3-4f52-4244-8ade-73eba2772a51"),
Description = "Description"
Description = "best boat in the world"
};
modelBuilder.Entity<Space>().HasData(new Space
{
Id = 2, Latitude = 38.705022, Longitude = -9.145460, SpaceAddress = "Lisbon, Lisboa-Cacilhas",
Id = 2, Latitude = 47.36164855957031, Longitude = 8.5366735458374023, SpaceAddress = "Mythenquai 9, 8002 Zürich",
SpaceProperty = JsonConvert.SerializeObject(newSpaceProperty2), UtilizationTypeId = 12
});
var newSpaceProperty3 = new SpaceProperty
{
SpaceId = 3,
Name = "Pinta",
SpacePropertyId = Guid.Parse("a5f8e388-0c2f-491c-82ff-d4c92da97aaa"),
Description = "Description"
Description = "best boat in the world"
};
modelBuilder.Entity<Space>().HasData(new Space
{
Id = 3, Latitude = 38.705022, Longitude = -9.145460, SpaceAddress = "Lisbon, Lisboa-Cacilhas",
Id = 3, Latitude = 47.3613166809082, Longitude = 8.5362958908081055, SpaceAddress = "Mythenquai 25, 8002 Zürich",
SpaceProperty = JsonConvert.SerializeObject(newSpaceProperty3), UtilizationTypeId = 12
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ public override async Task<IEnumerable<Space>> All()

public async Task<Space> GetByCoordinates(double latitude, double longitude)
{
return await dbSet.FirstOrDefaultAsync(x=>Math.Abs(x.Latitude - latitude) < 0.000000001 && Math.Abs(x.Longitude - longitude) < 0.000000001);
return await dbSet.Include(x=>x.UtilizationType)
.FirstOrDefaultAsync(x=>Math.Abs(x.Latitude - latitude) < 0.000000001 && Math.Abs(x.Longitude - longitude) < 0.000000001);
}

public async Task<List<Space>> GetByType(int utilizationTypeId)
Expand Down
39 changes: 14 additions & 25 deletions AlgoTecture.TelegramBot/Controllers/BoatController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ public class BoatController : BotController, IBoatController
private readonly IReservationService _reservationService;
private readonly ILogger<BoatController> _logger;

public BoatController(ISpaceGetter spaceGetter, IServiceProvider serviceProvider, IUnitOfWork unitOfWork, IReservationService reservationService, ILogger<BoatController> logger)
public BoatController(ISpaceGetter spaceGetter, IServiceProvider serviceProvider, IUnitOfWork unitOfWork, IReservationService reservationService,
ILogger<BoatController> logger)
{
_spaceGetter = spaceGetter ?? throw new ArgumentNullException(nameof(spaceGetter));
_serviceProvider = serviceProvider;
Expand All @@ -37,6 +38,13 @@ public BoatController(ISpaceGetter spaceGetter, IServiceProvider serviceProvider
[Action]
public async Task PressToMainBookingPage(BotState botState)
{
//only for demo
const int boatTargetOfSpaceId = 12;
if (botState.UtilizationTypeId !=boatTargetOfSpaceId)
{
return;
}

RowButton("See available boats", Q(PressToRentTargetUtilizationButton, botState, true));
RowButton("Make a reservation", Q(PressToEnterTheStartEndTime, botState, RentTimeState.None, null));

Expand All @@ -61,10 +69,8 @@ private async Task PressToRentTargetUtilizationButton(BotState botState, bool is
botState.SpaceId = default;
botState.SpaceName = default;
}

const int boatTargetOfSpaceId = 12;

var targetSpaces = await _spaceGetter.GetByType(boatTargetOfSpaceId);

var targetSpaces = await _spaceGetter.GetByType(botState.UtilizationTypeId);

foreach (var space in targetSpaces)
{
Expand All @@ -90,7 +96,7 @@ private async Task PressToChooseTheDate(BotState botState, RentTimeState rentTim
}

[Action]
private async Task PressToEnterTheStartEndTime(BotState botState, RentTimeState rentTimeState, DateTime? dateTime)
public async Task PressToEnterTheStartEndTime(BotState botState, RentTimeState rentTimeState, DateTime? dateTime)
{
var chatId = Context.GetSafeChatId();
if (!chatId.HasValue) return;
Expand Down Expand Up @@ -148,12 +154,12 @@ private async Task PressToEnterTheStartEndTime(BotState botState, RentTimeState

if (string.IsNullOrEmpty(time))
{
PushL("Reservation");
PushL("Reservation the boat");
await SendOrUpdate();
}
else
{
await Send("Reservation");
await Send("Reservation the boat");
}
}

Expand Down Expand Up @@ -306,21 +312,4 @@ private async Task PressMakeAReservation(BotState botState)
throw;
}
}

[On(Handle.Exception)]
public async Task Exception()
{
PushL("Ooops");

await SendOrUpdate();
}

[On(Handle.Unknown)]
public async Task Unknown()
{
PushL(
"I'm sorry, but I'm not yet able to understand natural language requests at the moment. Please provide specific instructions using the AlgoTecture bot " +
"interface for me to execute tasks.");
await SendOrUpdate();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,6 @@ namespace AlgoTecture.TelegramBot.Controllers.Interfaces;
public interface IBoatController
{
Task PressToMainBookingPage(BotState botState);

Task PressToEnterTheStartEndTime(BotState botState, RentTimeState rentTimeState, DateTime? dateTime);
}
113 changes: 107 additions & 6 deletions AlgoTecture.TelegramBot/Controllers/MainController.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
using AlgoTecture.Data.Persistence.Core.Interfaces;
using AlgoTecture.Domain.Models;
using AlgoTecture.Domain.Models.Dto;
using AlgoTecture.Libraries.GeoAdminSearch;
using AlgoTecture.Libraries.Spaces.Interfaces;
using AlgoTecture.Libraries.UtilizationTypes;
using AlgoTecture.TelegramBot.Controllers.Interfaces;
using AlgoTecture.TelegramBot.Interfaces;
using AlgoTecture.TelegramBot.Models;
using Deployf.Botf;
using Newtonsoft.Json;

namespace AlgoTecture.TelegramBot.Controllers;

Expand All @@ -14,16 +18,26 @@ public class MainController : BotController, IMainController
private readonly IUtilizationTypeGetter _utilizationTypeGetter;
private readonly IUnitOfWork _unitOfWork;
private readonly ILogger<MainController> _logger;
private readonly IGeoAdminSearcher _geoAdminSearcher;
private readonly ITelegramToAddressResolver _telegramToAddressResolver;
private readonly ISpaceGetter _spaceGetter;
private readonly IServiceProvider _serviceProvider;

private readonly IBoatController _boatController;

public MainController(ITelegramUserInfoService telegramUserInfoService, IBoatController boatController, IUtilizationTypeGetter utilizationTypeGetter, IUnitOfWork unitOfWork, ILogger<MainController> logger)
public MainController(ITelegramUserInfoService telegramUserInfoService, IBoatController boatController, IUtilizationTypeGetter utilizationTypeGetter,
IUnitOfWork unitOfWork, ILogger<MainController> logger, IGeoAdminSearcher geoAdminSearcher, ITelegramToAddressResolver telegramToAddressResolver,
ISpaceGetter spaceGetter, IServiceProvider serviceProvider)
{
_telegramUserInfoService = telegramUserInfoService;
_boatController = boatController;
_utilizationTypeGetter = utilizationTypeGetter;
_unitOfWork = unitOfWork;
_logger = logger;
_geoAdminSearcher = geoAdminSearcher;
_telegramToAddressResolver = telegramToAddressResolver;
_spaceGetter = spaceGetter;
_serviceProvider = serviceProvider;
}

[Action("/start", "start the bot")]
Expand Down Expand Up @@ -56,7 +70,9 @@ public async Task Start()
[Action]
public async Task PressToRentButton()
{
var utilizationTypes = (await _utilizationTypeGetter.GetAll()).Skip(6).ToList();
//only for demo
var utilizationTypes = (await _utilizationTypeGetter.GetAll()).Where(x=> (new List<string>(){"Residential", "Parking", "Boat"})
.Contains(x.Name)).ToList();

foreach (var utilizationType in utilizationTypes)
{
Expand All @@ -66,7 +82,7 @@ public async Task PressToRentButton()
Id = utilizationType.Id
};

var botState = new BotState { UtilizationTypeId = utilizationType.Id, MessageId = default(int) };
var botState = new BotState { UtilizationTypeId = utilizationType.Id, MessageId = default };

RowButton(utilizationTypeOut.Name, Q(_boatController.PressToMainBookingPage, botState));
}
Expand All @@ -92,15 +108,16 @@ public async Task PressToFindReservationsButton()
var reservationToTelegram = new ReservationToTelegramOut()
{
Id = reservation.Id,
DateTimeFrom = $"{reservation.ReservationFromUtc.Value:dd MM yyyy HH:mm} utc",
DateTimeTo = $"{reservation.ReservationToUtc.Value:dd MM yyyy HH:mm} utc",
DateTimeFrom = $"{reservation.ReservationFromUtc.Value:dd-MM-yyyy HH:mm} utc",
DateTimeTo = $"{reservation.ReservationToUtc.Value:dd-MM-yyyy HH:mm} utc",
Description = reservation.Description,
TotlaPrice = reservation.TotalPrice,
PriceCurrency = reservation.PriceSpecification.PriceCurrency
};
reservationList.Add(reservationToTelegram);
var description =
$"{reservationToTelegram.Description}, {reservationToTelegram.DateTimeFrom} - {reservationToTelegram.DateTimeTo}, {reservationToTelegram.TotlaPrice} {reservationToTelegram.PriceCurrency.ToUpper()}";
$"{reservationToTelegram.Description}, \n{reservationToTelegram.DateTimeFrom}, {reservationToTelegram.TotlaPrice} \n" +
$"{reservationToTelegram.PriceCurrency.ToUpper()}";
RowButton(description, Q(PressToManageContract));
}
RowButton("Go Back", Q(Start));
Expand All @@ -114,4 +131,88 @@ public async Task PressToManageContract()
{

}

[Action]
private async Task PressAddressToRentButton(string geoAdminFeatureId)
{
var chatId = Context.GetSafeChatId();
if (!chatId.HasValue) return;

var targetAddress = _telegramToAddressResolver.TryGetAddressListByChatId(chatId.Value).FirstOrDefault(x => x.FeatureId == geoAdminFeatureId);

//var user = await _unitOfWork.Users.GetByTelegramChatId(chatId.Value);
var targetSpace = await _spaceGetter.GetByCoordinates(targetAddress.latitude, targetAddress.longitude);

_telegramToAddressResolver.RemoveAddressListByChatId(chatId.Value);

if (targetSpace == null)
{
await Start();
await Send("No spaces found at this address");
}
else
{
var targetSpaceProperty = JsonConvert.DeserializeObject<SpaceProperty>(targetSpace.SpaceProperty);

var boatControllerService = _serviceProvider.GetRequiredService<IBoatController>();

RowButton("Rent!", Q(boatControllerService.PressToEnterTheStartEndTime, new BotState{SpaceId = targetSpace.Id,
SpaceName = targetSpaceProperty.Name}, RentTimeState.None, null));
RowButton("Go to main", Q(Start));

PushL($"Found! {targetSpace.UtilizationType.Name}: {targetSpaceProperty?.Name}. {targetSpaceProperty?.Description}");
}
}

[On(Handle.Exception)]
public async Task Exception(Exception ex)
{
_logger.LogError(ex, "Handle.Exception on telegram-bot");

PushL("Ooops. An error has occurred");
await Start();
await SendOrUpdate();
}

[On(Handle.Unknown)]
public async Task Unknown()
{
var chatId = Context.GetSafeChatId();
if (!chatId.HasValue) return;

PushL(
"I'm sorry, but I'm not yet able to understand natural language requests at the moment. Enter an address to search for the space");
await Send();

var address = await AwaitText();

var telegramToAddressList = new List<TelegramToAddressModel>();


var labels = (await _geoAdminSearcher.GetAddress(address)).ToList();

foreach (var label in labels)
{
var telegramToAddressModel = new TelegramToAddressModel
{
FeatureId = label.featureId,
latitude = label.lat,
longitude = label.lon,
Address = label.label
};
telegramToAddressList.Add(telegramToAddressModel);
RowButton(label.label, Q(PressAddressToRentButton, label.featureId));
}

if (!labels.Any())
{
RowButton("Try again");
await Send("Nothing found");
}
else
{
_telegramToAddressResolver.TryAddCurrentAddressList(chatId.Value, telegramToAddressList);
await Send("Choose the right address");
}
}
}

0 comments on commit 1c2da57

Please sign in to comment.