Files
EugeneTes a0cd2975b8 feat(telegram): save documents, videos and audio to the chat inbox
Content step 2 (InboundMedia.AddFilesAsync, InboxFiles): files land in <cwd>/inbox/<date>-<safe name>[-N], image documents within Telegram:InlineImageMaxBytes are attached inline, oversize files and failed downloads get a notice and no run. Documents, videos, audio and voice are accepted; the unsupported reply is now 'I can read text, photos, files and voice messages.'

Spec: Updates helpers are named DocumentMessage/VideoMessage/VoiceMessage/AudioMessage; the getFile 'file is too big' notice reads 'over 20 MB'; the too-large inline note is a parenthesised suffix after the size; size formats spelled out.
2026-09-26 22:09:16 +02:00

52 lines
2.0 KiB
C#

using Volcanic.AgenticCore.Telegram.Inbound;
using Volcanic.AgenticCore.Telegram.Rendering;
namespace Volcanic.AgenticCore.Telegram.Tests;
public sealed class InboxFilesTests : IDisposable
{
private readonly string _ws = Path.Combine(Path.GetTempPath(), "volcanic-inbox", Guid.NewGuid().ToString("N"));
private static readonly DateTimeOffset Now = new(2026, 9, 26, 10, 0, 0, TimeSpan.Zero);
public void Dispose() { try { Directory.Delete(_ws, true); } catch (IOException) { } }
[Theory]
[InlineData("report.pdf", "report.pdf")]
[InlineData("../../evil.sh", "evil.sh")]
[InlineData("..\\..\\win.bat", "win.bat")]
[InlineData(".bashrc", "bashrc")]
[InlineData("__init__.py", "init__.py")]
[InlineData("my report (final).pdf", "my_report__final_.pdf")]
[InlineData("отчёт.pdf", "отчёт.pdf")]
[InlineData("...", "file")]
[InlineData("", "file")]
[InlineData(null, "file")]
public void Hostile_names_are_sanitised(string? name, string expected) => Assert.Equal(expected, InboxFiles.SafeName(name));
[Fact]
public void Long_stems_and_extensions_are_capped()
{
Assert.Equal(new string('a', 80) + ".txt", InboxFiles.SafeName(new string('a', 300) + ".txt"));
Assert.Equal("x." + new string('b', 15), InboxFiles.SafeName("x." + new string('b', 30)));
}
[Fact]
public void Collisions_get_numbered_suffixes()
{
var paths = new List<string>();
for (var i = 0; i < 3; i++)
{
var (path, stream) = InboxFiles.Create(_ws, Now, "report.pdf");
stream.Dispose();
paths.Add(InboxFiles.Relative(_ws, path));
}
Assert.Equal(["inbox/2026-09-26-report.pdf", "inbox/2026-09-26-report-1.pdf", "inbox/2026-09-26-report-2.pdf"], paths);
}
[Theory]
[InlineData(5, "5 bytes")]
[InlineData(1536, "1.5 KB")]
[InlineData(1_258_291, "1.2 MB")]
public void Sizes_are_formatted(long bytes, string expected) => Assert.Equal(expected, TelegramLimits.FormatSize(bytes));
}