GroupClient.pas 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714
  1. unit GroupClient;
  2. interface
  3. uses
  4. superobject, WebSocket2, WebSocketClient, Classes, Graphics, synautil,
  5. blcksock, SysUtils, DateUtils, GroupUtility, GroupConfig, GroupProtocols,
  6. RealICQModel;
  7. type
  8. TGroupClient = class
  9. private
  10. FClient: TTestWebSocketClientConnection;
  11. FProtocol: TGroupProtocol;
  12. FLoginName: string;
  13. FConnected: Boolean;
  14. FGroupMonitor: TObject;
  15. FLastRecvMsg: ISuperObject;
  16. procedure GetMyGroups;
  17. procedure OnOpen(aSender: TWebSocketCustomConnection);
  18. procedure OnRead(aSender: TWebSocketCustomConnection; aFinal, aRes1, aRes2, aRes3: boolean; aCode: integer; aData: TMemoryStream);
  19. procedure OnClose(aSender: TWebSocketCustomConnection; aCloseCode: integer; aCloseReason: string; aClosedByPeer: boolean);
  20. public
  21. constructor Create();
  22. destructor Destroy; override;
  23. procedure Send(AData: string); overload;
  24. procedure Send(AProtocol: string; AData: ISuperObject); overload;
  25. procedure Ping;
  26. function Connect(ALoginName: string = ''): Boolean;
  27. procedure Disconnect;
  28. { TODO -olqq -c : 群组操作 2015/6/2 9:50:42 }
  29. procedure CreateTeam(ATeamName, ATeamCallBoard, ATeamIntro: string; ATeamMembers: TStringList; AIsTempTeam: Boolean; ATeamValidateType: TRealICQTeamValidateType);
  30. procedure RemoveTeam(ATeamID: string);
  31. procedure UpdateTeamInfo(ATeamID, AIntro, ANotice, AName: string; AAuth: Integer);
  32. procedure UpdateTeamCreator(ATeamID, AIntro, ANotice, AName: string; AAuth: Integer; ACreator: string);
  33. procedure SearchTeam(ATeamID, AName, AIntro, ANotice: string; AMatchingType: TRealICQMatchingType; ASkip: Integer = 0; ALimit: Integer = 20);
  34. procedure AsynTeam(ATeamID: string);
  35. procedure GetHistoryMessageCount(ATeamID: string);
  36. procedure GetHistoryMessages(ATeamID: string; ts: Int64);
  37. procedure ChangeActiveDevice;
  38. { TODO -olqq -c : 群成员操作 2015/6/2 10:03:30 }
  39. procedure AddTeamMembers(ATeamID: string; AMembersID, AManagersID: TStringList);
  40. procedure RemoveTeamMembers(ATeamID: string; AMembersID, AManagersID: TStringList);
  41. procedure SetAlias(ATeamID, AMemberID, Alias: string);
  42. function GetAlias(ATeamID, AMemberID: string): string;
  43. procedure InviteJoin(ATeamID, AOperatorID, AOperatorMsg: string; AMembers: TStringList);
  44. procedure JoinTeam(ATeamID, AMsg: string);
  45. procedure JoinTeamResponse(ATeamID, ALoginName, ATag: string; Accepted: Boolean);
  46. { TODO -olqq -c : 群消息 2015/6/2 10:11:20 }
  47. procedure SendTeamMessage(ATeamID, ASender, AMsg: string; AFont: TFont; AFaces: TStringList; Attachs: string);
  48. procedure GetOffineMessage;
  49. procedure MessageMisc(ATeamID: string);
  50. procedure MessageMiscMust(ATeamID: string);
  51. { TODO -olqq -c : 群图片 2015/6/3 9:39:26 }
  52. function UploadFile(Hash, FileName, ID, GroupID: string): Boolean;
  53. procedure SendFilesRequest(AGroupId, AUserId, FileName: string);
  54. property Connected: Boolean read FConnected write FConnected;
  55. end;
  56. {$INCLUDE LXTalk.inc}
  57. implementation
  58. uses
  59. IdHTTP, LoggerImport, GroupMonitor, xFonts, IdMultipartFormData,
  60. HTTPApp, RealICQClient, RealICQUtility;
  61. const
  62. UPLOAD_URL: string = 'http://%s:%d/file/upload';
  63. { TGroupClient }
  64. procedure TGroupClient.CreateTeam(ATeamName, ATeamCallBoard, ATeamIntro: string; ATeamMembers: TStringList; AIsTempTeam: Boolean; ATeamValidateType: TRealICQTeamValidateType);
  65. var
  66. createGroup: string;
  67. jo, AData: ISuperObject;
  68. AMemebers: TSuperArray;
  69. iLoop: Integer;
  70. begin
  71. //jo := SO(GROUP_CREATE_JSON);
  72. jo := SO('{"id":"", "group":{"name":"", "type":"", "creator":"", "intro":"", "notice":"","auth":0,"members":[]}}');
  73. jo.S['id'] := '';
  74. jo.S['group.name'] := Trim(ATeamName);
  75. jo.I['group.type'] := 0;
  76. jo.S['group.creator'] := FLoginName;
  77. jo.S['group.intro'] := Trim(ATeamIntro);
  78. jo.S['group.notice'] := Trim(ATeamCallBoard);
  79. //修复新建群组验证类型无效BUG
  80. jo.I['group.auth'] := Integer(ATeamValidateType);
  81. AMemebers := jo.A['group.members'];
  82. for iLoop := 0 to ATeamMembers.Count - 1 do
  83. AMemebers.S[iloop] := ATeamMembers[iLoop];
  84. Send(GROUP_CREATE_REQUEST, jo);
  85. end;
  86. procedure TGroupClient.RemoveTeam(ATeamID: string);
  87. var
  88. jo: ISuperObject;
  89. begin
  90. jo := SO('{"id":"", "group":{"id":""}}');
  91. jo.S['group.id'] := ATeamID;
  92. Send(GROUP_DEL_REQUEST, jo);
  93. end;
  94. procedure TGroupClient.UpdateTeamInfo(ATeamID, AIntro, ANotice, AName: string; AAuth: Integer);
  95. var
  96. jo: ISuperObject;
  97. begin
  98. jo := SO('{"id":"", "group":{"id":"","intro":"","notice":"","name":"","auth":0}}');
  99. jo.S['group.id'] := ATeamID;
  100. jo.S['group.intro'] := AIntro;
  101. jo.S['group.notice'] := ANotice;
  102. jo.S['group.name'] := AName;
  103. jo.I['group.auth'] := AAuth;
  104. Send(GROUP_UPDATE_REQUEST, jo);
  105. end;
  106. procedure TGroupClient.UpdateTeamCreator(ATeamID, AIntro, ANotice, AName: string; AAuth: Integer; ACreator: string);
  107. var
  108. jo: ISuperObject;
  109. begin
  110. jo := SO('{"id":"", "group":{"id":"","intro":"","notice":"","name":"","auth":0}}');
  111. jo.S['group.id'] := ATeamID;
  112. jo.S['group.intro'] := AIntro;
  113. jo.S['group.notice'] := ANotice;
  114. jo.S['group.name'] := AName;
  115. jo.I['group.auth'] := AAuth;
  116. jo.S['group.creator'] := ACreator;
  117. Send(GROUP_UPDATE_REQUEST, jo);
  118. end;
  119. procedure TGroupClient.AsynTeam(ATeamID: string);
  120. var
  121. jo: ISuperObject;
  122. begin
  123. jo := SO('{"id":"","group":{"id":""}}');
  124. jo.S['group.id'] := ATeamID;
  125. Send(GROUP_GET_REQUEST, jo);
  126. end;
  127. procedure TGroupClient.SearchTeam(ATeamID, AName, AIntro, ANotice: string; AMatchingType: TRealICQMatchingType; ASkip: Integer = 0; ALimit: Integer = 20);
  128. var
  129. jo: ISuperObject;
  130. SearchGroup: string;
  131. begin
  132. jo := SO('{"id":"","group":{"id":"","intro":"","name":"","notice":""},"skip":0,"limit":0}');
  133. jo.S['group.id'] := ATeamID;
  134. if AIntro <> '' then
  135. begin
  136. if AMatchingType = mtLikeSearch then
  137. jo.S['group.intro'] := '*' + AIntro
  138. else
  139. jo.S['group.intro'] := AIntro;
  140. end;
  141. if AName <> '' then
  142. begin
  143. if AMatchingType = mtLikeSearch then
  144. jo.S['group.name'] := '*' + AName
  145. else
  146. jo.S['group.name'] := AName;
  147. end;
  148. if ANotice <> '' then
  149. begin
  150. if AMatchingType = mtLikeSearch then
  151. jo.S['group.notice'] := '*' + ANotice
  152. else
  153. jo.S['group.notice'] := ANotice;
  154. end;
  155. jo.I['skip'] := ASkip;
  156. jo.I['limit'] := ALimit;
  157. Send(GROUP_QUERY_REQUEST, jo);
  158. end;
  159. procedure TGroupClient.AddTeamMembers(ATeamID: string; AMembersID, AManagersID: TStringList);
  160. var
  161. jo: ISuperObject;
  162. ja, ja1: TSuperArray;
  163. iLoop: Integer;
  164. begin
  165. jo := SO('{"id":"", "group":{"id":"","members":[],"managers": []}}');
  166. jo.S['group.id'] := ATeamID;
  167. ja := jo.A['group.members'];
  168. if (AMembersID <> nil) then
  169. for iLoop := 0 to AMembersID.Count - 1 do
  170. ja.S[iloop] := AMembersID[iLoop];
  171. ja1 := jo.A['group.managers'];
  172. if (AManagersID <> nil) then
  173. for iLoop := 0 to AManagersID.Count - 1 do
  174. ja1.S[iloop] := AManagersID[iLoop];
  175. Send(MEMBER_ADD_REQUEST, jo);
  176. end;
  177. procedure TGroupClient.RemoveTeamMembers(ATeamID: string; AMembersID, AManagersID: TStringList);
  178. var
  179. jo: ISuperObject;
  180. ja, ja1: TSuperArray;
  181. iLoop: Integer;
  182. begin
  183. jo := SO('{"id":"", "group":{"id":"","members":[],"managers": []}}');
  184. jo.S['group.id'] := ATeamID;
  185. if AMembersID <> nil then
  186. begin
  187. ja := jo.A['group.members'];
  188. for iLoop := 0 to AMembersID.Count - 1 do
  189. ja.S[iloop] := AMembersID[iLoop];
  190. end;
  191. if AManagersID <> nil then
  192. begin
  193. ja1 := jo.A['group.managers'];
  194. for iLoop := 0 to AManagersID.Count - 1 do
  195. ja1.S[iloop] := AManagersID[iLoop];
  196. end;
  197. Send(MEMBER_DEL_REQUEST, jo);
  198. end;
  199. procedure TGroupClient.SetAlias(ATeamID, AMemberID, Alias: string);
  200. var
  201. jo, jo1: ISuperObject;
  202. ja: TSuperArray;
  203. begin
  204. jo := SO('{"id":"","group":{"id":"","members":[]}}');
  205. jo1 := SO('{"id":"","alias":""}');
  206. jo.S['group.id'] := ATeamID;
  207. jo1.S['id'] := AMemberID;
  208. jo1.S['alias'] := Alias;
  209. ja := jo.A['group.members'];
  210. ja.Add(jo1);
  211. Send(MEMBER_UPDATE_REQUEST, jo);
  212. end;
  213. procedure TGroupClient.InviteJoin(ATeamID, AOperatorID, AOperatorMsg: string; AMembers: TStringList);
  214. var
  215. jo: ISuperObject;
  216. ja: TSuperArray;
  217. ILoop: Integer;
  218. begin
  219. jo := SO('{"id":"","group":{"id":"","members":[], "operator":{"id":"","msg":""}}}');
  220. jo.S['group.id'] := ATeamID;
  221. jo.S['group.operator.id'] := AOperatorID;
  222. jo.S['group.operator.msg'] := AOperatorMsg;
  223. ja := jo.A['group.members'];
  224. for iLoop := 0 to AMembers.Count - 1 do
  225. ja.S[iloop] := AMembers[iLoop];
  226. Send(INVITE_REQUEST, jo);
  227. end;
  228. procedure TGroupClient.JoinTeam(ATeamID, AMsg: string);
  229. var
  230. jo: ISuperObject;
  231. begin
  232. jo := SO('{"group":{"id":"","apply":{"uid":"","msg":""}}}');
  233. jo.S['group.id'] := ATeamID;
  234. jo.S['group.apply.msg'] := AMsg;
  235. jo.S['group.apply.uid'] := FLoginName;
  236. Send(MEMBER_APPLY_REQUEST, jo);
  237. end;
  238. procedure TGroupClient.JoinTeamResponse(ATeamID, ALoginName, ATag: string; Accepted: Boolean);
  239. var
  240. jo: ISuperObject;
  241. begin
  242. jo := SO('{"id":"","group":{"id":"","apply":{"uid":""},"reply":{"uid":"", "ret":0}}}');
  243. jo.S['group.id'] := ATeamID;
  244. jo.S['group.apply.uid'] := ALoginName;
  245. jo.S['group.reply.uid'] := FLoginName;
  246. jo.S['group.reply.msg'] := ATag;
  247. if Accepted then
  248. jo.I['group.reply.ret'] := 1
  249. else
  250. jo.I['group.reply.ret'] := 0;
  251. Send(MEMBER_REPLY_REQUEST, jo);
  252. end;
  253. procedure TGroupClient.SendTeamMessage(ATeamID, ASender, AMsg: string; AFont: TFont; AFaces: TStringList; Attachs: string);
  254. var
  255. jo, jofile, joNotify, joFont: ISuperObject;
  256. ja, jaHashs: TSuperArray;
  257. iLoop: Integer;
  258. sendstr: string;
  259. AFace: TFace;
  260. IMG_TAG, ATT_TAG: string;
  261. begin
  262. if Attachs <> '' then
  263. ATT_TAG := ',"attach":[]';
  264. if AFaces.Count > 0 then
  265. IMG_TAG := ',"img":[]';
  266. jo := SO('{"group":{"id":""},"content":""}');
  267. // if (Attachs = '') and (AFaces.Count = 0) then
  268. // jo := SO('{"group":{"id":""},"txt":""}')
  269. // else if (Attachs = '') and (AFaces.Count > 0) then
  270. // jo := SO('{"grou p":{"id":""},"txt":"","img":[]}')
  271. // else if (Attachs <> '') and (AFaces.Count = 0) then
  272. // jo := SO('{"group":{"id":""},"txt":"","attach":[]}')
  273. // else
  274. // jo := SO('{"group":{"id":""},"txt":"","img":[],"attach":[]}');
  275. jo.S['group.id'] := ATeamID;
  276. jo.S['content'] := AMsg;
  277. jo.I['isDes'] := 0;
  278. jo.I['msgType'] := 1;
  279. jo.I['fromClient'] := 0;
  280. jo.I['networkType'] := 0;
  281. joFont := FontToJson(AFont);
  282. if joFont <> nil then
  283. jo.O['style'] := joFont;
  284. if Attachs <> '' then
  285. begin
  286. jo.A['attach'].S[0] := Attachs;
  287. end;
  288. if AFaces.Count > 0 then
  289. begin
  290. joNotify := SO('{"group":{"id":""},"hashs":[]}');
  291. joNotify.S['group.id'] := ATeamID;
  292. jaHashs := joNotify.A['hashs'];
  293. for iLoop := 0 to AFaces.Count - 1 do
  294. begin
  295. AFace := AFaces.Objects[iLoop] as TFace;
  296. jofile := SO();
  297. jofile.S['file'] := ExtractFileName(AFace.FileName);
  298. jofile.S['hash'] := LowerCase(AFace.MD5Code);
  299. // jo.A['img'].Add(jofile);
  300. if UploadFile(jofile.S['hash'], jofile.S['file'], '', ATeamID) then
  301. jaHashs.Add(jofile);
  302. end;
  303. Send(MESSAGE_SAY_REQUEST, jo);
  304. if jaHashs.Length > 0 then
  305. Send(FILE_UPLOADED_REQUEST, joNotify);
  306. Exit;
  307. end;
  308. Send(MESSAGE_SAY_REQUEST, jo);
  309. {$IFDEF OldGroup}
  310. MessageMisc(ATeamID);
  311. {$ELSE}
  312. ChangeActiveDevice;
  313. MessageMisc(ATeamID);
  314. {$ENDIF}
  315. if Assigned(AFaces) and (AFaces.Count > 0) then
  316. TRealICQUtility.FreeStringList(AFaces as TStringList);
  317. end;
  318. procedure TGroupClient.MessageMisc(ATeamID: string);
  319. var
  320. ATick: Cardinal;
  321. begin
  322. ATick := FLastRecvMsg.I[ATeamID];
  323. if (ATick <> 0) and (GetTick - ATick < 5000) then
  324. Exit;
  325. MessageMiscMust(ATeamID);
  326. FLastRecvMsg.I[ATeamID] := GetTick;
  327. end;
  328. procedure TGroupClient.MessageMiscMust(ATeamID: string);
  329. var
  330. jo: ISuperObject;
  331. begin
  332. jo := SO('{"group":[]}');
  333. jo.A['group'].S[0] := ATeamID;
  334. Send(MARK_MK_REQUEST, jo);
  335. end;
  336. function GetSID(AResponseStr: string): string;
  337. var
  338. ACode: Byte;
  339. AStream: TStringStream;
  340. Len: Int64;
  341. begin
  342. Result := '';
  343. AStream := TStringStream.Create(AResponseStr);
  344. try
  345. AStream.Position := 1;
  346. Len := 0;
  347. AStream.Read(ACode, 1);
  348. while ACode <> $FF do
  349. begin
  350. Len := Len * 10;
  351. Inc(Len, ACode);
  352. AStream.Read(ACode, 1);
  353. end;
  354. //Code
  355. AStream.Read(ACode, 1);
  356. Result := AStream.ReadString(AStream.Size - AStream.Position);
  357. finally
  358. FreeAndNil(AStream);
  359. end;
  360. end;
  361. //{"socket":{"id":"639d9b0204f343a2acd5dfc3bf38b7f0","type":"mix","port":6714,"ver":"3.2.0","ip":"192.168.1.43","onlines":0},"storage":{"host":"127.0.0.1","port":6713}}
  362. function GatewayResponse(AJsonStr: string): Boolean;
  363. var
  364. jo: ISuperObject;
  365. config: TGroupConfig;
  366. begin
  367. Result := False;
  368. jo := SO(AJsonStr);
  369. if jo = nil then
  370. Exit;
  371. config := TGroupConfig.GetConfig;
  372. config.IP := jo.S['socket.host'];
  373. config.Port := jo.I['socket.port'];
  374. config.ImageIP := jo.S['storage.host'];
  375. config.ImagePort := jo.I['storage.port'];
  376. Result := True;
  377. end;
  378. procedure TGroupClient.ChangeActiveDevice;
  379. var
  380. jo: ISuperObject;
  381. begin
  382. jo := SO();
  383. jo.S['deviceID'] := 'pc';
  384. jo.B['on'] := True;
  385. Send(MARK_A_Q, jo);
  386. end;
  387. function TGroupClient.Connect(ALoginName: string = ''): Boolean;
  388. var
  389. AIdHttp: TIdHTTP;
  390. ResponeStr, sid: string;
  391. config: TGroupConfig;
  392. AURL: string;
  393. begin
  394. if ALoginName <> '' then
  395. FLoginName := ALoginName;
  396. if Trim(FLoginName) = '' then
  397. Exit;
  398. AIdHttp := TIdHTTP.Create(nil);
  399. try
  400. config := TGroupConfig.GetConfig;
  401. if config.GatewayEnable then
  402. begin
  403. config.RandomGatewayServer;
  404. AURL := Format(GATEWAY_URL, [config.GatewayIP, config.GatewayPort]);
  405. ResponeStr := AIdHttp.Get(AURL);
  406. if not GatewayResponse(ResponeStr) then
  407. Exit;
  408. end;
  409. SUCCESS(Format('%s:%d', [config.IP, config.Port]), '群组服务地址');
  410. AURL := Format(SHAKEHANDS_STEP1, [config.IP, config.Port, HTTPEncode(AnsiToUtf8(FLoginName)), (DateTimeToUnix(Now) - 8 * 60 * 60) * 1000]);
  411. ResponeStr := AIdHttp.get(AURL);
  412. ResponeStr := GetSID(ResponeStr);
  413. sid := SO(ResponeStr).S['sid'];
  414. AURL := Format(SHAKEHANDS_STEP2, [config.IP, config.Port, HTTPEncode(AnsiToUtf8(FLoginName)), (DateTimeToUnix(Now) - 8 * 60 * 60) * 1000, sid]);
  415. ResponeStr := AIdHttp.get(AURL);
  416. if FClient <> nil then
  417. FreeAndNil(FClient);
  418. AURL := Format(WEBSOCKET_URL, [HTTPEncode(AnsiToUtf8(FLoginName)), sid]);
  419. FClient := TTestWebSocketClientConnection.Create(config.IP, IntToStr(config.Port), AURL, '-', 'ws');
  420. FClient.OnRead := OnRead;
  421. FClient.OnClose := OnClose;
  422. FClient.OnOpen := OnOpen;
  423. FClient.Start;
  424. except
  425. on E: Exception do
  426. begin
  427. Freeandnil(AIdHttp);
  428. Error(E.Message, 'TGroupClient.Connect');
  429. Exit;
  430. end;
  431. end;
  432. Freeandnil(AIdHttp);
  433. end;
  434. function TGroupClient.UploadFile(Hash, FileName, ID, GroupID: string): Boolean;
  435. var
  436. AHttp: TIdHttp;
  437. MutPartForm: TIdMultiPartFormDataStream;
  438. Ret: TStringStream;
  439. response, UpUrl: string;
  440. jo, t, jofile: ISuperObject;
  441. SendStr: string;
  442. config: TGroupConfig;
  443. begin
  444. Result := False;
  445. config := TGroupConfig.GetConfig;
  446. UpUrl := Format(UPLOAD_URL, [config.ImageIP, config.ImagePort]);
  447. AHttp := Tidhttp.Create(nil);
  448. AHttp.Request.ContentType := 'multipart/form-data';
  449. AHttp.HandleRedirects := true;
  450. AHttp.AllowCookies := true;
  451. MutPartForm := TIdMultiPartFormDataStream.Create;
  452. MutPartForm.AddFile('file1', TRealICQClient.GetReceivedFaceDir + FileName, '');
  453. try
  454. response := AHttp.Post(UpUrl, MutPartForm);
  455. finally
  456. MutPartForm.Free;
  457. AHttp.Free;
  458. end;
  459. if response = 'ok' then
  460. Result := True;
  461. end;
  462. constructor TGroupClient.Create;
  463. begin
  464. FGroupMonitor := TGroupMonitor.Create;
  465. FProtocol := TGroupProtocol.Create(Self);
  466. FLastRecvMsg := SO('{}');
  467. end;
  468. destructor TGroupClient.Destroy;
  469. var
  470. PInt: PInteger;
  471. begin
  472. FreeAndNil(FGroupMonitor);
  473. if FClient <> nil then
  474. FreeAndNil(FClient);
  475. FLastRecvMsg := nil;
  476. FProtocol.Free;
  477. inherited;
  478. end;
  479. procedure TGroupClient.Disconnect;
  480. begin
  481. (FGroupMonitor as TGroupMonitor).Stop;
  482. (FGroupMonitor as TGroupMonitor).KeepAlive := False;
  483. if FConnected then
  484. begin
  485. FClient.Close(wsCloseNormal, 'goodbye');
  486. FConnected := False;
  487. end;
  488. end;
  489. function TGroupClient.GetAlias(ATeamID, AMemberID: string): string;
  490. begin
  491. end;
  492. procedure TGroupClient.GetHistoryMessageCount(ATeamID: string);
  493. var
  494. jo: ISuperObject;
  495. begin
  496. jo := SO();
  497. jo.N['filter'].S['group'] := ATeamID;
  498. Send(HISTORY_C_Q, jo);
  499. end;
  500. {
  501. group: <id>|<Group>, // 群组编号
  502. ts: <Number>|<String>, // * > >= < <= = Number
  503. skip: <Number>, // *偏移
  504. limit: <Number> // *限制
  505. }
  506. procedure TGroupClient.GetHistoryMessages(ATeamID: string; ts: Int64);
  507. var
  508. jo, joFilter: ISuperObject;
  509. begin
  510. {$IFNDEF OldGroup}
  511. if ts = 0 then
  512. Exit;
  513. jo := SO();
  514. joFilter := SO();
  515. joFilter.S['group'] := ATeamID;
  516. joFilter.S['ts'] := '>' + IntToStr(ts);
  517. joFilter.I['limit'] := 10000;
  518. jo.O['filter'] := joFilter;
  519. Send(HISTORY_H_Q, jo);
  520. {$ENDIF}
  521. end;
  522. procedure TGroupClient.GetMyGroups;
  523. var
  524. jo: ISuperObject;
  525. begin
  526. jo := SO('{}');
  527. jo.S['user'] := FLoginName;
  528. Send(USER_LI_REQUEST, jo);
  529. end;
  530. procedure TGroupClient.GetOffineMessage;
  531. var
  532. jo: ISuperObject;
  533. begin
  534. // jo := SO('{}');
  535. // jo.S['uid'] := FLoginName;
  536. // Send(MESSAGE_OFFLINE_REQUEST, jo);
  537. end;
  538. procedure TGroupClient.OnClose(aSender: TWebSocketCustomConnection; aCloseCode: integer; aCloseReason: string; aClosedByPeer: boolean);
  539. begin
  540. FConnected := False;
  541. FClient := nil;
  542. (FGroupMonitor as TGroupMonitor).Stop;
  543. if (aClosedByPeer) or (aCloseCode <> 1000) then
  544. begin
  545. Error(Format('异常断开. Code:%d;Reson:%s;ClolsedByPeer:%s;', [aCloseCode, aCloseReason, BoolToStr(aClosedByPeer)]), 'TGroupClient.OnClose');
  546. end
  547. else
  548. Success(Format('正常断开. Code:%d;Reson:%s;ClolsedByPeer:%s;', [aCloseCode, aCloseReason, BoolToStr(aClosedByPeer)]), 'TGroupClient.OnClose');
  549. end;
  550. procedure TGroupClient.OnOpen(aSender: TWebSocketCustomConnection);
  551. begin
  552. FConnected := True;
  553. FClient.SendText('2probe');
  554. (FGroupMonitor as TGroupMonitor).Start(Self);
  555. (FGroupMonitor as TGroupMonitor).KeepAlive := True;
  556. end;
  557. procedure TGroupClient.OnRead(aSender: TWebSocketCustomConnection; aFinal, aRes1, aRes2, aRes3: boolean; aCode: integer; aData: TMemoryStream);
  558. var
  559. s: UTF8String;
  560. Recvdata: string;
  561. c: TTestWebSocketClientConnection;
  562. begin
  563. try
  564. (FGroupMonitor as TGroupMonitor).ReflashLastTime;
  565. c := TTestWebSocketClientConnection(aSender);
  566. s := ReadStrFromStream(c.ReadStream, c.ReadStream.size);
  567. if (c.ReadCode = wsCodeText) then
  568. Recvdata := utf8toansi(s)//CharsetConversion(s, UTF_8, GetCurCP)
  569. else
  570. Recvdata := s;
  571. if SameText(Recvdata, '3probe') then
  572. begin
  573. FClient.SendText('5');
  574. GetMyGroups;
  575. Exit;
  576. end;
  577. if (Length(Recvdata) < 4) or (FProtocol = nil) then
  578. Exit;
  579. Success(Recvdata, 'TGroupClient.OnRead');
  580. FProtocol.Proccess(Recvdata);
  581. except
  582. on E: Exception do
  583. Error(E.Message, 'TGroupClient.OnRead(' + Recvdata + ')');
  584. end;
  585. end;
  586. procedure TGroupClient.Ping;
  587. begin
  588. if (FClient <> nil) and (not FClient.Closed) then
  589. FClient.SendText('2');
  590. end;
  591. procedure TGroupClient.Send(AProtocol: string; AData: ISuperObject);
  592. var
  593. AJo: ISuperObject;
  594. begin
  595. AJo := SO('[]');
  596. AJo.AsArray.S[0] := AProtocol;
  597. AJo.AsArray.O[1] := AData;
  598. Send('42' + AJo.Asjson);
  599. end;
  600. procedure TGroupClient.Send(AData: string);
  601. begin
  602. try
  603. if (FClient <> nil) and (not FClient.Closed) then
  604. FClient.SendText(AnsiToUTF8(AData));
  605. Success(AData, 'TGroupClient.Send');
  606. except
  607. on E: Exception do
  608. begin
  609. Error(E.Message, 'TGroupClient.Send(' + AData + ')');
  610. end;
  611. end;
  612. end;
  613. procedure TGroupClient.SendFilesRequest(AGroupId, AUserId, FileName: string);
  614. begin
  615. end;
  616. end.