Skip to content
This repository was archived by the owner on Oct 12, 2025. It is now read-only.

Commit e5db4df

Browse files
authored
[Core] Fixed various issues (#821)
* [Core] Fixed various issues 1. ForwardEntity in MultiEntity displays an exception 2. ForwardEntity in MultiEntity has extra `not null` text after it 3. Allow using ImageEntity in ForwardEntity in MultiMsg * Fix typo * Added error handling for GetMessage related services
1 parent 50ee32d commit e5db4df

File tree

15 files changed

+234
-124
lines changed

15 files changed

+234
-124
lines changed

Lagrange.Core/Internal/Context/HighwayContext.cs

Lines changed: 59 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,12 @@ namespace Lagrange.Core.Internal.Context;
1616
internal class HighwayContext : ContextBase, IDisposable
1717
{
1818
private const string Tag = nameof(HighwayContext);
19-
19+
2020
private static readonly RuntimeTypeModel Serializer;
2121

2222
private uint _sequence;
2323
private Uri? _uri;
24-
24+
2525
private readonly Dictionary<Type, IHighwayUploader> _uploaders;
2626
private readonly HttpClient _client;
2727
private readonly int _chunkSize;
@@ -32,7 +32,7 @@ static HighwayContext()
3232
Serializer = RuntimeTypeModel.Create();
3333
Serializer.UseImplicitZeroDefaults = false;
3434
}
35-
35+
3636
public HighwayContext(ContextCollection collection, BotKeystore keystore, BotAppInfo appInfo, BotDeviceInfo device, BotConfig config)
3737
: base(collection, keystore, appInfo, device)
3838
{
@@ -42,12 +42,12 @@ public HighwayContext(ContextCollection collection, BotKeystore keystore, BotApp
4242
var attribute = impl.GetCustomAttribute<HighwayUploaderAttribute>();
4343
if (attribute != null) _uploaders[attribute.Entity] = (IHighwayUploader)impl.CreateInstance(false);
4444
}
45-
45+
4646
var handler = new HttpClientHandler
4747
{
4848
ServerCertificateCustomValidationCallback = (_, _, _, _) => true,
4949
};
50-
50+
5151
_client = new HttpClient(handler);
5252
_client.DefaultRequestHeaders.Add("Accept-Encoding", "identity");
5353
_client.DefaultRequestHeaders.Add("User-Agent", "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2)");
@@ -65,8 +65,26 @@ public async Task UploadResources(MessageChain chain)
6565
{
6666
try
6767
{
68-
if (chain.IsGroup) await uploader.UploadGroup(Collection, chain, entity);
69-
else await uploader.UploadPrivate(Collection, chain, entity);
68+
if (chain.IsGroup) await uploader.UploadGroup(Collection, chain.GroupUin ?? 0, entity);
69+
else await uploader.UploadPrivate(Collection, chain.FriendInfo?.Uid ?? "", entity);
70+
}
71+
catch
72+
{
73+
Collection.Log.LogFatal(Tag, $"Upload resources for {entity.GetType().Name} failed");
74+
}
75+
}
76+
}
77+
}
78+
79+
public async Task UploadGroupResources(MessageChain chain, uint uin)
80+
{
81+
foreach (var entity in chain)
82+
{
83+
if (_uploaders.TryGetValue(entity.GetType(), out var uploader))
84+
{
85+
try
86+
{
87+
await uploader.UploadGroup(Collection, uin, entity);
7088
}
7189
catch
7290
{
@@ -76,6 +94,25 @@ public async Task UploadResources(MessageChain chain)
7694
}
7795
}
7896

97+
public async Task UploadPrivateResources(MessageChain chain, string uid)
98+
{
99+
foreach (var entity in chain)
100+
{
101+
if (_uploaders.TryGetValue(entity.GetType(), out var uploader))
102+
{
103+
try
104+
{
105+
await uploader.UploadPrivate(Collection, uid, entity);
106+
}
107+
catch
108+
{
109+
Collection.Log.LogFatal(Tag, $"Upload resources for {entity.GetType().Name} failed");
110+
}
111+
}
112+
}
113+
}
114+
115+
79116
public async Task ManualUploadEntity(IMessageEntity entity)
80117
{
81118
if (_uploaders.TryGetValue(entity.GetType(), out var uploader))
@@ -85,8 +122,8 @@ public async Task ManualUploadEntity(IMessageEntity entity)
85122
uint uin = Collection.Keystore.Uin;
86123
string uid = Collection.Keystore.Uid ?? "";
87124
var chain = new MessageChain(uin, uid, uid) { entity };
88-
89-
await uploader.UploadPrivate(Collection, chain, entity);
125+
126+
await uploader.UploadPrivate(Collection, chain.FriendInfo?.Uid ?? "", entity);
90127
}
91128
catch
92129
{
@@ -103,7 +140,7 @@ public async Task<bool> UploadSrcByStreamAsync(int commonId, Stream data, byte[]
103140
var result = (HighwayUrlEvent)highwayUrlEvent[0];
104141
_uri = result.HighwayUrls[1][0];
105142
}
106-
143+
107144
bool success = true;
108145
var upBlocks = new List<UpBlock>();
109146

@@ -126,7 +163,7 @@ public async Task<bool> UploadSrcByStreamAsync(int commonId, Stream data, byte[]
126163
var tasks = upBlocks.Select(x => SendUpBlockAsync(x, _uri)).ToArray();
127164
var results = await Task.WhenAll(tasks);
128165
success &= results.All(x => x);
129-
166+
130167
upBlocks.Clear();
131168
}
132169
}
@@ -171,7 +208,7 @@ private async Task<bool> SendUpBlockAsync(UpBlock upBlock, Uri server)
171208
};
172209

173210
bool isEnd = upBlock.Offset + (ulong)upBlock.Block.Length == upBlock.FileSize;
174-
var payload = await SendPacketAsync(highwayHead, new BinaryPacket(upBlock.Block), server, isEnd);
211+
var payload = await SendPacketAsync(highwayHead, new BinaryPacket(upBlock.Block), server, isEnd);
175212
var (respHead, resp) = ParsePacket(payload);
176213

177214
Collection.Log.LogDebug(Tag, $"Highway Block Result: {respHead.ErrorCode} | {respHead.MsgSegHead?.RetCode} | {respHead.BytesRspExtendInfo?.Hex()} | {resp.ToArray().Hex()}");
@@ -183,15 +220,15 @@ private Task<BinaryPacket> SendPacketAsync(ReqDataHighwayHead head, BinaryPacket
183220
{
184221
using var stream = new MemoryStream();
185222
Serializer.Serialize(stream, head);
186-
223+
187224
var writer = new BinaryPacket()
188225
.WriteByte(0x28) // packet start
189226
.WriteInt((int)stream.Length)
190227
.WriteInt((int)buffer.Length)
191228
.WriteBytes(stream.ToArray())
192229
.WritePacket(buffer)
193230
.WriteByte(0x29); // packet end
194-
231+
195232
return SendDataAsync(writer.ToArray(), server, end);
196233
}
197234

@@ -203,13 +240,13 @@ private static (RespDataHighwayHead, BinaryPacket) ParsePacket(BinaryPacket pack
203240
int bodyLength = packet.ReadInt();
204241
var head = Serializer.Deserialize<RespDataHighwayHead>(packet.ReadBytes(headLength).AsSpan());
205242
var body = packet.ReadPacket(bodyLength);
206-
243+
207244
if (packet.ReadByte() == 0x29) return (head, body);
208245
}
209-
246+
210247
throw new InvalidOperationException("Invalid packet");
211248
}
212-
249+
213250
private async Task<BinaryPacket> SendDataAsync(byte[] packet, Uri server, bool end)
214251
{
215252
var content = new ByteArrayContent(packet);
@@ -225,16 +262,16 @@ private async Task<BinaryPacket> SendDataAsync(byte[] packet, Uri server, bool e
225262
var data = await response.Content.ReadAsByteArrayAsync();
226263
return new BinaryPacket(data);
227264
}
228-
265+
229266
private record struct UpBlock(
230-
int CommandId,
267+
int CommandId,
231268
uint Uin,
232-
uint Sequence,
269+
uint Sequence,
233270
ulong FileSize,
234-
ulong Offset,
271+
ulong Offset,
235272
byte[] Ticket,
236273
byte[] FileMd5,
237-
byte[] Block,
274+
byte[] Block,
238275
byte[]? ExtendInfo = null,
239276
ulong Timestamp = 0);
240277

Lagrange.Core/Internal/Context/Logic/Implementation/MessagingLogic.cs

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,12 @@ public override async Task Outgoing(ProtocolEvent e)
310310
await ResolveChainMetadata(chain);
311311
await ResolveOutgoingChain(chain);
312312
await Collection.Highway.UploadResources(chain);
313+
314+
foreach (var forward in chain.OfType<ForwardEntity>())
315+
{
316+
if (chain.IsGroup) await Collection.Highway.UploadGroupResources(forward.Chain, chain.GroupUin ?? 0);
317+
else await Collection.Highway.UploadPrivateResources(forward.Chain, chain.FriendInfo?.Uid ?? "");
318+
}
313319
}
314320
break;
315321
}
@@ -447,6 +453,41 @@ private async Task ResolveIncomingChain(MessageChain chain)
447453
image.ImageUrl = result.Url;
448454
}
449455

456+
break;
457+
}
458+
case ForwardEntity forward:
459+
{
460+
if (chain is { GroupUin: not null })
461+
{
462+
var events = await Collection.Business.SendEvent(GetGroupMessageEvent.Create(
463+
chain.GroupUin.Value,
464+
forward.Sequence,
465+
forward.Sequence
466+
));
467+
468+
if (events.Count < 1) break;
469+
if (events[0] is not GetGroupMessageEvent @event) break;
470+
if (@event.ResultCode != 0) break;
471+
if (@event.Chains.Count < 1) break;
472+
473+
forward.Chain = @event.Chains[0];
474+
}
475+
else
476+
{
477+
var events = await Collection.Business.SendEvent(GetC2cMessageEvent.Create(
478+
chain.Uid ?? "",
479+
forward.Sequence,
480+
forward.Sequence
481+
));
482+
483+
if (events.Count < 1) break;
484+
if (events[0] is not GetC2cMessageEvent @event) break;
485+
if (@event.ResultCode != 0) break;
486+
if (@event.Chains.Count < 1) break;
487+
488+
forward.Chain = @event.Chains[0];
489+
}
490+
450491
break;
451492
}
452493
}

Lagrange.Core/Internal/Context/Uploader/IHighwayUploader.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ namespace Lagrange.Core.Internal.Context.Uploader;
44

55
internal interface IHighwayUploader
66
{
7-
public Task UploadPrivate(ContextCollection context, MessageChain chain, IMessageEntity entity);
8-
9-
public Task UploadGroup(ContextCollection context, MessageChain chain, IMessageEntity entity);
7+
public Task UploadPrivate(ContextCollection context, string uid, IMessageEntity entity);
8+
9+
public Task UploadGroup(ContextCollection context, uint uin, IMessageEntity entity);
1010
}

Lagrange.Core/Internal/Context/Uploader/ImageUploader.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,11 @@ namespace Lagrange.Core.Internal.Context.Uploader;
88
[HighwayUploader(typeof(ImageEntity))]
99
internal class ImageUploader : IHighwayUploader
1010
{
11-
public async Task UploadPrivate(ContextCollection context, MessageChain chain, IMessageEntity entity)
11+
public async Task UploadPrivate(ContextCollection context, string uid, IMessageEntity entity)
1212
{
1313
if (entity is ImageEntity { ImageStream: { } stream } image)
1414
{
15-
var uploadEvent = ImageUploadEvent.Create(image, chain.FriendInfo?.Uid ?? "");
15+
var uploadEvent = ImageUploadEvent.Create(image, uid);
1616
var uploadResult = await context.Business.SendEvent(uploadEvent);
1717
var metaResult = (ImageUploadEvent)uploadResult[0];
1818

@@ -26,18 +26,18 @@ public async Task UploadPrivate(ContextCollection context, MessageChain chain, I
2626
throw new Exception();
2727
}
2828
}
29-
29+
3030
image.MsgInfo = metaResult.MsgInfo; // directly constructed by Tencent's BDH Server
3131
image.CompatImage = metaResult.Compat; // for legacy QQ
3232
await image.ImageStream.Value.DisposeAsync();
3333
}
3434
}
3535

36-
public async Task UploadGroup(ContextCollection context, MessageChain chain, IMessageEntity entity)
36+
public async Task UploadGroup(ContextCollection context, uint uin, IMessageEntity entity)
3737
{
3838
if (entity is ImageEntity { ImageStream: { } stream } image)
3939
{
40-
var uploadEvent = ImageGroupUploadEvent.Create(image, chain.GroupUin ?? 0);
40+
var uploadEvent = ImageGroupUploadEvent.Create(image, uin);
4141
var uploadResult = await context.Business.SendEvent(uploadEvent);
4242
var metaResult = (ImageGroupUploadEvent)uploadResult[0];
4343

@@ -51,7 +51,7 @@ public async Task UploadGroup(ContextCollection context, MessageChain chain, IMe
5151
throw new Exception();
5252
}
5353
}
54-
54+
5555
image.MsgInfo = metaResult.MsgInfo; // directly constructed by Tencent's BDH Server
5656
image.CompatFace = metaResult.Compat; // for legacy QQ
5757
await image.ImageStream.Value.DisposeAsync();

Lagrange.Core/Internal/Context/Uploader/PttUploader.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,11 @@ namespace Lagrange.Core.Internal.Context.Uploader;
88
[HighwayUploader(typeof(RecordEntity))]
99
internal class PttUploader : IHighwayUploader
1010
{
11-
public async Task UploadPrivate(ContextCollection context, MessageChain chain, IMessageEntity entity)
11+
public async Task UploadPrivate(ContextCollection context, string uid, IMessageEntity entity)
1212
{
1313
if (entity is RecordEntity { AudioStream: { } stream } record)
1414
{
15-
var uploadEvent = RecordUploadEvent.Create(record, chain.FriendInfo?.Uid ?? "");
15+
var uploadEvent = RecordUploadEvent.Create(record, uid);
1616
var uploadResult = await context.Business.SendEvent(uploadEvent);
1717
var metaResult = (RecordUploadEvent)uploadResult[0];
1818

@@ -33,11 +33,11 @@ public async Task UploadPrivate(ContextCollection context, MessageChain chain, I
3333
}
3434
}
3535

36-
public async Task UploadGroup(ContextCollection context, MessageChain chain, IMessageEntity entity)
36+
public async Task UploadGroup(ContextCollection context, uint uin, IMessageEntity entity)
3737
{
3838
if (entity is RecordEntity { AudioStream: { } stream } record)
3939
{
40-
var uploadEvent = RecordGroupUploadEvent.Create(record, chain.GroupUin ?? 0);
40+
var uploadEvent = RecordGroupUploadEvent.Create(record, uin);
4141
var uploadResult = await context.Business.SendEvent(uploadEvent);
4242
var metaResult = (RecordGroupUploadEvent)uploadResult[0];
4343

@@ -51,7 +51,7 @@ public async Task UploadGroup(ContextCollection context, MessageChain chain, IMe
5151
throw new Exception();
5252
}
5353
}
54-
54+
5555
record.MsgInfo = metaResult.MsgInfo; // directly constructed by Tencent's BDH Server
5656
record.Compat = metaResult.Compat; // for legacy QQ
5757
await record.AudioStream.Value.DisposeAsync();

Lagrange.Core/Internal/Context/Uploader/VideoUploader.cs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,11 @@ namespace Lagrange.Core.Internal.Context.Uploader;
88
[HighwayUploader(typeof(VideoEntity))]
99
internal class VideoUploader : IHighwayUploader
1010
{
11-
public async Task UploadPrivate(ContextCollection context, MessageChain chain, IMessageEntity entity)
11+
public async Task UploadPrivate(ContextCollection context, string uid, IMessageEntity entity)
1212
{
1313
if (entity is VideoEntity { VideoStream: { } stream, ThumbnailStream: { } thumbnail } video)
1414
{
15-
var uploadEvent = VideoUploadEvent.Create(video, chain.FriendInfo?.Uid ?? "");
15+
var uploadEvent = VideoUploadEvent.Create(video, uid);
1616
var uploadResult = await context.Business.SendEvent(uploadEvent);
1717
var metaResult = (VideoUploadEvent)uploadResult[0];
1818

@@ -28,7 +28,7 @@ public async Task UploadPrivate(ContextCollection context, MessageChain chain, I
2828
throw new Exception();
2929
}
3030
}
31-
31+
3232
if (Common.GenerateExt(metaResult, metaResult.SubFiles[0]) is { } subExt)
3333
{
3434
var hash = metaResult.MsgInfo.MsgInfoBody[1].Index.Info.FileHash.UnHex();
@@ -48,18 +48,18 @@ public async Task UploadPrivate(ContextCollection context, MessageChain chain, I
4848
}
4949
}
5050

51-
public async Task UploadGroup(ContextCollection context, MessageChain chain, IMessageEntity entity)
51+
public async Task UploadGroup(ContextCollection context, uint uin, IMessageEntity entity)
5252
{
5353
if (entity is VideoEntity { VideoStream: { } stream, ThumbnailStream: { } thumbnail } video)
5454
{
55-
var uploadEvent = VideoGroupUploadEvent.Create(video, chain.GroupUin ?? 0);
55+
var uploadEvent = VideoGroupUploadEvent.Create(video, uin);
5656
var uploadResult = await context.Business.SendEvent(uploadEvent);
5757
var metaResult = (VideoGroupUploadEvent)uploadResult[0];
58-
58+
5959
if (Common.GenerateExt(metaResult) is { } ext)
6060
{
6161
ext.Hash.FileSha1 = Common.CalculateStreamBytes(stream.Value);
62-
62+
6363
var hash = metaResult.MsgInfo.MsgInfoBody[0].Index.Info.FileHash.UnHex();
6464
bool hwSuccess = await context.Highway.UploadSrcByStreamAsync(1005, stream.Value, await Common.GetTicket(context), hash, ext.Serialize().ToArray());
6565
if (!hwSuccess)
@@ -80,7 +80,7 @@ public async Task UploadGroup(ContextCollection context, MessageChain chain, IMe
8080
throw new Exception();
8181
}
8282
}
83-
83+
8484
video.MsgInfo = metaResult.MsgInfo; // directly constructed by Tencent's BDH Server
8585
video.Compat = metaResult.Compat; // for legacy QQ
8686
await stream.Value.DisposeAsync();

0 commit comments

Comments
 (0)