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

Commit 595b5fa

Browse files
authored
[All] multimedia related (#782)
1. Fix video entity parse 2. Add get media url operation
1 parent 70c93de commit 595b5fa

19 files changed

Lines changed: 394 additions & 262 deletions

Lagrange.Core/Common/Interface/Api/OperationExt.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,4 +299,7 @@ public static Task<string> UploadImage(this BotContext bot, ImageEntity entity)
299299

300300
public static Task<string> FetchPrivateFSDownload(this BotContext bot, string fileId, string fileHash, uint userId)
301301
=> bot.ContextCollection.Business.OperationLogic.FetchPrivateFSDownload(fileId, fileHash, userId);
302+
303+
public static Task<(int Code, string Message, string Url)> GetMediaUrl(this BotContext bot, string fileId)
304+
=> bot.ContextCollection.Business.OperationLogic.GetMediaUrl(fileId);
302305
}

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

Lines changed: 43 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,13 @@
88
using Lagrange.Core.Internal.Event.Message;
99
using Lagrange.Core.Internal.Event.Notify;
1010
using Lagrange.Core.Internal.Event.System;
11+
using Lagrange.Core.Internal.Packets.Misc;
12+
using Lagrange.Core.Internal.Packets.Service.Oidb.Common;
1113
using Lagrange.Core.Internal.Service;
1214
using Lagrange.Core.Message;
1315
using Lagrange.Core.Message.Entity;
1416
using Lagrange.Core.Message.Filter;
17+
using ProtoBuf;
1518
using FriendPokeEvent = Lagrange.Core.Event.EventArg.FriendPokeEvent;
1619
using GroupPokeEvent = Lagrange.Core.Event.EventArg.GroupPokeEvent;
1720

@@ -371,60 +374,77 @@ private async Task ResolveIncomingChain(MessageChain chain)
371374
}
372375
case RecordEntity { MsgInfo: not null } record:
373376
{
374-
var @event = chain.IsGroup
375-
? RecordGroupDownloadEvent.Create(chain.GroupUin ?? 0, record.MsgInfo)
376-
: RecordDownloadEvent.Create(chain.Uid ?? string.Empty, record.MsgInfo);
377+
MediaDownloadEvent @event = chain.IsGroup
378+
? RecordGroupDownloadEvent.Create(record.MsgInfo.MsgInfoBody[0].Index)
379+
: RecordDownloadEvent.Create(record.MsgInfo.MsgInfoBody[0].Index);
377380

378381
var results = await Collection.Business.SendEvent(@event);
379382
if (results.Count != 0)
380383
{
381-
var result = (RecordDownloadEvent)results[0];
382-
record.AudioUrl = result.AudioUrl;
384+
var result = (MediaDownloadEvent)results[0];
385+
record.AudioUrl = result.Url;
383386
}
384387

385388
break;
386389
}
387390
case RecordEntity { AudioUuid: not null } record:
388391
{
389-
var @event = chain.IsGroup
390-
? RecordGroupDownloadEvent.Create(chain.GroupUin ?? 0, record.AudioUuid)
391-
: RecordDownloadEvent.Create(chain.Uid ?? string.Empty, record.AudioUuid);
392+
int remainder = record.AudioUuid.Length % 4;
393+
int length = remainder == 0 ? record.AudioUuid.Length : record.AudioUuid.Length + (4 - remainder);
394+
string base64 = record.AudioUuid.Replace('-', '+').Replace('_', '/').PadRight(length, '=');
395+
var info = Serializer.Deserialize<FileId>(Convert.FromBase64String(base64).AsSpan());
396+
397+
var index = new IndexNode
398+
{
399+
FileUuid = record.AudioUuid,
400+
StoreId = 1,
401+
UploadTime = 0,
402+
Ttl = info.Ttl,
403+
SubType = 0
404+
};
405+
406+
var results = await Collection.Business.SendEvent(info.AppId switch
407+
{
408+
1402 => RecordDownloadEvent.Create(index),
409+
1403 => RecordGroupDownloadEvent.Create(index),
410+
411+
_ => throw new NotSupportedException($"Unsupported Record AppId: {info.AppId}"),
412+
});
392413

393-
var results = await Collection.Business.SendEvent(@event);
394414
if (results.Count != 0)
395415
{
396-
var result = (RecordDownloadEvent)results[0];
397-
record.AudioUrl = result.AudioUrl;
416+
var result = (MediaDownloadEvent)results[0];
417+
record.AudioUrl = result.Url;
398418
}
399419

400420
break;
401421
}
402-
case VideoEntity { VideoUuid: not null } video:
422+
case VideoEntity video when !video.VideoUrl.Contains("&rkey=") && video.MsgInfo is not null:
403423
{
404-
string uid = (chain.IsGroup
405-
? await Collection.Business.CachingLogic.ResolveUid(chain.GroupUin, chain.FriendUin)
406-
: chain.Uid) ?? "";
407-
var @event = VideoDownloadEvent.Create(video.VideoUuid, uid, video.FilePath, "", "", chain.IsGroup);
424+
MediaDownloadEvent @event = video.IsGroup
425+
? VideoGroupDownloadEvent.Create(video.MsgInfo.MsgInfoBody[0].Index)
426+
: VideoDownloadEvent.Create(video.MsgInfo.MsgInfoBody[0].Index);
427+
408428
var results = await Collection.Business.SendEvent(@event);
409429
if (results.Count != 0)
410430
{
411-
var result = (VideoDownloadEvent)results[0];
412-
video.VideoUrl = result.AudioUrl;
431+
var result = (MediaDownloadEvent)results[0];
432+
video.VideoUrl = result.Url;
413433
}
414434

415435
break;
416436
}
417437
case ImageEntity image when !image.ImageUrl.Contains("&rkey=") && image.MsgInfo is not null:
418438
{
419-
var @event = image.IsGroup
420-
? ImageGroupDownloadEvent.Create(chain.GroupUin ?? 0, image.MsgInfo)
421-
: ImageDownloadEvent.Create(chain.Uid ?? string.Empty, image.MsgInfo);
439+
MediaDownloadEvent @event = image.IsGroup
440+
? ImageGroupDownloadEvent.Create(image.MsgInfo.MsgInfoBody[0].Index)
441+
: ImageDownloadEvent.Create(image.MsgInfo.MsgInfoBody[0].Index);
422442

423443
var results = await Collection.Business.SendEvent(@event);
424444
if (results.Count != 0)
425445
{
426-
var result = (ImageDownloadEvent)results[0];
427-
image.ImageUrl = result.ImageUrl;
446+
var result = (MediaDownloadEvent)results[0];
447+
image.ImageUrl = result.Url;
428448
}
429449

430450
break;

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

Lines changed: 46 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,13 @@
44
using Lagrange.Core.Internal.Event.Action;
55
using Lagrange.Core.Internal.Event.Message;
66
using Lagrange.Core.Internal.Event.System;
7+
using Lagrange.Core.Internal.Packets.Misc;
78
using Lagrange.Core.Internal.Packets.Service.Highway;
9+
using Lagrange.Core.Internal.Packets.Service.Oidb.Common;
810
using Lagrange.Core.Message;
911
using Lagrange.Core.Message.Entity;
1012
using Lagrange.Core.Utility.Extension;
13+
using ProtoBuf;
1114

1215
namespace Lagrange.Core.Internal.Context.Logic.Implementation;
1316

@@ -754,13 +757,13 @@ public async Task<bool> FriendJoinEmojiChain(uint friendUin, uint emojiId, uint
754757
if (code != 0)
755758
return (code, errMsg, null);
756759

757-
var recordGroupDownloadEvent = RecordGroupDownloadEvent.Create(groupUin, record!.MsgInfo!);
760+
var recordGroupDownloadEvent = RecordGroupDownloadEvent.Create(record!.MsgInfo!.MsgInfoBody[0].Index);
758761
var @event = await Collection.Business.SendEvent(recordGroupDownloadEvent);
759762
if (@event.Count == 0) return (-1, "running event missing!", null);
760763

761764
var finalResult = (RecordGroupDownloadEvent)@event[0];
762765
return finalResult.ResultCode == 0
763-
? (finalResult.ResultCode, string.Empty, finalResult.AudioUrl)
766+
? (finalResult.ResultCode, string.Empty, finalResult.Url)
764767
: (finalResult.ResultCode, "Failed to get group ai record", null);
765768
}
766769

@@ -803,12 +806,12 @@ public async Task<bool> FriendJoinEmojiChain(uint friendUin, uint emojiId, uint
803806
public async Task<string> UploadImage(ImageEntity image)
804807
{
805808
await Collection.Highway.ManualUploadEntity(image);
806-
var msgInfo = image.MsgInfo;
807-
if (msgInfo is null) throw new Exception();
808-
var downloadEvent = ImageDownloadEvent.Create(Collection.Keystore.Uid ?? "", msgInfo);
809+
var msgInfo = image.MsgInfo ?? throw new Exception();
810+
811+
var downloadEvent = ImageDownloadEvent.Create(msgInfo.MsgInfoBody[0].Index);
809812
var result = await Collection.Business.SendEvent(downloadEvent);
810813
var ret = (ImageDownloadEvent)result[0];
811-
return ret.ImageUrl;
814+
return ret.Url;
812815
}
813816

814817
public async Task<ImageOcrResult?> ImageOcr(string imageUrl)
@@ -865,4 +868,41 @@ public async Task<string> UploadImage(ImageEntity image)
865868
var result = (SetPinGroupEvent)results[0];
866869
return (result.ResultCode, result.Message);
867870
}
871+
872+
public async Task<(int Code, string Message, string Url)> GetMediaUrl(string fileId)
873+
{
874+
int remainder = fileId.Length % 4;
875+
int length = remainder == 0 ? fileId.Length : fileId.Length + (4 - remainder);
876+
string base64 = fileId.Replace('-', '+').Replace('_', '/').PadRight(length, '=');
877+
var info = Serializer.Deserialize<FileId>(Convert.FromBase64String(base64).AsSpan());
878+
879+
var index = new IndexNode
880+
{
881+
FileUuid = fileId,
882+
StoreId = 1,
883+
UploadTime = 0,
884+
Ttl = info.Ttl,
885+
SubType = 0
886+
};
887+
// Special processing video cover
888+
if (info.AppId == 1414 || info.AppId == 1416) index.SubType = 100;
889+
890+
var results = await Collection.Business.SendEvent(info.AppId switch
891+
{
892+
1402 => RecordDownloadEvent.Create(index),
893+
1403 => RecordGroupDownloadEvent.Create(index),
894+
895+
1413 => VideoDownloadEvent.Create(index),
896+
1415 => VideoGroupDownloadEvent.Create(index),
897+
898+
1406 => ImageDownloadEvent.Create(index),
899+
1407 => ImageGroupDownloadEvent.Create(index),
900+
901+
_ => throw new NotSupportedException($"Unsupported AppId: {info.AppId}")
902+
});
903+
if (results.Count == 0) return (-1, "No Result", string.Empty);
904+
905+
var result = (MediaDownloadEvent)results[0];
906+
return (result.ResultCode, result.Message, result.Url);
907+
}
868908
}

Lagrange.Core/Internal/Event/Message/ImageDownloadEvent.cs

Lines changed: 7 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2,28 +2,14 @@
22

33
namespace Lagrange.Core.Internal.Event.Message;
44

5-
#pragma warning disable CS8618
6-
7-
internal class ImageDownloadEvent : ProtocolEvent
5+
internal class ImageDownloadEvent : MediaDownloadEvent
86
{
9-
public string SelfUid { get; }
10-
11-
public IndexNode Node { get; }
12-
13-
public string ImageUrl { get; }
14-
15-
protected ImageDownloadEvent(string selfUid, MsgInfo info) : base(true)
16-
{
17-
SelfUid = selfUid;
18-
Node = info.MsgInfoBody[0].Index;
19-
}
7+
protected ImageDownloadEvent(IndexNode index) : base(index) { }
8+
9+
protected ImageDownloadEvent(int code, string message, string url) : base(code, message, url) { }
2010

21-
protected ImageDownloadEvent(int resultCode, string imageUrl) : base(resultCode)
22-
{
23-
ImageUrl = imageUrl;
24-
}
25-
26-
public static ImageDownloadEvent Create(string selfUid, MsgInfo info) => new(selfUid, info);
11+
public static new ImageDownloadEvent Create(IndexNode index) => new(index);
2712

28-
public static ImageDownloadEvent Result(int resultCode, string url) => new(resultCode, url);
13+
public static new ImageDownloadEvent Result(string url) => new(0, string.Empty, url);
14+
public static new ImageDownloadEvent Result(int code, string message) => new(code, message, string.Empty);
2915
}

Lagrange.Core/Internal/Event/Message/ImageGroupDownloadEvent.cs

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,14 @@
22

33
namespace Lagrange.Core.Internal.Event.Message;
44

5-
internal class ImageGroupDownloadEvent : ImageDownloadEvent
5+
internal class ImageGroupDownloadEvent : MediaDownloadEvent
66
{
7-
public uint GroupUin { get; }
8-
9-
private ImageGroupDownloadEvent(uint groupUin, MsgInfo info) : base("", info)
10-
{
11-
GroupUin = groupUin;
12-
}
7+
protected ImageGroupDownloadEvent(IndexNode index) : base(index) { }
138

14-
private ImageGroupDownloadEvent(int resultCode, string imageUrl) : base(resultCode, imageUrl) { }
15-
16-
public static ImageGroupDownloadEvent Create(uint groupUin, MsgInfo info) => new(groupUin, info);
9+
protected ImageGroupDownloadEvent(int code, string message, string url) : base(code, message, url) { }
1710

18-
public new static ImageGroupDownloadEvent Result(int resultCode, string url) => new(resultCode, url);
11+
public static new ImageGroupDownloadEvent Create(IndexNode index) => new(index);
12+
13+
public static new ImageGroupDownloadEvent Result(string url) => new(0, string.Empty, url);
14+
public static new ImageGroupDownloadEvent Result(int code, string message) => new(code, message, string.Empty);
1915
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
using Lagrange.Core.Internal.Packets.Service.Oidb.Common;
2+
3+
namespace Lagrange.Core.Internal.Event.Message;
4+
5+
#pragma warning disable CS8618
6+
7+
internal class MediaDownloadEvent : ProtocolEvent
8+
{
9+
public IndexNode Node { get; }
10+
11+
public string Message { get; }
12+
public string Url { get; }
13+
14+
protected MediaDownloadEvent(IndexNode index) : base(true)
15+
{
16+
Node = index;
17+
}
18+
19+
protected MediaDownloadEvent(int code, string message, string imageUrl) : base(code)
20+
{
21+
Url = imageUrl;
22+
}
23+
24+
public static MediaDownloadEvent Create(IndexNode index) => new(index);
25+
26+
public static MediaDownloadEvent Result(string url) => new(0, string.Empty, url);
27+
public static MediaDownloadEvent Result(int code, string message) => new(code, message, string.Empty);
28+
}

Lagrange.Core/Internal/Event/Message/RecordDownloadEvent.cs

Lines changed: 6 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -2,38 +2,14 @@
22

33
namespace Lagrange.Core.Internal.Event.Message;
44

5-
#pragma warning disable CS8618
6-
7-
internal class RecordDownloadEvent : ProtocolEvent
5+
internal class RecordDownloadEvent : MediaDownloadEvent
86
{
9-
public string SelfUid { get; }
10-
11-
public string FileUuid { get; }
12-
13-
public IndexNode? Node { get; }
14-
15-
public string AudioUrl { get; }
16-
17-
protected RecordDownloadEvent(string selfUid, MsgInfo info) : base(true)
18-
{
19-
SelfUid = selfUid;
20-
Node = info.MsgInfoBody[0].Index;
21-
}
7+
protected RecordDownloadEvent(IndexNode index) : base(index) { }
228

23-
protected RecordDownloadEvent(string selfUid, string fileUuid) : base(true)
24-
{
25-
SelfUid = selfUid;
26-
FileUuid = fileUuid;
27-
}
28-
29-
protected RecordDownloadEvent(int resultCode, string audioUrl) : base(resultCode)
30-
{
31-
AudioUrl = audioUrl;
32-
}
9+
protected RecordDownloadEvent(int code, string message, string url) : base(code, message, url) { }
3310

34-
public static RecordDownloadEvent Create(string selfUid, MsgInfo info) => new(selfUid, info);
35-
36-
public static RecordDownloadEvent Create(string selfUid, string fileUuid) => new(selfUid, fileUuid);
11+
public static new RecordDownloadEvent Create(IndexNode index) => new(index);
3712

38-
public static RecordDownloadEvent Result(int resultCode, string url) => new(resultCode, url);
13+
public static new RecordDownloadEvent Result(string url) => new(0, string.Empty, url);
14+
public static new RecordDownloadEvent Result(int code, string message) => new(code, message, string.Empty);
3915
}

Lagrange.Core/Internal/Event/Message/RecordGroupDownloadEvent.cs

Lines changed: 7 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,25 +2,14 @@
22

33
namespace Lagrange.Core.Internal.Event.Message;
44

5-
internal class RecordGroupDownloadEvent : RecordDownloadEvent
5+
internal class RecordGroupDownloadEvent : MediaDownloadEvent
66
{
7-
public uint GroupUin { get; }
8-
9-
private RecordGroupDownloadEvent(uint groupUin, MsgInfo info) : base("", info)
10-
{
11-
GroupUin = groupUin;
12-
}
13-
14-
private RecordGroupDownloadEvent(uint groupUin, string fileUuid) : base("", fileUuid)
15-
{
16-
GroupUin = groupUin;
17-
}
7+
protected RecordGroupDownloadEvent(IndexNode index) : base(index) { }
188

19-
private RecordGroupDownloadEvent(int resultCode, string audioUrl) : base(resultCode, audioUrl) { }
20-
21-
public static RecordGroupDownloadEvent Create(uint groupUin, MsgInfo info) => new(groupUin, info);
22-
23-
public static RecordGroupDownloadEvent Create(uint groupUin, string fileUuid) => new(groupUin, fileUuid);
9+
protected RecordGroupDownloadEvent(int code, string message, string url) : base(code, message, url) { }
2410

25-
public new static RecordGroupDownloadEvent Result(int resultCode, string url) => new(resultCode, url);
11+
public static new RecordGroupDownloadEvent Create(IndexNode index) => new(index);
12+
13+
public static new RecordGroupDownloadEvent Result(string url) => new(0, string.Empty, url);
14+
public static new RecordGroupDownloadEvent Result(int code, string message) => new(code, message, string.Empty);
2615
}

0 commit comments

Comments
 (0)