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>
Task<string?> SendAsync(SendRequest request, CancellationToken ct = default);
/// <summary>
/// Универсальный метод удаления сообщения.
/// </summary>
Task DeleteAsync(string chatId, string messageId, CancellationToken ct = default);
/// <summary>
/// Создать билдер альбома для отправки медиагруппы.
/// </summary>

View File

@@ -9,8 +9,14 @@ namespace BotPages.Core;
public static class PageContextAdapterExtensions
{
/// <summary>
/// Отправить универсальный запрос через привязанный адаптер.
/// Отправить сообщение универсальным запросом через привязанный адаптер.
/// </summary>
public static Task<string?> SendAsync(this PageContext ctx, SendRequest request, CancellationToken ct = default)
=> 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)> _album = new();
private bool _disableReplyKeyboard;
private string? _editMessageId = null;
private AdapterOptionsBag? _adapterOptions = null;
private string? _chatId = null;
/// <summary>Создать билдер сообщений.</summary>
public MessageBuilder(PageContext ctx) => _ctx = ctx;
@@ -32,6 +32,13 @@ public sealed class MessageBuilder
return this;
}
/// <summary>ID чата куда отрпавить сообщение.</summary>
public MessageBuilder ChatId(string chatId)
{
_chatId = chatId;
return this;
}
/// <summary>Текст сообщения.</summary>
public MessageBuilder Text(string text, MessageFormat format = MessageFormat.Plain)
{
@@ -40,13 +47,6 @@ public sealed class MessageBuilder
return this;
}
/// <summary>Редактировать сообщение.</summary>
public MessageBuilder EditMessage(string messagId)
{
_editMessageId = messagId;
return this;
}
/// <summary>Добавить inlineкнопку.</summary>
public MessageBuilder Inline(string label, string value)
{
@@ -129,10 +129,20 @@ public sealed class MessageBuilder
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>
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;
if (_disableReplyKeyboard) reply = new();
@@ -143,16 +153,16 @@ public sealed class MessageBuilder
{
var req = new SendRequest
{
ChatId = _ctx.Update.Chat.Id,
ChatId = _chatId ?? _ctx.Update.Chat.Id,
Text = _text,
TextFormat = _format,
Inline = _inline,
Reply = reply,
MessageId = _editMessageId,
MessageId = string.IsNullOrWhiteSpace(messageId) ? null : messageId,
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
{
ChatId = _ctx.Update.Chat.Id,
ChatId = _chatId ?? _ctx.Update.Chat.Id,
File = file,
Caption = caption,
CaptionFormat = captionFormat,
@@ -171,7 +181,7 @@ public sealed class MessageBuilder
var res = await _ctx.SendAsync(req, ct);
// сохранить первый возвращённый 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();
_album.Clear();
_editMessageId = 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;
}
/// <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 ---
private InlineKeyboardMarkup? BuildInlineMarkup(IEnumerable<IEnumerable<InlineButton>>? inline)

View File

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

View File

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