1+ using System . Buffers ;
2+ using System . Security . Cryptography ;
3+ using Lagrange . Core . Exceptions ;
4+ using Lagrange . Core . Internal . Events . Message ;
5+ using Lagrange . Core . Internal . Events . System ;
6+ using Lagrange . Core . Internal . Packets . Service ;
7+ using Lagrange . Core . Utility ;
8+ using Lagrange . Core . Utility . Cryptography ;
9+
10+ namespace Lagrange . Core . Internal . Logic ;
11+
12+ internal class OperationLogic ( BotContext context ) : ILogic
13+ {
14+ public async Task < bool > SendFriendFile ( long targetUin , Stream fileStream , string ? fileName )
15+ {
16+ if ( fileName == null )
17+ {
18+ if ( fileStream is FileStream file )
19+ {
20+ fileName = Path . GetFileName ( file . Name ) ;
21+ }
22+ else
23+ {
24+ Span < byte > bytes = stackalloc byte [ 16 ] ;
25+ Random . Shared . NextBytes ( bytes ) ;
26+ fileName = Convert . ToHexString ( bytes ) ;
27+ }
28+ }
29+
30+ var friend = await context . CacheContext . ResolveFriend ( targetUin ) ?? throw new InvalidTargetException ( targetUin ) ;
31+ var request = new FileUploadEventReq ( friend . Uid , fileStream , fileName ) ;
32+ var result = await context . EventContext . SendEvent < FileUploadEventResp > ( request ) ;
33+
34+ var buffer = ArrayPool < byte > . Shared . Rent ( 10 * 1024 * 1024 ) ;
35+ int payload = request . FileStream . Read ( buffer ) ;
36+ var md510m = MD5 . HashData ( buffer [ ..payload ] ) ;
37+ ArrayPool < byte > . Shared . Return ( buffer ) ;
38+ request . FileStream . Seek ( 0 , SeekOrigin . Begin ) ;
39+
40+ if ( ! result . IsExist )
41+ {
42+ var ext = new FileUploadExt
43+ {
44+ Unknown1 = 100 ,
45+ Unknown2 = 1 ,
46+ Entry = new FileUploadEntry
47+ {
48+ BusiBuff = new ExcitingBusiInfo { SenderUin = context . Keystore . Uin } ,
49+ FileEntry = new ExcitingFileEntry
50+ {
51+ FileSize = fileStream . Length ,
52+ Md5 = request . FileMd5 ,
53+ CheckKey = request . FileSha1 ,
54+ Md510M = md510m ,
55+ Sha3 = TriSha1Provider . CalculateTriSha1 ( fileStream ) ,
56+ FileId = result . FileId ,
57+ UploadKey = result . UploadKey
58+ } ,
59+ ClientInfo = new ExcitingClientInfo
60+ {
61+ ClientType = 3 ,
62+ AppId = "100" ,
63+ TerminalType = 3 ,
64+ ClientVer = "1.1.1" ,
65+ Unknown = 4
66+ } ,
67+ FileNameInfo = new ExcitingFileNameInfo { FileName = fileName } ,
68+ Host = new ExcitingHostConfig
69+ {
70+ Hosts = result . RtpMediaPlatformUploadAddress . Select ( x => new ExcitingHostInfo
71+ {
72+ Url = new ExcitingUrlInfo { Unknown = 1 , Host = x . Item1 } ,
73+ Port = x . Item2
74+ } ) . ToList ( )
75+ }
76+ } ,
77+ Unknown200 = 1
78+ } ;
79+
80+ bool success = await context . HighwayContext . UploadFile ( fileStream , 95 , ProtoHelper . Serialize ( ext ) ) ;
81+ if ( ! success ) return false ;
82+ }
83+
84+ int sequence = Random . Shared . Next ( 10000 , 99999 ) ;
85+ uint random = ( uint ) Random . Shared . Next ( ) ;
86+ var sendResult = await context . EventContext . SendEvent < SendMessageEventResp > ( new SendFriendFileEventReq ( friend , request , result , sequence , random ) ) ;
87+ if ( sendResult . Result != 0 ) throw new OperationException ( sendResult . Result ) ;
88+
89+ return true ;
90+ }
91+ }
0 commit comments