Skip to content

Commit

Permalink
[Core] Implemented UploadFriendFile
Browse files Browse the repository at this point in the history
  • Loading branch information
Linwenxuan04 committed Mar 3, 2024
1 parent 19bd32d commit 92da94f
Show file tree
Hide file tree
Showing 12 changed files with 288 additions and 13 deletions.
5 changes: 5 additions & 0 deletions Lagrange.Core/Common/Interface/Api/OperationExt.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using Lagrange.Core.Common.Entity;
using Lagrange.Core.Message;
using Lagrange.Core.Message.Entity;

namespace Lagrange.Core.Common.Interface.Api;

Expand Down Expand Up @@ -162,4 +163,8 @@ public static Task<bool> MarkAsRead(this BotContext bot, MessageChain targetChai
uint timestamp = (uint)(targetChain.Time - new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc)).TotalSeconds;
return bot.ContextCollection.Business.OperationLogic.MarkAsRead(targetChain.GroupUin ?? 0, targetChain.Uid, targetChain.Sequence, timestamp);
}

public static Task<bool> UploadFriendFile(this BotContext bot, uint targetUin, FileEntity fileEntity)
=> bot.ContextCollection.Business.OperationLogic.UploadFriendFile(targetUin, fileEntity);

}
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,21 @@ public Task<bool> GroupFSUpload(uint groupUin, FileEntity fileEntity)
}
}

public async Task<bool> UploadFriendFile(uint targetUin, FileEntity fileEntity)
{
string? uid = await Collection.Business.CachingLogic.ResolveUid(null, targetUin);
var chain = new MessageChain(targetUin, Collection.Keystore.Uid ?? "", uid ?? "") { fileEntity };

try
{
return await FileUploader.UploadPrivate(Collection, chain, fileEntity);
}
catch
{
return false;
}
}

public async Task<bool> RecallGroupMessage(uint groupUin, MessageResult result)
{
if (result.Sequence == null) return false;
Expand Down
72 changes: 70 additions & 2 deletions Lagrange.Core/Internal/Context/Uploader/FileUploader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,77 @@ namespace Lagrange.Core.Internal.Context.Uploader;
/// </summary>
internal static class FileUploader
{
public static Task<bool> UploadPrivate(ContextCollection context, MessageChain chain, IMessageEntity entity)
public static async Task<bool> UploadPrivate(ContextCollection context, MessageChain chain, IMessageEntity entity)
{
throw new NotImplementedException();
if (entity is not FileEntity { FileStream: not null } file) return false;

var uploadEvent = FileUploadEvent.Create(chain.Uid ?? "", file);
var result = await context.Business.SendEvent(uploadEvent);
var uploadResp = (FileUploadEvent)result[0];

var hwUrlEvent = HighwayUrlEvent.Create();
var highwayUrlResult = await context.Business.SendEvent(hwUrlEvent);
var ticketResult = (HighwayUrlEvent)highwayUrlResult[0];

var ext = new FileUploadExt
{
Unknown1 = 100,
Unknown2 = 1,
Entry = new FileUploadEntry
{
BusiBuff = new ExcitingBusiInfo
{
SenderUin = context.Keystore.Uin,
},
FileEntry = new ExcitingFileEntry
{
FileSize = file.FileStream.Length,
Md5 = file.FileMd5,
CheckKey = file.FileSha1,
Md5S2 = file.FileMd5,
FileId = uploadResp.FileId,
UploadKey = uploadResp.UploadKey
},
ClientInfo = new ExcitingClientInfo
{
ClientType = 3,
AppId = "100",
TerminalType = 3,
ClientVer = "1.1.1",
Unknown = 4
},
FileNameInfo = new ExcitingFileNameInfo
{
FileName = file.FileName
},
Host = new ExcitingHostConfig
{
Hosts = new List<ExcitingHostInfo>
{
new()
{
Url = new ExcitingUrlInfo
{
Unknown = 1,
Host = uploadResp.Ip
},
Port = uploadResp.Port
}
}
}
},
Unknown200 = 1
};

file.FileHash = uploadResp.Addon;
file.FileUuid = uploadResp.FileId;

bool hwSuccess = await context.Highway.UploadSrcByStreamAsync(95, file.FileStream, ticketResult.SigSession, file.FileMd5, ext.Serialize().ToArray());
if (!hwSuccess) return false;

var sendEvent = SendMessageEvent.Create(chain);
var sendResult = await context.Business.SendEvent(sendEvent);
return sendResult.Count != 0 && ((SendMessageEvent)sendResult[0]).MsgResult.Result == 0;
}

public static async Task<bool> UploadGroup(ContextCollection context, MessageChain chain, IMessageEntity entity)
Expand Down
42 changes: 42 additions & 0 deletions Lagrange.Core/Internal/Event/Message/FileUploadEvent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
using Lagrange.Core.Message.Entity;

namespace Lagrange.Core.Internal.Event.Message;

#pragma warning disable CS8618

internal class FileUploadEvent : ProtocolEvent
{
public string TargetUid { get; }

public FileEntity Entity { get; }

public string FileId { get; }

public byte[] UploadKey { get; }

public string Ip { get; }

public uint Port { get; }

public string Addon { get; }

private FileUploadEvent(string targetUid, FileEntity entity) : base(true)
{
TargetUid = targetUid;
Entity = entity;
}

private FileUploadEvent(int resultCode, string fileId, byte[] uploadKey, string ip, uint port, string addon) : base(resultCode)
{
FileId = fileId;
UploadKey = uploadKey;
Ip = ip;
Port = port;
Addon = addon;
}

public static FileUploadEvent Create(string targetUid, FileEntity entity) => new(targetUid, entity);

public static FileUploadEvent Result(int resultCode, string fileId, byte[] uploadKey, string ip, uint port, string addon)
=> new(resultCode, fileId, uploadKey, ip, port, addon);
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,21 @@ namespace Lagrange.Core.Internal.Packets.Service.Oidb.Request;
[OidbSvcTrpcTcp(0xE37, 1700)]
internal class OidbSvcTrpcTcp0xE37_1700
{
[ProtoMember(1)] public uint SubCommand => 1700;
[ProtoMember(1)] public uint Command { get; set; } // 1700

[ProtoMember(2)] public int Field2 { get; set; } // Unknown
[ProtoMember(2)] public int Seq { get; set; } // 0

[ProtoMember(101)] public int Field101 { get; set; } // Unknown
[ProtoMember(19)] public ApplyUploadReqV3 Upload { get; set; }

[ProtoMember(102)] public int Field102 { get; set; } // Unknown
[ProtoMember(101)] public int BusinessId { get; set; } // 3

[ProtoMember(200)] public int Field200 { get; set; } // Unknown
[ProtoMember(102)] public int ClientType { get; set; } // 1

[ProtoMember(200)] public int FlagSupportMediaPlatform { get; set; } // 1
}

[ProtoContract]
internal class OidbSvcTrpcTcp0xE37_1700Body
internal class ApplyUploadReqV3
{
[ProtoMember(10)] public string SenderUid { get; set; }

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
using ProtoBuf;

namespace Lagrange.Core.Internal.Packets.Service.Oidb.Response;

// Resharper disable InconsistentNaming
#pragma warning disable CS8618

[ProtoContract]
internal class OidbSvcTrpcTcp0xE37Response
{
[ProtoMember(1)] public uint Command { get; set; } // 1700

[ProtoMember(2)] public int Seq { get; set; } // 0

[ProtoMember(19)] public ApplyUploadRespV3 Upload { get; set; }

[ProtoMember(101)] public int BusinessId { get; set; } // 3

[ProtoMember(102)] public int ClientType { get; set; } // 1

[ProtoMember(200)] public int FlagSupportMediaPlatform { get; set; } // 1
}

[ProtoContract]
internal class ApplyUploadRespV3
{
[ProtoMember(10)] public int RetCode { get; set; }

[ProtoMember(20)] public string RetMsg { get; set; }

[ProtoMember(30)] public long TotalSpace { get; set; }

[ProtoMember(40)] public long UsedSpace { get; set; }

[ProtoMember(50)] public long UploadedSize { get; set; }

[ProtoMember(60)] public string UploadIp { get; set; }

[ProtoMember(70)] public string UploadDomain { get; set; }

[ProtoMember(80)] public uint UploadPort { get; set; }

[ProtoMember(90)] public string Uuid { get; set; }

[ProtoMember(100)] public byte[] UploadKey { get; set; }

[ProtoMember(110)] public bool BoolFileExist { get; set; }

[ProtoMember(120)] public int PackSize { get; set; }

[ProtoMember(130)] public List<string> UploadIpList { get; set; }

[ProtoMember(140)] public int UploadHttpsPort { get; set; }

[ProtoMember(150)] public string UploadHttpsDomain { get; set; }

[ProtoMember(160)] public string UploadDns { get; set; }

[ProtoMember(170)] public string UploadLanip { get; set; }

[ProtoMember(200)] public string FileAddon { get; set; }

[ProtoMember(220)] public byte[] MediaPlatformUploadKey { get; set; }
}
58 changes: 58 additions & 0 deletions Lagrange.Core/Internal/Service/Message/FileUploadService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
using Lagrange.Core.Common;
using Lagrange.Core.Internal.Event;
using Lagrange.Core.Internal.Event.Message;
using Lagrange.Core.Internal.Packets.Service.Oidb;
using Lagrange.Core.Internal.Packets.Service.Oidb.Request;
using Lagrange.Core.Internal.Packets.Service.Oidb.Response;
using Lagrange.Core.Utility.Binary;
using Lagrange.Core.Utility.Extension;
using ProtoBuf;

namespace Lagrange.Core.Internal.Service.Message;

[EventSubscribe(typeof(FileUploadEvent))]
[Service("OidbSvcTrpcTcp.0xe37_1700")]
internal class FileUploadService : BaseService<FileUploadEvent>
{
protected override bool Build(FileUploadEvent input, BotKeystore keystore, BotAppInfo appInfo, BotDeviceInfo device,
out BinaryPacket output, out List<BinaryPacket>? extraPackets)
{
if (input.Entity.FileStream is null) throw new Exception();

var packet = new OidbSvcTrpcTcpBase<OidbSvcTrpcTcp0xE37_1700>(new OidbSvcTrpcTcp0xE37_1700
{
Command = 1700,
Seq = 0,
Upload = new ApplyUploadReqV3
{
SenderUid = keystore.Uid ?? "",
ReceiverUid = input.TargetUid,
FileSize = (uint)input.Entity.FileStream.Length,
FileName = input.Entity.FileName,
Md510MCheckSum = input.Entity.FileStream.Md5(0, 10 * 1024 * 1024).UnHex(),
Sha1CheckSum = input.Entity.FileSha1,
LocalPath = "/",
Md5CheckSum = input.Entity.FileMd5,
Sha3CheckSum = Array.Empty<byte>()
},
BusinessId = 3,
ClientType = 1,
FlagSupportMediaPlatform = 1
});

output = packet.Serialize();
extraPackets = null;
return true;
}

protected override bool Parse(byte[] input, BotKeystore keystore, BotAppInfo appInfo, BotDeviceInfo device,
out FileUploadEvent output, out List<ProtocolEvent>? extraEvents)
{
var payload = Serializer.Deserialize<OidbSvcTrpcTcpResponse<OidbSvcTrpcTcp0xE37Response>>(input.AsSpan());
var upload = payload.Body.Upload;

output = FileUploadEvent.Result((int)payload.ErrorCode, upload.Uuid, upload.MediaPlatformUploadKey, upload.UploadIp, upload.UploadPort, upload.FileAddon);
extraEvents = null;
return true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ internal class GroupFSUploadService : BaseService<GroupFSUploadEvent>
protected override bool Build(GroupFSUploadEvent input, BotKeystore keystore, BotAppInfo appInfo, BotDeviceInfo device,
out BinaryPacket output, out List<BinaryPacket>? extraPackets)
{
if (input.Entity.FileStream is null) throw new Exception();

var packet = new OidbSvcTrpcTcpBase<OidbSvcTrpcTcp0x6D6_0>(new OidbSvcTrpcTcp0x6D6_0
{
File = new OidbSvcTrpcTcp0x6D6_0Upload
Expand All @@ -29,7 +31,7 @@ protected override bool Build(GroupFSUploadEvent input, BotKeystore keystore, Bo
FileName = input.Entity.FileName,
LocalDirectory = $"/{input.Entity.FileName}",
FileSize = input.Entity.FileSize,
FileSha1 = input.Entity.FileStream?.Sha1().UnHex() ?? Array.Empty<byte>(),
FileSha1 = input.Entity.FileStream.Sha1().UnHex(),
FileSha3 = Array.Empty<byte>(),
FileMd5 = input.Entity.FileMd5,
Field15 = true
Expand Down
6 changes: 6 additions & 0 deletions Lagrange.Core/Internal/Service/Message/PushMessageService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,11 @@ private static void ProcessEvent0x210(byte[] payload, PushMsg msg, List<Protocol
extraEvents.Add(recallEvent);
break;
}
case Event0x210SubType.GroupKickNotice when msg.Message.Body?.MsgContent is { } content:
{
// 0A710A4008AFB39FF80A1218755F54305768425A6368695A684555496253786F6F63474128AFB39FF80A3218755F54305768425A6368695A684555496253786F6F634741122108900410D40118D4012090845428A0850230ECB982AF06609084D48080808080021A0A0A00120608BDCCF4E802180122340A0E33302E3137312E3135392E32333510FE9D011A1E10900418A08502209084D480808080800230D401380140AFB39FF80A4801
break;
}
default:
{
Console.WriteLine($"Unknown Event0x210 message type: {pkgType}: {payload.Hex()}");
Expand Down Expand Up @@ -217,5 +222,6 @@ private enum Event0x210SubType
FriendRecallNotice = 138,
FriendRequestNotice = 226,
FriendPokeNotice = 290,
GroupKickNotice = 212,
}
}
6 changes: 3 additions & 3 deletions Lagrange.Core/Message/Entity/FileEntity.cs
Original file line number Diff line number Diff line change
Expand Up @@ -78,14 +78,14 @@ internal FileEntity(long fileSize, string fileName, byte[] fileMd5, string fileU
File = new NotOnlineFile
{
FileType = 0,
FileUuid = "",
FileUuid = FileUuid,
FileMd5 = FileMd5,
FileName = FileName,
FileSize = FileSize,
Subcmd = 1,
DangerEvel = 0,
ExpireTime = DateTime.Now.AddDays(7).Second,
FileHash = "" // TODO: Send out Oidb
ExpireTime = (int)(DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0) + TimeSpan.FromDays(7)).TotalSeconds,
FileHash = FileHash // TODO: Send out Oidb
}
};

Expand Down
13 changes: 13 additions & 0 deletions Lagrange.Core/Utility/Extension/StreamExt.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,19 @@ public static string Md5(this Stream stream, bool lower = false, bool space = fa
return hash.Hex(lower, space);
}

public static string Md5(this Stream stream, int offset, int count, bool lower = false, bool space = false)
{
using var temp = new MemoryStream(count);
stream.Seek(offset, SeekOrigin.Begin);
stream.CopyTo(temp, count);

using var md5 = MD5.Create();
var hash = md5.ComputeHash(temp);

stream.Seek(0, SeekOrigin.Begin);
return hash.Hex(lower, space);
}

public static string Sha1(this Stream stream, bool lower = false, bool space = false)
{
using var sha1 = SHA1.Create();
Expand Down
Loading

0 comments on commit 92da94f

Please sign in to comment.