Skip to content

Commit df0467c

Browse files
committed
[Core & Milky] Implement Core's GetNTV2RichMediaUrl and Milky's get_resource_temp_url
1 parent e29de24 commit df0467c

6 files changed

Lines changed: 151 additions & 17 deletions

File tree

Lagrange.Core/Common/Interface/OperationExt.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,4 +41,7 @@ public static Task SetGroupNotification(this BotContext context, long groupUin,
4141

4242
public static Task SetGroupReaction(this BotContext context, long groupUin, ulong sequence, string code, bool isAdd) =>
4343
context.EventContext.GetLogic<OperationLogic>().SetGroupReaction(groupUin, sequence, code, isAdd);
44+
45+
public static Task<string> GetNTV2RichMediaUrl(this BotContext context, string fileUuid) =>
46+
context.EventContext.GetLogic<OperationLogic>().GetNTV2RichMediaUrl(fileUuid);
4447
}

Lagrange.Core/Internal/Logic/OperationLogic.cs

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,14 @@
55
using Lagrange.Core.Internal.Events.Message;
66
using Lagrange.Core.Internal.Events.System;
77
using Lagrange.Core.Internal.Packets.Service;
8+
using Lagrange.Core.Message;
9+
using Lagrange.Core.Message.Entities;
810
using Lagrange.Core.Utility;
911
using Lagrange.Core.Utility.Cryptography;
1012
using Lagrange.Core.Utility.Extension;
13+
using Lagrange.Proto.Primitives;
14+
using Lagrange.Proto.Serialization;
15+
using FileInfo = Lagrange.Core.Internal.Packets.Service.FileInfo;
1116

1217
namespace Lagrange.Core.Internal.Logic;
1318

@@ -284,4 +289,93 @@ public async Task SetGroupReaction(long groupUin, ulong sequence, string code, b
284289
new ReduceGroupReactionEventReq(groupUin, sequence, code)
285290
);
286291
}
292+
293+
public async Task<string> GetNTV2RichMediaUrl(string uuid)
294+
{
295+
int remainder = uuid.Length % 4;
296+
int length = remainder == 0 ? uuid.Length : uuid.Length + (4 - remainder);
297+
string base64 = uuid.Replace('-', '+').Replace('_', '/').PadRight(length, '=');
298+
299+
ulong appId = 0;
300+
uint ttl = 0;
301+
var reader = new ProtoReader(Convert.FromBase64String(base64));
302+
while (!reader.IsCompleted)
303+
{
304+
uint tag = reader.DecodeVarIntUnsafe<uint>();
305+
switch (tag >>> 3)
306+
{
307+
case 4:
308+
{
309+
appId = reader.DecodeVarInt<ulong>();
310+
break;
311+
}
312+
case 10:
313+
{
314+
ttl = reader.DecodeVarInt<uint>();
315+
break;
316+
}
317+
default:
318+
{
319+
reader.SkipField((WireType)(tag & 0b111));
320+
break;
321+
}
322+
}
323+
}
324+
325+
NTV2RichMediaDownloadEventResp response = appId switch
326+
{
327+
// Record
328+
1402 => await context.EventContext.SendEvent<RecordDownloadEventResp>(new RecordDownloadEventReq(
329+
CreateFakeFriendMessage(context.BotUin),
330+
CreateFakeEntity<RecordEntity>(uuid, ttl)
331+
)),
332+
1403 => await context.EventContext.SendEvent<RecordGroupDownloadEventResp>(new RecordGroupDownloadEventReq(
333+
CreateFakeGroupMessage(context.BotUin),
334+
CreateFakeEntity<RecordEntity>(uuid, ttl)
335+
)),
336+
// Video
337+
1413 => await context.EventContext.SendEvent<VideoDownloadEventResp>(new VideoDownloadEventReq(
338+
CreateFakeFriendMessage(context.BotUin),
339+
CreateFakeEntity<VideoEntity>(uuid, ttl)
340+
)),
341+
1415 => await context.EventContext.SendEvent<VideoGroupDownloadEventResp>(new VideoGroupDownloadEventReq(
342+
CreateFakeGroupMessage(context.BotUin),
343+
CreateFakeEntity<VideoEntity>(uuid, ttl)
344+
)),
345+
// Image
346+
1406 => await context.EventContext.SendEvent<ImageDownloadEventResp>(new ImageDownloadEventReq(
347+
CreateFakeFriendMessage(context.BotUin),
348+
CreateFakeEntity<ImageEntity>(uuid, ttl)
349+
)),
350+
1407 => await context.EventContext.SendEvent<ImageGroupDownloadEventResp>(new ImageGroupDownloadEventReq(
351+
CreateFakeGroupMessage(context.BotUin),
352+
CreateFakeEntity<ImageEntity>(uuid, ttl)
353+
)),
354+
_ => throw new NotSupportedException($"Unsupported AppId: {appId}"),
355+
};
356+
357+
return response.Url;
358+
359+
static BotMessage CreateFakeFriendMessage(long uin) => BotMessage.CreateCustomFriend(uin, string.Empty, uin, string.Empty, DateTime.Now, []);
360+
static BotMessage CreateFakeGroupMessage(long uin) => BotMessage.CreateCustomGroup(uin, 0, string.Empty, DateTime.Now, []);
361+
static RichMediaEntityBase CreateFakeEntity<T>(string fileUuid, uint ttl) where T : RichMediaEntityBase, new()
362+
{
363+
return new T
364+
{
365+
MsgInfo = new MsgInfo
366+
{
367+
MsgInfoBody = [new MsgInfoBody {
368+
Index = new IndexNode {
369+
Info = new FileInfo {},
370+
FileUuid = fileUuid,
371+
StoreId = 1,
372+
UploadTime = 0,
373+
Ttl = ttl,
374+
SubType = 0,
375+
}
376+
}]
377+
}
378+
};
379+
}
380+
}
287381
}

Lagrange.Core/Message/Entities/RichMediaEntityBase.cs

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -11,53 +11,53 @@ public abstract class RichMediaEntityBase : IMessageEntity
1111
protected byte[]? _compat;
1212

1313
private protected bool IsGroup;
14-
14+
1515
internal MsgInfo? MsgInfo
1616
{
1717
get => _msgInfo;
18-
private protected set
18+
set
1919
{
2020
Debug.Assert(value != null);
21-
21+
2222
var fileInfo = value.MsgInfoBody[0].Index.Info;
2323
FileUuid = value.MsgInfoBody[0].Index.FileUuid;
2424
FileMd5 = fileInfo.FileHash;
2525
FileSha1 = fileInfo.FileSha1;
2626
FileSize = fileInfo.FileSize;
2727
FileName = fileInfo.FileName;
2828
_msgInfo = value;
29-
}
29+
}
3030
}
31-
31+
3232
private protected bool DisposeOnCompletion;
3333

3434
internal abstract Lazy<Stream>? Stream { get; }
3535

3636
public string FileUuid { get; internal set; } = string.Empty;
37-
37+
3838
public string FileUrl { get; internal set; } = string.Empty;
3939

4040
public string FileName { get; internal set; } = string.Empty;
41-
41+
4242
public string FileSha1 { get; internal set; } = string.Empty;
43-
43+
4444
public uint FileSize { get; internal set; }
4545

4646
public string FileMd5 { get; internal set; } = string.Empty;
47-
47+
4848
public abstract Task Preprocess(BotContext context, BotMessage message);
4949

5050
public abstract Task Postprocess(BotContext context, BotMessage message);
51-
51+
5252
internal abstract Elem[] Build();
53-
53+
5454
internal abstract IMessageEntity? Parse(List<Elem> elements, Elem target);
55-
55+
5656
public abstract string ToPreviewString();
57-
57+
5858
Elem[] IMessageEntity.Build() => Build();
5959

6060
IMessageEntity? IMessageEntity.Parse(List<Elem> elements, Elem target) => Parse(elements, target);
61-
61+
6262
string IMessageEntity.ToPreviewString() => ToPreviewString();
6363
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
2+
using System.Text.Json.Serialization;
3+
using Lagrange.Core;
4+
using Lagrange.Core.Common.Interface;
5+
6+
namespace Lagrange.Milky.Api.Handler.Message;
7+
8+
[Api("get_resource_temp_url")]
9+
public class GetResourceTempUrlHandler(BotContext bot) : IApiHandler<GetResourceTempUrlParameter, GetResourceTempUrlResult>
10+
{
11+
private readonly BotContext _bot = bot;
12+
13+
public async Task<GetResourceTempUrlResult> HandleAsync(GetResourceTempUrlParameter parameter, CancellationToken token)
14+
{
15+
return new GetResourceTempUrlResult(await _bot.GetNTV2RichMediaUrl(parameter.ResourceId));
16+
}
17+
}
18+
19+
public class GetResourceTempUrlParameter(string resourceId)
20+
{
21+
[JsonRequired]
22+
[JsonPropertyName("resource_id")]
23+
public string ResourceId { get; init; } = resourceId;
24+
}
25+
26+
public class GetResourceTempUrlResult(string url)
27+
{
28+
[JsonPropertyName("url")]
29+
public string Url { get; } = url;
30+
}

Lagrange.Milky/README.md

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,11 @@ https://lagrangedev.github.io/Lagrange.Milky.Document
1212

1313
## Feature List
1414

15+
Current Milky version: [77c6cbd](https://github.com/SaltifyDev/milky/tree/77c6cbd6fb131d581fbb4c128a540eadfbcbd475)
16+
1517
### communication
1618

19+
- [ ] SSE (wontimpl)
1720
- [x] WebSocket
1821
- [x] WebHook
1922

@@ -39,7 +42,7 @@ https://lagrangedev.github.io/Lagrange.Milky.Document
3942
- [x] /send_group_message
4043
- [x] /get_message
4144
- [x] /get_history_messages - not supported start_message_seq eql null
42-
- [ ] /get_resource_temp_url
45+
- [x] /get_resource_temp_url
4346
- [ ] /get_forwarded_messages
4447
- [ ] /recall_private_message
4548
- [ ] /recall_group_message
@@ -125,6 +128,7 @@ https://lagrangedev.github.io/Lagrange.Milky.Document
125128
- [x] image
126129
- [x] record
127130
- [x] video
131+
- [ ] file
128132
- [x] forward
129133
- [ ] market_face
130134
- [ ] light_app
@@ -145,8 +149,8 @@ https://lagrangedev.github.io/Lagrange.Milky.Document
145149
#### forward
146150

147151
- [x] text
148-
<!-- - [ ] mention -->
149-
<!-- - [ ] mention_all -->
152+
- [ ] mention - (wontimpl) forward not supported
153+
- [ ] mention_all - (wontimpl) forward not supported
150154
- [ ] face
151155
- [ ] reply
152156
- [ ] image

Lagrange.Milky/Utility/JsonUtility.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,9 @@ public static partial class JsonUtility
7575
// get_history_messages
7676
[JsonSerializable(typeof(GetHistoryMessagesParameter))]
7777
[JsonSerializable(typeof(GetHistoryMessagesResult))]
78+
// get_resource_temp_url
79+
[JsonSerializable(typeof(GetResourceTempUrlParameter))]
80+
[JsonSerializable(typeof(GetResourceTempUrlResult))]
7881
// == friend ==
7982
// send_friend_nudge
8083
[JsonSerializable(typeof(SendFriendNudgeParameter))]

0 commit comments

Comments
 (0)