Skip to content

Commit 22087ee

Browse files
author
Igor Evdokimov
committed
- ShowMap
1 parent c1997af commit 22087ee

File tree

17 files changed

+284
-79
lines changed

17 files changed

+284
-79
lines changed

.idea/.idea.Botticelli/.idea/vcs.xml

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFramework>net8.0</TargetFramework>
5+
<ImplicitUsings>enable</ImplicitUsings>
6+
<Nullable>enable</Nullable>
7+
8+
<IsPackable>false</IsPackable>
9+
<IsTestProject>true</IsTestProject>
10+
</PropertyGroup>
11+
12+
<ItemGroup>
13+
<PackageReference Include="coverlet.collector" Version="6.0.0"/>
14+
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0"/>
15+
<PackageReference Include="NUnit" Version="3.14.0"/>
16+
<PackageReference Include="NUnit.Analyzers" Version="3.9.0"/>
17+
<PackageReference Include="NUnit3TestAdapter" Version="4.5.0"/>
18+
</ItemGroup>
19+
20+
<ItemGroup>
21+
<Using Include="NUnit.Framework"/>
22+
</ItemGroup>
23+
24+
<ItemGroup>
25+
<Reference Include="Microsoft.Extensions.Configuration.Abstractions">
26+
<HintPath>..\..\..\..\Program Files\dotnet\shared\Microsoft.AspNetCore.App\8.0.4\Microsoft.Extensions.Configuration.Abstractions.dll</HintPath>
27+
</Reference>
28+
<Reference Include="Microsoft.Extensions.DependencyInjection.Abstractions">
29+
<HintPath>..\..\..\..\Program Files\dotnet\shared\Microsoft.AspNetCore.App\8.0.4\Microsoft.Extensions.DependencyInjection.Abstractions.dll</HintPath>
30+
</Reference>
31+
</ItemGroup>
32+
33+
<ItemGroup>
34+
<ProjectReference Include="..\Botticelli.Locations\Botticelli.Locations.csproj" />
35+
</ItemGroup>
36+
37+
</Project>
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
using System.Reflection;
2+
using Botticelli.Framework.Commands.Validators;
3+
using Botticelli.Framework.Controls.Parsers;
4+
using Botticelli.Framework.Extensions;
5+
using Botticelli.Framework.Telegram;
6+
using Botticelli.Framework.Telegram.Layout;
7+
using Botticelli.Locations.Commands;
8+
using Botticelli.Locations.Commands.CommandProcessors;
9+
using Botticelli.Locations.Integration;
10+
using Botticelli.Locations.Options;
11+
using Flurl;
12+
using Mapster;
13+
using Microsoft.Extensions.Configuration;
14+
using Microsoft.Extensions.DependencyInjection;
15+
using Nominatim.API.Address;
16+
using Nominatim.API.Geocoders;
17+
using Nominatim.API.Interfaces;
18+
using Nominatim.API.Web;
19+
using Telegram.Bot.Types.ReplyMarkups;
20+
21+
namespace Botticelli.Locations.Telegram.Extensions;
22+
23+
public static class ServiceCollectionExtensions
24+
{
25+
/// <summary>
26+
/// Adds an OSM location provider
27+
/// </summary>
28+
/// <returns></returns>
29+
public static IServiceCollection AddOsmLocations(this IServiceCollection services,
30+
IConfiguration config,
31+
string url = "https://nominatim.openstreetmap.org")
32+
{
33+
services.AddHttpClient<OsmLocationProvider>();
34+
TypeAdapterConfig.GlobalSettings.Scan(Assembly.GetExecutingAssembly());
35+
return services.Configure<LocationsProcessorOptions>(config)
36+
.AddScoped<ICommandValidator<FindLocationsCommand>, PassValidator<FindLocationsCommand>>()
37+
.AddScoped<ICommandValidator<ShowMapCommand>, PassValidator<ShowMapCommand>>()
38+
.AddScoped<FindLocationsCommandProcessor<InlineKeyboardMarkup>>()
39+
.AddScoped<ShowMapCommandProcessor<ReplyKeyboardMarkup>>()
40+
.AddScoped<ILocationProvider, OsmLocationProvider>()
41+
.AddScoped<INominatimWebInterface, NominatimWebInterface>()
42+
.AddScoped<IAddressSearcher, AddressSearcher>()
43+
.AddScoped<ILayoutSupplier<InlineKeyboardMarkup>, InlineTelegramLayoutSupplier>()
44+
.AddScoped<ILayoutSupplier<ReplyKeyboardMarkup>, ReplyTelegramLayoutSupplier>()
45+
.AddScoped<IForwardGeocoder, ForwardGeocoder>(sp =>
46+
new ForwardGeocoder(sp.GetRequiredService<INominatimWebInterface>(),
47+
Url.Combine(url, "search")))
48+
.AddScoped<IReverseGeocoder, ReverseGeocoder>(sp =>
49+
new ReverseGeocoder(sp.GetRequiredService<INominatimWebInterface>(),
50+
Url.Combine(url, "reverse")));
51+
}
52+
53+
public static IServiceProvider RegisterOsmLocationsCommands(this IServiceProvider sp,
54+
string url = "https://nominatim.openstreetmap.org") =>
55+
sp.RegisterBotCommand<FindLocationsCommand, FindLocationsCommandProcessor<InlineKeyboardMarkup>, TelegramBot>()
56+
.RegisterBotCommand<ShowMapCommand, ShowMapCommandProcessor<ReplyKeyboardMarkup>, TelegramBot>();
57+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFramework>net8.0</TargetFramework>
5+
<ImplicitUsings>enable</ImplicitUsings>
6+
<Nullable>enable</Nullable>
7+
<RootNamespace>Botticelli.Locations.Vk1</RootNamespace>
8+
</PropertyGroup>
9+
10+
<ItemGroup>
11+
<Reference Include="Microsoft.Extensions.Configuration.Abstractions">
12+
<HintPath>..\..\..\..\Program Files\dotnet\shared\Microsoft.AspNetCore.App\8.0.4\Microsoft.Extensions.Configuration.Abstractions.dll</HintPath>
13+
</Reference>
14+
<Reference Include="Microsoft.Extensions.DependencyInjection.Abstractions">
15+
<HintPath>..\..\..\..\Program Files\dotnet\shared\Microsoft.AspNetCore.App\8.0.4\Microsoft.Extensions.DependencyInjection.Abstractions.dll</HintPath>
16+
</Reference>
17+
</ItemGroup>
18+
19+
<ItemGroup>
20+
<PackageReference Include="Mapster" Version="7.4.0"/>
21+
</ItemGroup>
22+
23+
<ItemGroup>
24+
<ProjectReference Include="..\Botticelli.Framework.Vk\Botticelli.Framework.Vk.Messages.csproj"/>
25+
<ProjectReference Include="..\Botticelli.Locations\Botticelli.Locations.csproj"/>
26+
</ItemGroup>
27+
28+
</Project>
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
using System.Reflection;
2+
using Botticelli.Framework.Commands.Validators;
3+
using Botticelli.Framework.Controls.Parsers;
4+
using Botticelli.Framework.Extensions;
5+
using Botticelli.Framework.Vk.Messages;
6+
using Botticelli.Framework.Vk.Messages.API.Markups;
7+
using Botticelli.Framework.Vk.Messages.Layout;
8+
using Botticelli.Interfaces;
9+
using Botticelli.Locations.Commands;
10+
using Botticelli.Locations.Commands.CommandProcessors;
11+
using Botticelli.Locations.Integration;
12+
using Botticelli.Locations.Options;
13+
using Flurl;
14+
using Mapster;
15+
using Microsoft.Extensions.Configuration;
16+
using Microsoft.Extensions.DependencyInjection;
17+
using Nominatim.API.Address;
18+
using Nominatim.API.Geocoders;
19+
using Nominatim.API.Interfaces;
20+
using Nominatim.API.Web;
21+
22+
namespace Botticelli.Locations.Vk.Extensions;
23+
24+
public static class ServiceCollectionExtensions
25+
{
26+
/// <summary>
27+
/// Adds an OSM location provider
28+
/// </summary>
29+
/// <returns></returns>
30+
public static IServiceCollection AddOsmLocations(this IServiceCollection services,
31+
IConfiguration config,
32+
string url = "https://nominatim.openstreetmap.org")
33+
{
34+
services.AddHttpClient<OsmLocationProvider>();
35+
TypeAdapterConfig.GlobalSettings.Scan(Assembly.GetExecutingAssembly());
36+
return services.Configure<LocationsProcessorOptions>(config)
37+
.AddScoped<ICommandValidator<FindLocationsCommand>, PassValidator<FindLocationsCommand>>()
38+
.AddScoped<FindLocationsCommandProcessor<VkKeyboardMarkup>>()
39+
.AddScoped<ShowMapCommandProcessor<VkKeyboardMarkup>>()
40+
.AddScoped<ILocationProvider, OsmLocationProvider>()
41+
.AddScoped<INominatimWebInterface, NominatimWebInterface>()
42+
.AddScoped<IAddressSearcher, AddressSearcher>()
43+
.AddScoped<ILayoutSupplier<VkKeyboardMarkup>, VkLayoutSupplier>()
44+
.AddScoped<IForwardGeocoder, ForwardGeocoder>(sp =>
45+
new ForwardGeocoder(sp.GetRequiredService<INominatimWebInterface>(),
46+
Url.Combine(url, "search")))
47+
.AddScoped<IReverseGeocoder, ReverseGeocoder>(sp =>
48+
new ReverseGeocoder(sp.GetRequiredService<INominatimWebInterface>(),
49+
Url.Combine(url, "reverse")));
50+
}
51+
52+
public static IServiceProvider RegisterOsmLocationsCommands(this IServiceProvider sp,
53+
string url = "https://nominatim.openstreetmap.org")
54+
=> sp.RegisterBotCommand<FindLocationsCommand, FindLocationsCommandProcessor<VkKeyboardMarkup>, VkBot>()
55+
.RegisterBotCommand<ShowMapCommand, ShowMapCommandProcessor<VkKeyboardMarkup>, VkBot>();
56+
}

Botticelli.Locations/Botticelli.Locations.csproj

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,4 @@
2727
<ProjectReference Include="..\Botticelli.Framework\Botticelli.Framework.csproj" />
2828
</ItemGroup>
2929

30-
<ItemGroup>
31-
<ProjectReference Include="..\Botticelli.Framework.Controls\Botticelli.Framework.Controls.csproj" />
32-
<ProjectReference Include="..\Botticelli.Framework\Botticelli.Framework.csproj" />
33-
</ItemGroup>
34-
3530
</Project>

Botticelli.Locations/Commands/CommandProcessors/FindLocationsCommandProcessor.cs

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,9 @@
77
using Botticelli.Framework.Controls.Parsers;
88
using Botticelli.Framework.SendOptions;
99
using Botticelli.Locations.Integration;
10-
using Botticelli.Locations.Options;
1110
using Botticelli.Shared.API.Client.Requests;
1211
using Botticelli.Shared.ValueObjects;
1312
using Microsoft.Extensions.Logging;
14-
using Microsoft.Extensions.Options;
1513

1614
namespace Botticelli.Locations.Commands.CommandProcessors;
1715

@@ -20,19 +18,16 @@ public class FindLocationsCommandProcessor<TReplyMarkup> : CommandProcessor<Find
2018
{
2119
private readonly ILocationProvider _locationProvider;
2220
private readonly ILayoutSupplier<TReplyMarkup> _layoutSupplier;
23-
private readonly IOptionsSnapshot<LocationsProcessorOptions> _options;
2421

25-
22+
2623
public FindLocationsCommandProcessor(ILogger<FindLocationsCommandProcessor<TReplyMarkup>> logger,
2724
ICommandValidator<FindLocationsCommand> validator,
2825
MetricsProcessor metricsProcessor,
2926
ILocationProvider locationProvider,
30-
ILayoutSupplier<TReplyMarkup> layoutSupplier,
31-
IOptionsSnapshot<LocationsProcessorOptions> options) : base(logger, validator, metricsProcessor)
27+
ILayoutSupplier<TReplyMarkup> layoutSupplier) : base(logger, validator, metricsProcessor)
3228
{
3329
_locationProvider = locationProvider;
3430
_layoutSupplier = layoutSupplier;
35-
_options = options;
3631
}
3732

3833
protected override async Task InnerProcess(Message message, string args, CancellationToken token)
@@ -45,17 +40,14 @@ protected override async Task InnerProcess(Message message, string args, Cancell
4540

4641
foreach (var result in results)
4742
{
48-
var cdata = $"{_options.Value.ApiUrl}/" +
49-
$"#map={(int)_options.Value.InitialZoom}/" +
50-
$"{result.Latitude:N5}/" +
51-
$"{result.Longitude:N5}";
43+
var cdata = await _locationProvider.GetMapLink(result);
5244

5345
markup.AddItem(new Item
5446
{
5547
Control = new Button
5648
{
5749
Content = result.DisplayName,
58-
CallbackData = cdata
50+
CallbackData = $"/ShowMap {cdata}"
5951
},
6052
Params = new ItemParams()
6153
});
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
using Botticelli.Client.Analytics;
2+
using Botticelli.Framework.Commands.Processors;
3+
using Botticelli.Framework.Commands.Validators;
4+
using Botticelli.Framework.Controls.Parsers;
5+
using Botticelli.Locations.Integration;
6+
using Botticelli.Shared.API.Client.Requests;
7+
using Botticelli.Shared.ValueObjects;
8+
using Microsoft.Extensions.Logging;
9+
10+
namespace Botticelli.Locations.Commands.CommandProcessors;
11+
12+
public class ShowMapCommandProcessor<TReplyMarkup> : CommandProcessor<ShowMapCommand>
13+
where TReplyMarkup : class
14+
{
15+
private readonly ILocationProvider _locationProvider;
16+
private readonly ILayoutSupplier<TReplyMarkup> _layoutSupplier;
17+
18+
19+
public ShowMapCommandProcessor(ILogger<FindLocationsCommandProcessor<TReplyMarkup>> logger,
20+
ICommandValidator<ShowMapCommand> validator,
21+
MetricsProcessor metricsProcessor,
22+
ILocationProvider locationProvider,
23+
ILayoutSupplier<TReplyMarkup> layoutSupplier) : base(logger, validator, metricsProcessor)
24+
{
25+
_locationProvider = locationProvider;
26+
_layoutSupplier = layoutSupplier;
27+
}
28+
29+
protected override async Task InnerProcess(Message message, string args, CancellationToken token)
30+
{
31+
var request = new SendMessageRequest
32+
{
33+
Message = new Message
34+
{
35+
Uid = Guid.NewGuid().ToString(),
36+
ChatIds = message.ChatIds,
37+
Body = args,
38+
}
39+
};
40+
41+
await Bot.SendMessageAsync(request, token);
42+
}
43+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
using Botticelli.Framework.Commands;
2+
3+
namespace Botticelli.Locations.Commands;
4+
5+
public class ShowMapCommand : ICommand
6+
{
7+
public Guid Id { get; }
8+
}

0 commit comments

Comments
 (0)