3 Commits

Author SHA1 Message Date
69ff3cf7d4 Исправлена очистка кнопок при отправке сообщения
All checks were successful
CI / build-test (push) Successful in 42s
Release / pack-and-publish (release) Successful in 47s
2026-01-13 21:24:27 +03:00
0ed47b2b90 Исправлен возврат messageId при отправке сообщения
All checks were successful
CI / build-test (push) Successful in 38s
Release / pack-and-publish (release) Successful in 43s
2026-01-13 21:22:06 +03:00
FrigaT
f29e72a6f2 Добавлен метод удаления сообщения
All checks were successful
CI / build-test (push) Successful in 48s
Release / pack-and-publish (release) Successful in 51s
2026-01-13 20:38:41 +03:00
6 changed files with 55 additions and 20 deletions

View File

@@ -18,6 +18,11 @@ public interface IMessengerAdapter
/// </summary> /// </summary>
Task<string?> SendAsync(SendRequest request, CancellationToken ct = default); Task<string?> SendAsync(SendRequest request, CancellationToken ct = default);
/// <summary>
/// Универсальный метод удаления сообщения.
/// </summary>
Task DeleteAsync(string chatId, string messageId, CancellationToken ct = default);
/// <summary> /// <summary>
/// Создать билдер альбома для отправки медиагруппы. /// Создать билдер альбома для отправки медиагруппы.
/// </summary> /// </summary>

View File

@@ -9,8 +9,14 @@ namespace BotPages.Core;
public static class PageContextAdapterExtensions public static class PageContextAdapterExtensions
{ {
/// <summary> /// <summary>
/// Отправить универсальный запрос через привязанный адаптер. /// Отправить сообщение универсальным запросом через привязанный адаптер.
/// </summary> /// </summary>
public static Task<string?> SendAsync(this PageContext ctx, SendRequest request, CancellationToken ct = default) public static Task<string?> SendAsync(this PageContext ctx, SendRequest request, CancellationToken ct = default)
=> ctx.Adapter.SendAsync(request, ct); => ctx.Adapter.SendAsync(request, ct);
/// <summary>
/// Удалить сообщение через привязанный адаптер.
/// </summary>
public static Task DeleteAsync(this PageContext ctx, string chatId, string messageId, CancellationToken ct = default)
=> ctx.Adapter.DeleteAsync(chatId, messageId, ct);
} }

View File

@@ -16,8 +16,8 @@ public sealed class MessageBuilder
private readonly List<(FileDescriptor file, string? caption, MessageFormat? captionFormat)> _files = new(); private readonly List<(FileDescriptor file, string? caption, MessageFormat? captionFormat)> _files = new();
private readonly List<(FileDescriptor file, string? caption, MessageFormat? captionFormat)> _album = new(); private readonly List<(FileDescriptor file, string? caption, MessageFormat? captionFormat)> _album = new();
private bool _disableReplyKeyboard; private bool _disableReplyKeyboard;
private string? _editMessageId = null;
private AdapterOptionsBag? _adapterOptions = null; private AdapterOptionsBag? _adapterOptions = null;
private string? _chatId = null;
/// <summary>Создать билдер сообщений.</summary> /// <summary>Создать билдер сообщений.</summary>
public MessageBuilder(PageContext ctx) => _ctx = ctx; public MessageBuilder(PageContext ctx) => _ctx = ctx;
@@ -32,6 +32,13 @@ public sealed class MessageBuilder
return this; return this;
} }
/// <summary>ID чата куда отрпавить сообщение.</summary>
public MessageBuilder ChatId(string chatId)
{
_chatId = chatId;
return this;
}
/// <summary>Текст сообщения.</summary> /// <summary>Текст сообщения.</summary>
public MessageBuilder Text(string text, MessageFormat format = MessageFormat.Plain) public MessageBuilder Text(string text, MessageFormat format = MessageFormat.Plain)
{ {
@@ -40,13 +47,6 @@ public sealed class MessageBuilder
return this; return this;
} }
/// <summary>Редактировать сообщение.</summary>
public MessageBuilder EditMessage(string messagId)
{
_editMessageId = messagId;
return this;
}
/// <summary>Добавить inlineкнопку.</summary> /// <summary>Добавить inlineкнопку.</summary>
public MessageBuilder Inline(string label, string value) public MessageBuilder Inline(string label, string value)
{ {
@@ -129,10 +129,20 @@ public sealed class MessageBuilder
return this; return this;
} }
/// <summary>Удалить сообщение.</summary>
public async Task DeleteAsync(string messageId, CancellationToken ct = default)
{
await _ctx.DeleteAsync(this._chatId ?? _ctx.Update.Chat.Id, messageId, ct);
}
/// <summary>Отправить собранное сообщение.</summary> /// <summary>Отправить собранное сообщение.</summary>
public async Task<string?> SendAsync(CancellationToken ct = default) public async Task<string?> SendAsync(CancellationToken ct = default)
=> await SendAsync(string.Empty, ct);
/// <summary>Редактировать сообщение.</summary>
public async Task<string?> SendAsync(string messageId, CancellationToken ct = default)
{ {
string? messageId = null; string? outMessageId = null;
List<List<ReplyButton>>? reply = null; List<List<ReplyButton>>? reply = null;
if (_disableReplyKeyboard) reply = new(); if (_disableReplyKeyboard) reply = new();
@@ -143,16 +153,16 @@ public sealed class MessageBuilder
{ {
var req = new SendRequest var req = new SendRequest
{ {
ChatId = _ctx.Update.Chat.Id, ChatId = _chatId ?? _ctx.Update.Chat.Id,
Text = _text, Text = _text,
TextFormat = _format, TextFormat = _format,
Inline = _inline, Inline = _inline,
Reply = reply, Reply = reply,
MessageId = _editMessageId, MessageId = string.IsNullOrWhiteSpace(messageId) ? null : messageId,
AdapterOptions = _adapterOptions AdapterOptions = _adapterOptions
}; };
messageId = await _ctx.SendAsync(req, ct); outMessageId = await _ctx.SendAsync(req, ct);
} }
// Файлы // Файлы
@@ -160,7 +170,7 @@ public sealed class MessageBuilder
{ {
var req = new SendRequest var req = new SendRequest
{ {
ChatId = _ctx.Update.Chat.Id, ChatId = _chatId ?? _ctx.Update.Chat.Id,
File = file, File = file,
Caption = caption, Caption = caption,
CaptionFormat = captionFormat, CaptionFormat = captionFormat,
@@ -171,7 +181,7 @@ public sealed class MessageBuilder
var res = await _ctx.SendAsync(req, ct); var res = await _ctx.SendAsync(req, ct);
// сохранить первый возвращённый id сообщения // сохранить первый возвращённый id сообщения
if (messageId is null && res is not null) messageId = res; if (outMessageId is null && res is not null) outMessageId = res;
} }
// Альбом // Альбом
@@ -187,9 +197,12 @@ public sealed class MessageBuilder
_files.Clear(); _files.Clear();
_album.Clear(); _album.Clear();
_editMessageId = null;
_adapterOptions = null; _adapterOptions = null;
_chatId = null;
return messageId; _reply.Clear();
_inline.Clear();
return outMessageId;
} }
} }

View File

@@ -137,6 +137,18 @@ public sealed class TelegramAdapter : IMessengerAdapterSetup
return null; return null;
} }
/// <inheritdoc/>
public Task DeleteAsync(string chatId, string messageId, CancellationToken ct = default)
{
if (_client is null)
{
_logger.Log(LogLevel.Critical, $"{MessengerType} client is not initialized.");
return null;
}
return _client.DeleteMessage(chatId, Convert.ToInt32(messageId), ct);
}
// --- Helpers --- // --- Helpers ---
private InlineKeyboardMarkup? BuildInlineMarkup(IEnumerable<IEnumerable<InlineButton>>? inline) private InlineKeyboardMarkup? BuildInlineMarkup(IEnumerable<IEnumerable<InlineButton>>? inline)

View File

@@ -23,7 +23,7 @@ public sealed class FileSendPage : SingletonPage
GetStreamAsync = _ => Task.FromResult<Stream>(stream) GetStreamAsync = _ => Task.FromResult<Stream>(stream)
}; };
await new MessageBuilder(ctx) var msg = await new MessageBuilder(ctx)
.Text("Вот пример отправки нового файла 📎", MessageFormat.Markdown) .Text("Вот пример отправки нового файла 📎", MessageFormat.Markdown)
.File(demoFile, "Демонстрационный файл") .File(demoFile, "Демонстрационный файл")
.SendAsync(ct); .SendAsync(ct);

View File

@@ -21,8 +21,7 @@ public sealed class SubmitPage : SingletonPage
Thread.Sleep(TimeSpan.FromMilliseconds(200)); Thread.Sleep(TimeSpan.FromMilliseconds(200));
await new MessageBuilder(ctx) await new MessageBuilder(ctx)
.Text($"Отправка заявки\n{i}%") .Text($"Отправка заявки\n{i}%")
.EditMessage(messageId!) .SendAsync(messageId, ct);
.SendAsync(ct);
} }
while (i < 100); while (i < 100);