Skip to content
This repository was archived by the owner on Oct 12, 2025. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 9 additions & 5 deletions Lagrange.OneBot/Core/Operation/Ability/UploadImageOperation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,17 @@ public class UploadImageOperation : IOperation
{
public async Task<OneBotResult> HandleOperation(BotContext context, JsonNode? payload)
{
if (payload?["file"]?.ToString() is { } file && CommonResolver.ResolveStream(file) is { } stream)
if (payload?["file"]?.ToString() is { } file)
{
var entity = new ImageEntity(stream);
var url = await context.UploadImage(entity);
return new OneBotResult(url, 0, "ok");
using var stream = await CommonResolver.ResolveStreamAsync(file);
if (stream != null)
{
var entity = new ImageEntity(stream);
var url = await context.UploadImage(entity);
return new OneBotResult(url, 0, "ok");
}
}

throw new Exception();
throw new Exception("Failed to resolve image file");
}
}
14 changes: 9 additions & 5 deletions Lagrange.OneBot/Core/Operation/Generic/OcrImageOperation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,16 @@ public class OcrImageOperation() : IOperation
{
public async Task<OneBotResult> HandleOperation(BotContext context, JsonNode? payload)
{
if (payload.Deserialize<OneBotOcrImage>(SerializerOptions.DefaultOptions) is { } data && CommonResolver.ResolveStream(data.Image) is { } stream)
if (payload.Deserialize<OneBotOcrImage>(SerializerOptions.DefaultOptions) is { } data)
{
var entity = new ImageEntity(stream);
var res = await context.OcrImage(entity);
return new OneBotResult(res, 0, "ok");
using var stream = await CommonResolver.ResolveStreamAsync(data.Image);
if (stream != null)
{
var entity = new ImageEntity(stream);
var res = await context.OcrImage(entity);
return new OneBotResult(res, 0, "ok");
}
}
throw new Exception();
throw new Exception("Failed to resolve image for OCR");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,15 @@ public async Task<OneBotResult> HandleOperation(BotContext context, JsonNode? pa
{
if (payload?["file"]?.ToString() is { } portrait)
{
var image = CommonResolver.ResolveStream(portrait);
if (image == null) throw new Exception();

var imageEntity = new ImageEntity(image);
bool result = await context.SetAvatar(imageEntity);
return new OneBotResult(null, result ? 0 : 1, "");
using var image = await CommonResolver.ResolveStreamAsync(portrait);
if (image != null)
{
var imageEntity = new ImageEntity(image);
bool result = await context.SetAvatar(imageEntity);
return new OneBotResult(null, result ? 0 : 1, result ? "ok" : "failed");
}
}

throw new Exception();
throw new Exception("Failed to resolve avatar image");
}
}
54 changes: 50 additions & 4 deletions Lagrange.OneBot/Message/Entity/CommonResolver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,30 +4,76 @@ public static class CommonResolver
{
private static readonly HttpClient Client = new();

public static async Task<byte[]?> ResolveAsync(string url, CancellationToken cancellationToken = default)
{
try
{
if (url.StartsWith("base64://"))
return Convert.FromBase64String(url.Substring("base64://".Length));

Uri uri = new(url);

return uri.Scheme switch
{
"http" or "https" => await (await Client.GetAsync(uri, cancellationToken)).Content.ReadAsByteArrayAsync(cancellationToken),
"file" => await File.ReadAllBytesAsync(Path.GetFullPath(uri.LocalPath), cancellationToken),
_ => null,
};
}
catch (Exception ex) when (ex is HttpRequestException or FileNotFoundException or DirectoryNotFoundException)
{
return null;
}
}

public static async Task<Stream?> ResolveStreamAsync(string url, CancellationToken cancellationToken = default)
{
try
{
if (url.StartsWith("base64://"))
return new MemoryStream(Convert.FromBase64String(url.Substring("base64://".Length)));

Uri uri = new(url);

return uri.Scheme switch
{
"http" or "https" => await (await Client.GetAsync(uri, cancellationToken)).Content.ReadAsStreamAsync(cancellationToken),
"file" => new FileStream(Path.GetFullPath(uri.LocalPath), FileMode.Open, FileAccess.Read, FileShare.Read),
_ => null,
};
}
catch (Exception ex) when (ex is HttpRequestException or FileNotFoundException or DirectoryNotFoundException)
{
return null;
}
}

public static byte[]? Resolve(string url)
{
if (url.StartsWith("base64://")) return Convert.FromBase64String(url.Replace("base64://", ""));
if (url.StartsWith("base64://"))
return Convert.FromBase64String(url.Substring("base64://".Length));

Uri uri = new(url);

return uri.Scheme switch
{
"http" or "https" => Client.GetAsync(uri).Result.Content.ReadAsByteArrayAsync().Result,
"file" => File.ReadAllBytes(Path.GetFullPath(uri.LocalPath)),
"http" or "https" => ResolveAsync(url).GetAwaiter().GetResult(),
_ => null,
};
}

public static Stream? ResolveStream(string url)
{
if (url.StartsWith("base64://")) return new MemoryStream(Convert.FromBase64String(url.Replace("base64://", "")));
if (url.StartsWith("base64://"))
return new MemoryStream(Convert.FromBase64String(url.Substring("base64://".Length)));

Uri uri = new(url);

return uri.Scheme switch
{
"http" or "https" => Client.GetAsync(uri).Result.Content.ReadAsStreamAsync().Result,
"file" => new FileStream(Path.GetFullPath(uri.LocalPath), FileMode.Open, FileAccess.Read, FileShare.Read),
"http" or "https" => ResolveStreamAsync(url).GetAwaiter().GetResult(),
_ => null,
};
}
Expand Down