Files
Playa/tests/Volcanic.AgenticCore.Telegram.Tests/BotSetupServiceTests.cs
EugeneTes 92a0061fdd feat(telegram): ADMIN_USER_ID may /impersonate another user
While on, the admin's updates are routed as the target user's (allow-list,
chat, workspace, session, settings, jobs) and the target chat's output goes
to the admin's chat. The target's own updates are dropped with a notice that
an admin is working with their account. In memory; /impersonate 0 stops.
2026-10-05 07:24:07 +00:00

81 lines
3.4 KiB
C#

using Microsoft.Extensions.Logging.Abstractions;
using Telegram.Bot.Exceptions;
using Telegram.Bot.Requests;
using Telegram.Bot.Requests.Abstractions;
using Volcanic.AgenticCore.Telegram.Rendering;
using Volcanic.AgenticCore.Telegram.Tests.Support;
namespace Volcanic.AgenticCore.Telegram.Tests;
public sealed class BotSetupServiceTests
{
private static (BotSetupService Service, FakeBotClient Bot) Create(Action<IRequest>? onSend)
{
var bot = new FakeBotClient { OnSend = onSend };
var options = new TelegramOptions
{
BotToken = "t",
AllowedUserIds = [Updates.AllowedUser, 2002],
ReconnectInitialDelay = TimeSpan.FromMilliseconds(5),
ReconnectMaxDelay = TimeSpan.FromMilliseconds(20),
};
var sender = new TelegramSender(bot, NullLogger<TelegramSender>.Instance);
return (new BotSetupService(bot, options, sender, NullLogger<BotSetupService>.Instance), bot);
}
[Fact]
public async Task Online_goes_once_to_the_owner_after_setup_succeeds_on_the_second_try()
{
var getMeCalls = 0;
var (service, bot) = Create(r =>
{
if (r is GetMeRequest && Interlocked.Increment(ref getMeCalls) == 1) throw FakeBotClient.NetworkDown();
});
await service.StartAsync(CancellationToken.None);
await service.ExecuteTask!.WaitAsync(TimeSpan.FromSeconds(5));
await service.StopAsync(CancellationToken.None);
Assert.Equal(2, bot.Requests.OfType<GetMeRequest>().Count());
var online = Assert.Single(bot.Sent);
Assert.Equal(Updates.AllowedUser, online.ChatId.Identifier);
Assert.Equal("🟢 Online.", online.Text);
}
[Fact]
public async Task A_forbidden_online_message_is_not_retried_and_does_not_stop_the_service()
{
var (service, bot) = Create(r =>
{
if (r is SendMessageRequest) throw new ApiRequestException("Forbidden: bot can't initiate conversation with a user", 403);
});
await service.StartAsync(CancellationToken.None);
await service.ExecuteTask!.WaitAsync(TimeSpan.FromSeconds(5));
Assert.True(service.ExecuteTask.IsCompletedSuccessfully);
Assert.Single(bot.Requests.OfType<SendMessageRequest>());
Assert.Single(bot.Requests.OfType<GetMeRequest>());
await service.StopAsync(CancellationToken.None);
}
[Fact]
public async Task The_admins_chat_menu_also_lists_impersonate()
{
var bot = new FakeBotClient();
var options = new TelegramOptions { BotToken = "t", AllowedUserIds = [Updates.AllowedUser], AdminUserId = 5005 };
var service = new BotSetupService(bot, options, new TelegramSender(bot, NullLogger<TelegramSender>.Instance), NullLogger<BotSetupService>.Instance);
await service.StartAsync(CancellationToken.None);
await service.ExecuteTask!.WaitAsync(TimeSpan.FromSeconds(5));
await service.StopAsync(CancellationToken.None);
var menus = bot.Requests.OfType<SetMyCommandsRequest>().ToList();
Assert.Equal(2, menus.Count);
Assert.DoesNotContain(menus[0].Commands, c => c.Command == "impersonate");
var admin = Assert.IsType<global::Telegram.Bot.Types.BotCommandScopeChat>(menus[1].Scope);
Assert.Equal(5005, admin.ChatId.Identifier);
Assert.Contains(menus[1].Commands, c => c.Command == "impersonate");
}
}