| | | 1 | | using Microsoft.Extensions.DependencyInjection; |
| | | 2 | | using TeleFlow.Telegram.Schema.Abstractions; |
| | | 3 | | using TeleFlow.Telegram.Schema.Types; |
| | | 4 | | |
| | | 5 | | namespace TeleFlow.Telegram; |
| | | 6 | | |
| | | 7 | | public sealed class ChatActions |
| | | 8 | | { |
| | 1 | 9 | | private static readonly TimeSpan DefaultRepeatDelay = TimeSpan.FromSeconds(4); |
| | | 10 | | |
| | | 11 | | private readonly TelegramUpdateContext _context; |
| | | 12 | | |
| | | 13 | | internal ChatActions(TelegramUpdateContext context) |
| | | 14 | | { |
| | 815 | 15 | | _context = context; |
| | 815 | 16 | | } |
| | | 17 | | |
| | | 18 | | public async ValueTask<ChatActionLease> ActionAsync( |
| | | 19 | | ChatAction action, |
| | | 20 | | CancellationToken cancellationToken = default) |
| | | 21 | | { |
| | 12 | 22 | | if (!TryResolveTarget(out var target)) |
| | | 23 | | { |
| | 1 | 24 | | throw new InvalidOperationException( |
| | 1 | 25 | | "The current Telegram update does not expose a Telegram chat target for chat actions."); |
| | | 26 | | } |
| | | 27 | | |
| | 11 | 28 | | var effectiveToken = ResolveCancellationToken(cancellationToken); |
| | 11 | 29 | | await SendChatActionAsync(_context.Bot, target, action, effectiveToken).ConfigureAwait(false); |
| | | 30 | | |
| | 9 | 31 | | var timeProvider = _context.Services.GetService<TimeProvider>() ?? TimeProvider.System; |
| | 9 | 32 | | return new ChatActionLease( |
| | 9 | 33 | | _context.Bot, |
| | 9 | 34 | | target, |
| | 9 | 35 | | action, |
| | 9 | 36 | | timeProvider, |
| | 9 | 37 | | DefaultRepeatDelay, |
| | 9 | 38 | | effectiveToken); |
| | 9 | 39 | | } |
| | | 40 | | |
| | | 41 | | internal static Task<bool> SendChatActionAsync( |
| | | 42 | | ITelegramClient bot, |
| | | 43 | | TelegramChatActionTarget target, |
| | | 44 | | ChatAction action, |
| | | 45 | | CancellationToken cancellationToken) |
| | | 46 | | { |
| | 13 | 47 | | ArgumentException.ThrowIfNullOrWhiteSpace(action.Value, nameof(action)); |
| | | 48 | | |
| | 12 | 49 | | return bot.SendChatActionAsync( |
| | 12 | 50 | | IntegerString.From(target.ChatId), |
| | 12 | 51 | | action.Value, |
| | 12 | 52 | | businessConnectionId: target.BusinessConnectionId, |
| | 12 | 53 | | messageThreadId: target.MessageThreadId, |
| | 12 | 54 | | cancellationToken: cancellationToken); |
| | | 55 | | } |
| | | 56 | | |
| | | 57 | | private bool TryResolveTarget(out TelegramChatActionTarget target) |
| | | 58 | | { |
| | 12 | 59 | | if (_context is MessageContext messageContext) |
| | | 60 | | { |
| | 9 | 61 | | target = CreateMessageTarget(messageContext.TelegramMessage); |
| | 9 | 62 | | return true; |
| | | 63 | | } |
| | | 64 | | |
| | 3 | 65 | | if (_context is CallbackQueryContext callbackContext) |
| | | 66 | | { |
| | 2 | 67 | | return TryResolveCallbackTarget(callbackContext.TelegramCallbackQuery, out target); |
| | | 68 | | } |
| | | 69 | | |
| | 1 | 70 | | if (_context is ChatMemberUpdatedContext chatMemberContext) |
| | | 71 | | { |
| | 1 | 72 | | target = new TelegramChatActionTarget( |
| | 1 | 73 | | chatMemberContext.TelegramChat.Id, |
| | 1 | 74 | | BusinessConnectionId: null, |
| | 1 | 75 | | MessageThreadId: null); |
| | 1 | 76 | | return true; |
| | | 77 | | } |
| | | 78 | | |
| | 0 | 79 | | if (_context.Update.Message is { } message) |
| | | 80 | | { |
| | 0 | 81 | | target = CreateMessageTarget(message); |
| | 0 | 82 | | return true; |
| | | 83 | | } |
| | | 84 | | |
| | 0 | 85 | | if (_context.Update.CallbackQuery is { } callbackQuery) |
| | | 86 | | { |
| | 0 | 87 | | return TryResolveCallbackTarget(callbackQuery, out target); |
| | | 88 | | } |
| | | 89 | | |
| | 0 | 90 | | var chatMemberUpdated = _context.Update.ChatMember ?? _context.Update.MyChatMember; |
| | 0 | 91 | | if (chatMemberUpdated is not null) |
| | | 92 | | { |
| | 0 | 93 | | target = new TelegramChatActionTarget( |
| | 0 | 94 | | chatMemberUpdated.Chat.Id, |
| | 0 | 95 | | BusinessConnectionId: null, |
| | 0 | 96 | | MessageThreadId: null); |
| | 0 | 97 | | return true; |
| | | 98 | | } |
| | | 99 | | |
| | 0 | 100 | | target = default; |
| | 0 | 101 | | return false; |
| | | 102 | | } |
| | | 103 | | |
| | | 104 | | private static TelegramChatActionTarget CreateMessageTarget(Message message) |
| | | 105 | | { |
| | 10 | 106 | | return new TelegramChatActionTarget( |
| | 10 | 107 | | message.Chat.Id, |
| | 10 | 108 | | message.BusinessConnectionId, |
| | 10 | 109 | | message.MessageThreadId); |
| | | 110 | | } |
| | | 111 | | |
| | | 112 | | private static bool TryResolveCallbackTarget( |
| | | 113 | | CallbackQuery callbackQuery, |
| | | 114 | | out TelegramChatActionTarget target) |
| | | 115 | | { |
| | 2 | 116 | | if (callbackQuery.Message is null) |
| | | 117 | | { |
| | 1 | 118 | | target = default; |
| | 1 | 119 | | return false; |
| | | 120 | | } |
| | | 121 | | |
| | 1 | 122 | | if (callbackQuery.Message.TryGetMessage(out var accessibleMessage) && |
| | 1 | 123 | | accessibleMessage is not null) |
| | | 124 | | { |
| | 1 | 125 | | target = CreateMessageTarget(accessibleMessage); |
| | 1 | 126 | | return true; |
| | | 127 | | } |
| | | 128 | | |
| | 0 | 129 | | if (callbackQuery.Message.TryGetInaccessibleMessage(out var inaccessibleMessage) && |
| | 0 | 130 | | inaccessibleMessage is not null) |
| | | 131 | | { |
| | 0 | 132 | | target = new TelegramChatActionTarget( |
| | 0 | 133 | | inaccessibleMessage.Chat.Id, |
| | 0 | 134 | | BusinessConnectionId: null, |
| | 0 | 135 | | MessageThreadId: null); |
| | 0 | 136 | | return true; |
| | | 137 | | } |
| | | 138 | | |
| | 0 | 139 | | target = default; |
| | 0 | 140 | | return false; |
| | | 141 | | } |
| | | 142 | | |
| | | 143 | | private CancellationToken ResolveCancellationToken(CancellationToken cancellationToken) |
| | | 144 | | { |
| | 11 | 145 | | return cancellationToken.CanBeCanceled ? cancellationToken : _context.CancellationToken; |
| | | 146 | | } |
| | | 147 | | } |