GroupClient.pas 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588
  1. unit GroupClient;
  2. interface
  3. uses
  4. superobject, GroupUtility, WebSocket2, WebSocketClient, Classes, Graphics,
  5. blcksock, SysUtils, DateUtils, GroupConfig, GroupProtocols, synautil;
  6. type
  7. //表情类
  8. TFace = class
  9. private
  10. FName: String;
  11. FShortCut: String;
  12. FFileName: String;
  13. FMD5Code: String;
  14. FCategory: String;
  15. procedure SetFileName(const Value: String);
  16. public
  17. // constructor Create(AFileName, AShortCut, AName, AMD5Code: String; ACategory: String);
  18. // procedure Assign(AFace: TFace);
  19. // procedure SetFileName(Value: String);
  20. published
  21. property Name: String read FName write FName;
  22. property ShortCut: String read FShortCut write FShortCut;
  23. property FileName: String read FFileName write SetFileName;
  24. property MD5Code: String read FMD5Code write FMD5Code;
  25. property Category: String read FCategory write FCategory;
  26. end;
  27. TGroupClient = class
  28. private
  29. FClient: TTestWebSocketClientConnection;
  30. FProtocol: TGroupProtocol;
  31. FLoginName: string;
  32. FConnected: Boolean;
  33. FGroupMonitor: TObject;
  34. procedure OnOpen(aSender: TWebSocketCustomConnection);
  35. procedure OnRead(aSender: TWebSocketCustomConnection; aFinal, aRes1, aRes2, aRes3: boolean; aCode: integer; aData: TMemoryStream);
  36. procedure OnClose(aSender: TWebSocketCustomConnection; aCloseCode: integer; aCloseReason: string; aClosedByPeer: boolean);
  37. public
  38. constructor Create();
  39. destructor Destroy; override;
  40. procedure Send(AData: string); overload;
  41. procedure Send(AProtocol: string; AData: ISuperObject); overload;
  42. procedure Ping;
  43. function Connect(ALoginName: string = ''): Boolean;
  44. procedure Disconnect;
  45. { TODO -olqq -c : 群组操作 2015/6/2 9:50:42 }
  46. procedure CreateTeam(ATeamName, ATeamCallBoard, ATeamIntro: string; ATeamMembers: TStringList; AIsTempTeam: Boolean);
  47. procedure RemoveTeam(ATeamID: string);
  48. procedure UpdateTeamInfo(ATeamID, AIntro, ANotice, AName: string; AAuth: Integer);
  49. procedure SearchTeamById(ATeamID: string);
  50. procedure SearchTeam(ATeamID, AName, AIntro, ANotice: string; ASkip: Integer; ALimit: Integer = 20);
  51. { TODO -olqq -c : 群成员操作 2015/6/2 10:03:30 }
  52. procedure AddTeamMembers(ATeamID: string; AMembersID, AManagersID: TStringList);
  53. procedure RemoveTeamMembers(ATeamID: string; AMembersID, AManagersID: TStringList);
  54. procedure SetAlias(ATeamID, AMemberID, Alias: string);
  55. function GetAlias(ATeamID, AMemberID: string): string;
  56. procedure InviteJoin(ATeamID,AOperatorID,AOperatorMsg: string;AMembers: TStringList);
  57. procedure JoinTeam(ATeamID, AMsg: string);
  58. procedure JoinTeamResponse(ATeamID, AApplyId, AApplyMsg,AReplyId,AReplyUid,AReplyMsg: String);
  59. { TODO -olqq -c : 群消息 2015/6/2 10:11:20 }
  60. procedure SendTeamMessage(ATeamID, ASender, AMsg: string; AFont: TFont; AFaces: TStringList; Attachs: String);
  61. procedure MessageMisc(AMessagesID, AEventId: TStringList);
  62. { TODO -olqq -c : 群图片 2015/6/3 9:39:26 }
  63. procedure UploadFile(Hash, FileName, ID, GroupID: string);
  64. procedure DownloadTeamFace(AMD5String, AFileName, Path: string);
  65. procedure SendFilesRequest(AGroupId, AUserId, FileName: string);
  66. procedure Leave(ATeamID: string);
  67. procedure AddManager(ATeamID, AName: string);
  68. procedure RemoveManager(ATeamID, AName: string);
  69. procedure RemoveMember(ATeamID,AName: string);
  70. Procedure SendGetTeamInfo(ATeamID: string);
  71. property Connected: Boolean read FConnected write FConnected;
  72. end;
  73. implementation
  74. uses
  75. IdHTTP, LoggerImport, GroupMonitor, xFonts, {MainFrm,} IdMultipartFormData;
  76. const
  77. UPLOAD_URL: string = 'http://%s:%d/file/upload';
  78. { TGroupClient }
  79. procedure TGroupClient.CreateTeam(ATeamName, ATeamCallBoard, ATeamIntro: String;
  80. ATeamMembers: TStringList; AIsTempTeam: Boolean);
  81. var
  82. createGroup:String;
  83. jo, AData: ISuperObject;
  84. AMemebers: TSuperArray;
  85. iLoop: Integer;
  86. begin
  87. jo := SO(GROUP_CREATE_JSON);
  88. jo.S['id'] := '';
  89. jo.S['group.name'] := Trim(ATeamName);
  90. jo.I['group.type'] := 0;
  91. jo.S['group.creator'] := FLoginName;
  92. jo.S['group.intro'] := Trim(ATeamIntro);
  93. jo.S['group.notice'] := Trim(ATeamCallBoard);
  94. AMemebers := jo.A['group.members'];
  95. for iLoop := 0 to ATeamMembers.Count - 1 do
  96. AMemebers.S[iloop] := ATeamMembers[iLoop];
  97. Send(GROUP_CREATE_REQUEST, jo);
  98. end;
  99. procedure TGroupClient.RemoveTeam(ATeamID: String);
  100. var
  101. jo: ISuperObject;
  102. begin
  103. jo := SO('{"id":"", "group":{"id":""}}');
  104. jo.S['group.id'] := ATeamID;
  105. Send(GROUP_DEL_REQUEST, jo);
  106. end;
  107. procedure TGroupClient.UpdateTeamInfo(ATeamID, AIntro, ANotice, AName: string;
  108. AAuth: Integer);
  109. var
  110. jo: ISuperObject;
  111. begin
  112. jo := SO('{"id":"", "group":{"id":"","intro":"","notice":"","name":"","auth":0}}');
  113. jo.S['group.id'] := ATeamID;
  114. jo.S['group.intro'] := AIntro;
  115. jo.S['group.notice'] := ANotice;
  116. jo.S['group.name'] := AName;
  117. jo.I['group.auth'] := AAuth;
  118. Send(GROUP_UPDATE_REQUEST, jo);
  119. end;
  120. procedure TGroupClient.SearchTeamById(ATeamID: String);
  121. var
  122. jo: ISuperObject;
  123. begin
  124. jo := SO('{"id":"","group":{"id":""}}');
  125. jo.S['group.id'] := ATeamID;
  126. Send(GROUP_GET_REQUEST, jo);
  127. end;
  128. procedure TGroupClient.SearchTeam(ATeamID, AName, AIntro, ANotice: String; ASkip: Integer; ALimit: Integer = 20);
  129. var
  130. jo: ISuperObject;
  131. SearchGroup: String;
  132. begin
  133. jo := SO('{"id":"","group":{"id":"","intro":"","name":"","notice":"","skip":0,"limit":0}}');
  134. jo.S['group.id'] := ATeamID;
  135. jo.S['group.intro'] := AName;
  136. jo.S['group.name'] := AIntro;
  137. jo.S['group.notice'] := ANotice;
  138. jo.I['group.skip'] := ASkip;
  139. jo.I['group.limit'] := ALimit;
  140. Send(GROUP_QUERY_REQUEST, jo);
  141. end;
  142. procedure TGroupClient.AddTeamMembers(ATeamID: string; AMembersID,
  143. AManagersID: TStringList);
  144. var
  145. jo :ISuperObject;
  146. ja,ja1: TSuperArray;
  147. iLoop : Integer;
  148. begin
  149. jo := SO('{"id":"", "group":{"id":"","members":[],"managers": []}}');
  150. jo.S['group.id'] := ATeamID;
  151. ja := jo.A['group.members'];
  152. for iLoop := 0 to AMembersID.Count - 1 do
  153. ja.S[iloop] := AMembersID[iLoop];
  154. ja1 := jo.A['group.managers'];
  155. for iLoop := 0 to AManagersID.Count - 1 do
  156. ja1.S[iloop] := AManagersID[iLoop];
  157. Send(MEMBER_ADD_REQUEST, jo);
  158. end;
  159. procedure TGroupClient.RemoveTeamMembers(ATeamID: string; AMembersID,
  160. AManagersID: TStringList);
  161. var
  162. jo :ISuperObject;
  163. ja,ja1: TSuperArray;
  164. iLoop : Integer;
  165. begin
  166. jo := SO('{"id":"", "group":{"id":"","members":[],"managers": []}}');
  167. jo.S['group.id'] := ATeamID;
  168. ja := jo.A['group.members'];
  169. for iLoop := 0 to AMembersID.Count - 1 do
  170. ja.S[iloop] := AMembersID[iLoop];
  171. ja1 := jo.A['group.managers'];
  172. for iLoop := 0 to AManagersID.Count - 1 do
  173. ja1.S[iloop] := AManagersID[iLoop];
  174. Send(MEMBER_DEL_REQUEST, jo);
  175. end;
  176. procedure TGroupClient.SetAlias(ATeamID, AMemberID, Alias: string);
  177. var
  178. jo,jo1: ISuperObject;
  179. ja: TSuperArray;
  180. begin
  181. jo := SO('{"id":"","group":{"id":"","members":[]}}');
  182. jo1:= SO('{"id":"","alias":""}');
  183. jo.S['group.id']:= ATeamID;
  184. jo1.S['id'] := AMemberID;
  185. jo1.S['alias'] := Alias;
  186. ja := jo.A['group.members'];
  187. ja.Add(jo1);
  188. Send(MEMBER_UPDATE_REQUEST, jo);
  189. end;
  190. procedure TGroupClient.InviteJoin(ATeamID, AOperatorID, AOperatorMsg: string;
  191. AMembers: TStringList);
  192. var
  193. jo: ISuperObject;
  194. ja: TSuperArray;
  195. ILoop : Integer;
  196. begin
  197. jo := SO('{"id":"","group":{"id":"","members":[], "operator":{"id":"","msg":""}}}');
  198. jo.S['group.id']:= ATeamID;
  199. jo.S['group.operator.id']:= AOperatorID;
  200. jo.S['group.operator.msg']:= AOperatorMsg;
  201. ja := jo.A['group.members'];
  202. for iLoop := 0 to AMembers.Count - 1 do
  203. ja.S[iloop] := AMembers[iLoop];
  204. Send(INVITE_REQUEST, jo);
  205. end;
  206. procedure TGroupClient.JoinTeam(ATeamID, AMsg: string);
  207. var
  208. jo: ISuperObject;
  209. begin
  210. jo := SO('{"id":"","group":{"id":"","apply":{"uid":"","msg":""}}}');
  211. jo.S['group.id'] := ATeamID;
  212. jo.S['group.apply.msg'] := AMsg;
  213. Send(MEMBER_REPLY_REQUEST, jo);
  214. end;
  215. procedure TGroupClient.JoinTeamResponse(ATeamID, AApplyId, AApplyMsg,AReplyId,AReplyUid,AReplyMsg: string);
  216. var
  217. jo: ISuperObject;
  218. begin
  219. jo := SO('{"id":"","group":{"id":"","apply":{"uid":"","msg":""},"reply":{"id":"", "uid":"", "ret":0, "msg":""}}}');
  220. jo.S['group.id'] := ATeamID;
  221. jo.S['group.apply.id'] := AApplyId;
  222. jo.S['group.apply.msg'] := AApplyMsg;
  223. jo.S['group.reply.id'] := AReplyId;
  224. jo.S['group.reply.uid'] := AReplyUid;
  225. jo.S['group.reply.msg'] := AReplyMsg;
  226. Send(MEMBER_REPLY_RESPONSE, jo);
  227. end;
  228. procedure TGroupClient.SendTeamMessage(ATeamID, ASender, AMsg: String;
  229. AFont: TFont; AFaces: TStringList; Attachs: String);
  230. var
  231. jo, jofile: ISuperObject;
  232. ja: TSuperArray;
  233. iLoop : Integer;
  234. sendstr: String;
  235. AFace: TFace;
  236. begin
  237. jo := SO('{"id":"","group":{"id":[]},"msg":{"id":"","sender":"","style":[],"ts":"","txt":"","img":[],"attach":[]}}');
  238. ja := jo.A['group.id'];
  239. ja.S[0] := ATeamID;
  240. jo.S['msg.txt'] := AMsg;
  241. jo.S['msg.sender'] := ASender;
  242. jo.A['msg.style'].S[0] := AFont.Name;
  243. jo.A['msg.style'].S[1] := inttostr(AFont.Size);
  244. jo.A['msg.style'].S[2] := ColorToString(AFont.Color);
  245. jo.A['msg.style'].S[3] := FontStyleToString(AFont);
  246. jo.A['msg.attach'].S[0] := Attachs;
  247. jo.S['msg.ts'] := IntToStr((DateTimeToUnix(Now) - 8*60*60) * 1000);
  248. for iLoop := 0 to AFaces.Count - 1 do
  249. begin
  250. AFace := AFaces.Objects[iLoop] as TFace;
  251. jofile := SO();
  252. jofile.S['file'] := ExtractFileName(AFace.FileName);
  253. jofile.S['hash'] := UpperCase(AFace.MD5Code);
  254. jo.A['msg.img'].Add(jofile);
  255. end;
  256. Send(MESSAGE_SAY_REQUEST, jo);
  257. end;
  258. procedure TGroupClient.MessageMisc(AMessagesID, AEventId: TStringList);
  259. var
  260. jo: ISuperObject;
  261. ja,ja1: TSuperArray;
  262. iLoop : Integer;
  263. sendstr: String;
  264. begin
  265. jo := SO('{"id":"","message":{"id":[]},"event":{"id":[]}}');
  266. ja := jo.A['message.id'];
  267. for iLoop := 0 to AMessagesID.Count - 1 do
  268. ja.S[iloop] := AMessagesID[iLoop];
  269. ja1 := jo.A['event.id'];
  270. for iLoop := 0 to AEventId.Count - 1 do
  271. ja1.S[iloop] := AEventId[iLoop];
  272. Send(MARK_MK_REQUEST, jo);
  273. end;
  274. procedure TGroupClient.AddManager(ATeamID, AName: String);
  275. begin
  276. end;
  277. function GetSID(AResponseStr: string): string;
  278. var
  279. ACode: Byte;
  280. AStream: TStringStream;
  281. Len: Int64;
  282. begin
  283. Result := '';
  284. AStream := TStringStream.Create(AResponseStr);
  285. try
  286. AStream.Position :=1;
  287. Len := 0;
  288. AStream.Read(ACode, 1);
  289. while ACode <> $FF do
  290. begin
  291. Len := Len * 10;
  292. Inc(Len, ACode);
  293. AStream.Read(ACode, 1);
  294. end;
  295. //Code
  296. AStream.Read(ACode, 1);
  297. Result := AStream.ReadString(AStream.Size - AStream.Position);
  298. finally
  299. FreeAndNil(AStream);
  300. end;
  301. end;
  302. function TGroupClient.Connect(ALoginName: string = ''): Boolean;
  303. var
  304. AIdHttp:TIdHTTP;
  305. ResponeStr,sid: string;
  306. config: TGroupConfig;
  307. begin
  308. if ALoginName <> '' then
  309. FLoginName := ALoginName;
  310. if Trim(FLoginName) = '' then
  311. Exit;
  312. AIdHttp:= TIdHTTP.Create(nil);
  313. try
  314. config := TGroupConfig.GetConfig;
  315. ResponeStr := AIdHttp.get(Format(SHAKEHANDS_STEP1, [config.IP, config.Port, ALoginName, (DateTimeToUnix(Now) - 8*60*60) * 1000]));
  316. ResponeStr := GetSID(ResponeStr);
  317. sid := SO(ResponeStr).S['sid'];
  318. ResponeStr := AIdHttp.get(Format(SHAKEHANDS_STEP2, [config.IP, config.Port, ALoginName, (DateTimeToUnix(Now) - 8*60*60) * 1000, sid]));
  319. if FClient <> nil then
  320. FreeAndNil(FClient);
  321. FClient := TTestWebSocketClientConnection.Create(config.IP, IntToStr(config.Port),Format(WEBSOCKET_URL, [ALoginName, sid]),'-','ws');
  322. FClient.OnRead := OnRead;
  323. FClient.OnClose := OnClose;
  324. FClient.OnOpen := OnOpen;
  325. FClient.Start;
  326. except
  327. on E: Exception do
  328. begin
  329. Freeandnil(AIdHttp);
  330. Error(E.Message, 'TGroupClient.Connect');
  331. Exit;
  332. end;
  333. end;
  334. Freeandnil(AIdHttp);
  335. end;
  336. procedure TGroupClient.UploadFile(Hash, FileName, ID, GroupID: String);
  337. var
  338. AHttp: TIdHttp;
  339. MutPartForm: TIdMultiPartFormDataStream;
  340. Ret:TStringStream;
  341. response,UpUrl: String;
  342. jo,t,jofile: ISuperObject;
  343. SendStr: String;
  344. config: TGroupConfig;
  345. begin
  346. config := TGroupConfig.GetConfig;
  347. UpUrl := Format(UPLOAD_URL, [config.ImageIP, config.Port]);
  348. AHttp := Tidhttp.Create(nil);
  349. AHttp.Request.ContentType:='multipart/form-data';
  350. AHttp.HandleRedirects := true;
  351. AHttp.AllowCookies := true;
  352. MutPartForm := TIdMultiPartFormDataStream.Create;
  353. MutPartForm.AddFile('file1', FileName,'');
  354. try
  355. response := AHttp.Post(UpUrl, MutPartForm);
  356. finally
  357. MutPartForm.Free;
  358. AHttp.Free;
  359. end;
  360. if response = 'ok' then
  361. begin
  362. // jo := SO();
  363. // jo.S['name'] := 'group.file';
  364. // jo.S['args.id'] := id;
  365. // jo.S['args.groupid'] := GroupId;
  366. // t := SA([]);
  367. // jofile := SO();
  368. // jofile.S['file'] := ExtractFileName(filename);
  369. // jofile.S['hash'] := hash;
  370. // t.AsArray.Add(jofile);
  371. // jo['args.files'] := t;
  372. // SendStr := '5:::' + jo.AsJSon(False,False);
  373. // Send(SendStr);
  374. end;
  375. end;
  376. procedure TGroupClient.DownloadTeamFace(AMD5String, AFileName, Path: String);
  377. var
  378. FileStream: TFileStream;
  379. idHTTP: TIDHTTP;
  380. URL: String;
  381. ss: String;
  382. begin
  383. {
  384. URL := Format(DOWNLOAD_URL, [FImageIP, FImagePort, AMD5String]);
  385. FDownFile.OnComplete := DownFaceFileComplete;
  386. FDownFile.ThreadDownFile(URL,TRealICQClient.GetReceivedFaceDir+AFileName);
  387. }
  388. end;
  389. constructor TGroupClient.Create;
  390. begin
  391. FGroupMonitor := TGroupMonitor.Create;
  392. end;
  393. destructor TGroupClient.Destroy;
  394. begin
  395. FreeAndNil(FGroupMonitor);
  396. if FClient <> nil then
  397. FreeAndNil(FClient);
  398. inherited;
  399. end;
  400. procedure TGroupClient.Disconnect;
  401. begin
  402. (FGroupMonitor as TGroupMonitor).Stop;
  403. (FGroupMonitor as TGroupMonitor).KeepAlive := False;
  404. FClient.Close(wsCloseNormal, 'goodbye');
  405. end;
  406. function TGroupClient.GetAlias(ATeamID, AMemberID: string): string;
  407. begin
  408. end;
  409. procedure TGroupClient.Leave(ATeamID: string);
  410. begin
  411. end;
  412. procedure TGroupClient.OnClose(aSender: TWebSocketCustomConnection;
  413. aCloseCode: integer; aCloseReason: string; aClosedByPeer: boolean);
  414. begin
  415. FConnected := False;
  416. FClient := nil;
  417. (FGroupMonitor as TGroupMonitor).Stop;
  418. { TODO -olqq -c : 先把定时器关掉再开 2014/12/12 15:32:22 }
  419. if (aClosedByPeer) or (aCloseCode <> 1000) then
  420. begin
  421. Error(Format('异常断开. Code:%d;Reson:%s;ClolsedByPeer:%s;', [aCloseCode, aCloseReason, BoolToStr(aClosedByPeer)]), 'TGroup.OnClose');
  422. // Reconnect;
  423. end
  424. else
  425. Success(Format('正常断开. Code:%d;Reson:%s;ClolsedByPeer:%s;', [aCloseCode, aCloseReason, BoolToStr(aClosedByPeer)]), 'TGroup.OnClose');
  426. end;
  427. procedure TGroupClient.OnOpen(aSender: TWebSocketCustomConnection);
  428. begin
  429. Success(FLoginName, 'OnOpen');
  430. FConnected := True;
  431. FClient.SendText('2probe');
  432. (FGroupMonitor as TGroupMonitor).Start(Self);
  433. (FGroupMonitor as TGroupMonitor).KeepAlive := True;
  434. end;
  435. procedure TGroupClient.OnRead(aSender: TWebSocketCustomConnection; aFinal,
  436. aRes1, aRes2, aRes3: boolean; aCode: integer; aData: TMemoryStream);
  437. var
  438. s,Recvdata: string;
  439. c: TTestWebSocketClientConnection;
  440. begin
  441. try
  442. (FGroupMonitor as TGroupMonitor).ReflashLastTime;
  443. c := TTestWebSocketClientConnection(aSender);
  444. s := ReadStrFromStream(c.ReadStream, c.ReadStream.size{min(c.ReadStream.size, 10 * 1024)});
  445. if (c.ReadCode = wsCodeText) then
  446. Recvdata := utf8toansi(s)//CharsetConversion(s, UTF_8, GetCurCP)
  447. else
  448. Recvdata := s;
  449. if SameText(Recvdata, '3probe') then
  450. FClient.SendText('5');
  451. Success(Recvdata, 'TGroupClient.OnRead');
  452. if FProtocol = nil then
  453. Exit;
  454. FProtocol.Proccess(Recvdata);
  455. except
  456. on E: Exception do
  457. Error(E.Message, 'TGroupClient.OnRead('+Recvdata+')');
  458. end;
  459. end;
  460. procedure TGroupClient.Ping;
  461. begin
  462. if (FClient <> nil) and (not FClient.Closed) then
  463. FClient.SendText('2');
  464. end;
  465. procedure TGroupClient.RemoveManager(ATeamID, AName: String);
  466. begin
  467. end;
  468. procedure TGroupClient.RemoveMember(ATeamID, AName: String);
  469. begin
  470. end;
  471. procedure TGroupClient.Send(AProtocol: string; AData: ISuperObject);
  472. var
  473. AJo: ISuperObject;
  474. begin
  475. AJo := SO('[]');
  476. AJo.AsArray.S[0] := AProtocol;
  477. AJo.AsArray.O[1] := AData;
  478. Send('42' + AJo.Asjson);
  479. end;
  480. procedure TGroupClient.Send(AData: string);
  481. begin
  482. try
  483. if (FClient <> nil) and (not FClient.Closed) then
  484. FClient.SendText(AnsiToUTF8(AData));
  485. except
  486. on E: Exception do
  487. begin
  488. Error(E.Message, 'TGroupClient.Send('+AData+')');
  489. end;
  490. end;
  491. end;
  492. procedure TGroupClient.SendFilesRequest(AGroupId, AUserId, FileName: String);
  493. begin
  494. end;
  495. procedure TGroupClient.SendGetTeamInfo(ATeamID: String);
  496. begin
  497. end;
  498. { TFace }
  499. procedure TFace.SetFileName(const Value: String);
  500. begin
  501. FFileName := Value;
  502. end;
  503. end.