diff --git a/src/.config/dotnet-tools.json b/src/.config/dotnet-tools.json
index 40d4373..4f48799 100644
--- a/src/.config/dotnet-tools.json
+++ b/src/.config/dotnet-tools.json
@@ -3,10 +3,11 @@
"isRoot": true,
"tools": {
"dotnet-ef": {
- "version": "8.0.10",
+ "version": "9.0.0",
"commands": [
"dotnet-ef"
- ]
+ ],
+ "rollForward": false
}
}
}
\ No newline at end of file
diff --git a/src/Directory.Packages.props b/src/Directory.Packages.props
index 224936f..2976937 100644
--- a/src/Directory.Packages.props
+++ b/src/Directory.Packages.props
@@ -15,7 +15,6 @@
all
runtime; build; native; contentfiles; analyzers; buildtransitive
-
@@ -33,9 +32,10 @@
-
+
-
+
+
@@ -46,8 +46,7 @@
-
-
+
@@ -56,4 +55,4 @@
runtime; build; native; contentfiles; analyzers; buildtransitive
-
+
\ No newline at end of file
diff --git a/src/SpinRallyBot.Bot/Services/BotInit.cs b/src/SpinRallyBot.Bot/Services/BotInit.cs
index 930fe6a..391ec32 100644
--- a/src/SpinRallyBot.Bot/Services/BotInit.cs
+++ b/src/SpinRallyBot.Bot/Services/BotInit.cs
@@ -3,20 +3,20 @@ namespace SpinRallyBot.Services;
internal class BotInit : IHostedService {
private readonly ITelegramBotClient _botClient;
private readonly ILogger _logger;
- private readonly IScopedMediator _mediator;
+ private readonly IServiceProvider _serviceProvider;
- public BotInit(ITelegramBotClient botClient,
- ILogger logger,
- IScopedMediator mediator) {
+ public BotInit(ITelegramBotClient botClient, ILogger logger, IServiceProvider serviceProvider) {
_botClient = botClient;
_logger = logger;
- _mediator = mediator;
+ _serviceProvider = serviceProvider;
}
public async Task StartAsync(CancellationToken cancellationToken) {
_logger.LogInformation("Initialize bot (commands, etc)");
await InitCommands(cancellationToken);
- await _mediator.Send(new InitUpdaterJob(false), cancellationToken);
+ await using AsyncServiceScope scope = _serviceProvider.CreateAsyncScope();
+ var mediator = scope.ServiceProvider.GetRequiredService();
+ await mediator.Send(new InitUpdaterJob(false), cancellationToken);
}
public Task StopAsync(CancellationToken cancellationToken) {
diff --git a/src/SpinRallyBot.Bot/SpinRallyBot.Bot.csproj b/src/SpinRallyBot.Bot/SpinRallyBot.Bot.csproj
index e70a61c..36a752d 100644
--- a/src/SpinRallyBot.Bot/SpinRallyBot.Bot.csproj
+++ b/src/SpinRallyBot.Bot/SpinRallyBot.Bot.csproj
@@ -2,13 +2,11 @@
-
-
diff --git a/src/SpinRallyBot.Bot/Utils/UserExtensions.cs b/src/SpinRallyBot.Bot/Utils/UserExtensions.cs
index 8eefd7f..f8bdbdf 100644
--- a/src/SpinRallyBot.Bot/Utils/UserExtensions.cs
+++ b/src/SpinRallyBot.Bot/Utils/UserExtensions.cs
@@ -1,11 +1,16 @@
-using Telegram.Bot.Extensions.Markup;
-
namespace SpinRallyBot.Utils;
public static class UserExtensions {
+ private static string MentionMarkdown(ChatId userId, string name, ParseMode parseMode = ParseMode.Markdown) {
+ string tgLink = $"tg://user?id={userId}";
+ return parseMode == ParseMode.Markdown
+ ? $"[{name}]({tgLink})"
+ : $"[{StringExtensions.EscapeMarkdown(name, parseMode)}]({tgLink})";
+ }
+
public static string ToMentionMarkdownV2(this User user) {
- return Tools.MentionMarkdown(user.Id,
- user.Username is not null ? $"@{user.Username}" : $"{user.FirstName} {user.LastName}".Trim(),
+ return MentionMarkdown(
+ user.Id, user.Username is not null ? $"@{user.Username}" : $"{user.FirstName} {user.LastName}".Trim(),
ParseMode.MarkdownV2);
}
}
diff --git a/src/SpinRallyBot.Database.Postgres/Migrations/PostgresDbContextModelSnapshot.cs b/src/SpinRallyBot.Database.Postgres/Migrations/PostgresDbContextModelSnapshot.cs
index c06a902..6fd7ee7 100644
--- a/src/SpinRallyBot.Database.Postgres/Migrations/PostgresDbContextModelSnapshot.cs
+++ b/src/SpinRallyBot.Database.Postgres/Migrations/PostgresDbContextModelSnapshot.cs
@@ -18,7 +18,7 @@ protected override void BuildModel(ModelBuilder modelBuilder)
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("Npgsql:CollationDefinition:case_insensitive", "en-u-ks-primary,en-u-ks-primary,icu,False")
- .HasAnnotation("ProductVersion", "8.0.1")
+ .HasAnnotation("ProductVersion", "9.0.0")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
diff --git a/src/SpinRallyBot.Database.Sqlite/Migrations/SqliteDbContextModelSnapshot.cs b/src/SpinRallyBot.Database.Sqlite/Migrations/SqliteDbContextModelSnapshot.cs
index 1a6da06..e826b1c 100644
--- a/src/SpinRallyBot.Database.Sqlite/Migrations/SqliteDbContextModelSnapshot.cs
+++ b/src/SpinRallyBot.Database.Sqlite/Migrations/SqliteDbContextModelSnapshot.cs
@@ -15,7 +15,7 @@ partial class SqliteDbContextModelSnapshot : ModelSnapshot
protected override void BuildModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
- modelBuilder.HasAnnotation("ProductVersion", "8.0.1");
+ modelBuilder.HasAnnotation("ProductVersion", "9.0.0");
modelBuilder.Entity("SpinRallyBot.Models.BackNavigationEntity", b =>
{
@@ -78,7 +78,7 @@ protected override void BuildModel(ModelBuilder modelBuilder)
b.HasKey("PlayerUrl");
- b.ToTable("Players");
+ b.ToTable("Players", (string)null);
});
modelBuilder.Entity("SpinRallyBot.Models.SubscriptionEntity", b =>
diff --git a/src/SpinRallyBot.Utils/SpinRallyBot.Utils.csproj b/src/SpinRallyBot.Utils/SpinRallyBot.Utils.csproj
index 59aa644..959b532 100644
--- a/src/SpinRallyBot.Utils/SpinRallyBot.Utils.csproj
+++ b/src/SpinRallyBot.Utils/SpinRallyBot.Utils.csproj
@@ -1,5 +1,5 @@
-
+
diff --git a/src/SpinRallyBot.Utils/StringExtensions.cs b/src/SpinRallyBot.Utils/StringExtensions.cs
index b9e2a9e..28aee82 100644
--- a/src/SpinRallyBot.Utils/StringExtensions.cs
+++ b/src/SpinRallyBot.Utils/StringExtensions.cs
@@ -1,10 +1,47 @@
-using Telegram.Bot.Extensions.Markup;
+using System.Collections.Immutable;
+using System.Text.RegularExpressions;
using Telegram.Bot.Types.Enums;
namespace SpinRallyBot;
public static class StringExtensions {
+ private static ImmutableDictionary<(ParseMode parseMode, MessageEntityType? entityType), string> Escaped =>
+ new Dictionary<(ParseMode parseMode, MessageEntityType? entityType), string> {
+ { (ParseMode.Markdown, null), Regex.Escape("_*`[") },
+ { (ParseMode.MarkdownV2, MessageEntityType.Pre), Regex.Escape("""\`""") },
+ { (ParseMode.MarkdownV2, MessageEntityType.Code), Regex.Escape("""\`""") },
+ { (ParseMode.MarkdownV2, MessageEntityType.TextLink), Regex.Escape("""\)""") }, {
+ (ParseMode.MarkdownV2, null),
+ Regex.Escape(str: """\_*()~`>#+-=|{}.![]""")
+ .Replace("]", "\\]", StringComparison.Ordinal)
+ .Replace("-", "\\-", StringComparison.Ordinal)
+ },
+ }.ToImmutableDictionary();
+
+ public static string EscapeMarkdown(
+ string text,
+ ParseMode parseMode = ParseMode.Markdown,
+ MessageEntityType? entityType = default) {
+ string escaped = (parseMode, entityType) switch {
+ (ParseMode.Markdown, _) => Escaped[(ParseMode.Markdown, null)],
+ (ParseMode.MarkdownV2, MessageEntityType.Pre) => Escaped[(ParseMode.MarkdownV2, MessageEntityType.Pre)],
+ (ParseMode.MarkdownV2, MessageEntityType.Code) => Escaped[(ParseMode.MarkdownV2, MessageEntityType.Code)],
+ (ParseMode.MarkdownV2, MessageEntityType.TextLink) => Escaped[
+ (ParseMode.MarkdownV2, MessageEntityType.TextLink)],
+ (ParseMode.MarkdownV2, _) => Escaped[(ParseMode.MarkdownV2, null)],
+ _ => throw new ArgumentException("Only ParseMode.Markdown and ParseMode.MarkdownV2 allowed.",
+ nameof(parseMode)),
+ };
+
+ return Regex.Replace(
+ input: text,
+ pattern: $"([{escaped}])",
+ replacement: """\$1""",
+ RegexOptions.CultureInvariant,
+ matchTimeout: TimeSpan.FromSeconds(1));
+ }
+
public static string ToEscapedMarkdownV2(this string str) {
- return Tools.EscapeMarkdown(str, ParseMode.MarkdownV2);
+ return EscapeMarkdown(str, ParseMode.MarkdownV2);
}
}
diff --git a/src/SpinRallyBot/HostApplicationBuilderExtensions.cs b/src/SpinRallyBot/HostApplicationBuilderExtensions.cs
index 286581c..bc0b872 100644
--- a/src/SpinRallyBot/HostApplicationBuilderExtensions.cs
+++ b/src/SpinRallyBot/HostApplicationBuilderExtensions.cs
@@ -1,10 +1,10 @@
-using Newtonsoft.Json;
-using Newtonsoft.Json.Serialization;
+using System.Text.Json;
using Quartz;
using Serilog.Enrichers.Sensitive;
using SpinRallyBot.Events.PlayerRatingChangedConsumers;
using SpinRallyBot.Serilog;
using SpinRallyBot.Subscriptions;
+using Telegram.Bot;
namespace SpinRallyBot;
@@ -45,12 +45,12 @@ public static HostApplicationBuilder AddMassTransit(this HostApplicationBuilder
if (builder.Configuration["AMQP_URI"] is { } amqpUri) {
x.UsingRabbitMq((context, cfg) => {
cfg.Host(amqpUri);
- ConfigureNewtonsoft(cfg);
+ cfg.ConfigureJsonSerializerOptions(AddJsonBotApiJsonSerializerOptions);
cfg.ConfigureEndpoints(context);
});
} else {
x.UsingInMemory((context, cfg) => {
- ConfigureNewtonsoft(cfg);
+ cfg.ConfigureJsonSerializerOptions(AddJsonBotApiJsonSerializerOptions);
cfg.ConfigureEndpoints(context);
});
}
@@ -62,19 +62,6 @@ public static HostApplicationBuilder AddMassTransit(this HostApplicationBuilder
return builder;
}
- private static void ConfigureNewtonsoft(IBusFactoryConfigurator cfg) {
- cfg.UseNewtonsoftJsonSerializer();
- cfg.ConfigureNewtonsoftJsonSerializer(_ => new JsonSerializerSettings {
- NullValueHandling = NullValueHandling.Include,
- ContractResolver = new CamelCasePropertyNamesContractResolver {
- IgnoreSerializableAttribute = true,
- IgnoreShouldSerializeMembers = true
- },
- DateFormatHandling = DateFormatHandling.IsoDateFormat,
- DateTimeZoneHandling = DateTimeZoneHandling.Unspecified
- });
- }
-
public static HostApplicationBuilder AddQuartz(this HostApplicationBuilder builder) {
builder.Services.AddQuartz(q => {
q.MisfireThreshold = TimeSpan.FromHours(1);
@@ -97,8 +84,15 @@ public static HostApplicationBuilder AddQuartz(this HostApplicationBuilder build
default:
throw new Exception($"Unsupported provider: {provider}");
}
+
+ s.UseSystemTextJsonSerializer();
});
});
return builder;
}
+
+ private static JsonSerializerOptions AddJsonBotApiJsonSerializerOptions(JsonSerializerOptions options) {
+ JsonBotAPI.Configure(options);
+ return options;
+ }
}
diff --git a/src/SpinRallyBot/SpinRallyBot.csproj b/src/SpinRallyBot/SpinRallyBot.csproj
index f03ad1f..3e78a7f 100644
--- a/src/SpinRallyBot/SpinRallyBot.csproj
+++ b/src/SpinRallyBot/SpinRallyBot.csproj
@@ -23,6 +23,7 @@
runtime; build; native; contentfiles; analyzers; buildtransitive
+