TextMessageService.pas 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450
  1. unit TextMessageService;
  2. interface
  3. uses
  4. BaseService, PerlRegEx, Classes, SysUtils, StrUtils, RealICQModel, Forms;
  5. type
  6. TTextMessageService = class(TBaseService)
  7. private
  8. function GetImageReplacementStr(AImgUrl: string; ATalkingForm: TForm): string;
  9. function GetMapReplacementStr(AImgUrl: string; ATalkingForm: TForm): string;
  10. function GetVoiceReplacementStr(AVoiceUrl: string): string;
  11. function GetGradeReplacementStr(AGradeUrl: string; AShowForm: Boolean = False): string;
  12. public
  13. procedure HandleAsycTextMessage(AData: Array of Byte);
  14. function PreProccess(ATalkingForm: TForm; ASender: String; AMessageContent: string; AShowCustomFace: Boolean = True): string;
  15. function ContentFilter(AMsg: TRealICQMessage): string;
  16. constructor Create;
  17. destructor Destroy; override;
  18. class function GetService: TTextMessageService; static;
  19. end;
  20. implementation
  21. uses
  22. Windows, RealICQDBHistory, MainFrm, TalkingFrm, IdURI, ShareUtils,
  23. DownloadFaceWithHttp, RealICQClient, MessagesHander, HttpDownloader, MD5, BaseChromeView,
  24. UsersService;
  25. var
  26. ATextMessageService: TTextMessageService;
  27. const
  28. IMAGE_LOADED_TAG: string = '<img oncontextmenu="location.href=''FaceMenu_%s'';return false;" src="%s" align="absBottom" hspace="1" onload="AutoResizeImage(250,250,this)" onclick="openInIE(this)">';
  29. IMAGE_LOADING_TAG: string = '<img ID = "%s" oncontextmenu="location.href=''FaceMenu_%s'';return false;" src="%s" align="absBottom" hspace="1" onload="AutoResizeImage(250,250,this)" onclick="openInIE(this)">';
  30. VOICE_TAG: string = '<object id="%s" width="300" height="63" classid="CLSID:6BF52A52-394A-11d3-B153-00C04F79FAA6" codebase="http://activex.microsoft.com/activex/controls/mplayer/en/nsmp2inf.cab#Version=7.0" align="top" border="0" type="application/x-oleobject">' +
  31. '<param name="URL" value="%s">' +
  32. '<param name="AUTOSTART" value="0">' +
  33. '<param name="uiMode" value="mini">' +
  34. '</object>';
  35. MAP_IFRAME_TAG: string = '<iframe src="%s" frameborder="no" border="0" ></iframe>';
  36. { TTextMessageService }
  37. function TTextMessageService.ContentFilter(AMsg: TRealICQMessage): string;
  38. var
  39. reg: TPerlRegEx;
  40. begin
  41. reg := TPerlRegEx.Create;
  42. try
  43. reg.Subject := AMsg.MessageStr;
  44. reg.RegEx := '\[(\w+)\-src=\"(http://[\w\W]+)\"]';
  45. while reg.MatchAgain do
  46. begin
  47. if CompareText(reg.Groups[1], 'grade') = 0 then
  48. begin
  49. reg.Replacement := GetGradeReplacementStr(
  50. reg.Groups[2],
  51. not SameText(TUsersService.GetUsersService.GetMe.LoginName, AMsg.Sender));
  52. reg.Subject := reg.Replace();
  53. end;
  54. end;
  55. Result := reg.Subject;
  56. finally
  57. reg.Free;
  58. end;
  59. end;
  60. constructor TTextMessageService.Create;
  61. begin
  62. inherited;
  63. end;
  64. destructor TTextMessageService.Destroy;
  65. begin
  66. inherited;
  67. end;
  68. class function TTextMessageService.GetService: TTextMessageService;
  69. begin
  70. if ATextMessageService = nil then
  71. ATextMessageService := TTextMessageService.Create;
  72. Result := ATextMessageService;
  73. end;
  74. function TTextMessageService.GetGradeReplacementStr(AGradeUrl: string; AShowForm: Boolean = False): string;
  75. var
  76. AForm: TBaseChromeViewForm;
  77. begin
  78. Result := '请您为我们这次服务给个评分或提个建议,谢谢!';
  79. if AShowForm then
  80. begin
  81. AForm := TBaseChromeViewForm.Create(nil);
  82. try
  83. AForm.Caption := '评分系统';
  84. AForm.ChangeUIColor(MainForm.FormColor);
  85. AForm.Width := 720;
  86. AForm.Height := 394;
  87. AForm.Top := (Screen.Height - 394) div 2;
  88. AForm.Left := (Screen.Width - 720) div 2;
  89. AForm.URL := AnsiReplaceText(AGradeUrl, '&amp;', '&');
  90. AForm.Show;
  91. finally
  92. end;
  93. end;
  94. end;
  95. function TTextMessageService.GetVoiceReplacementStr(AVoiceUrl: string): string;
  96. var
  97. AMD5String, ALocalPath, AFileName, AFaceID: string;
  98. AURL: TIdURI;
  99. ATask: THttpDownloader;
  100. WaitingFace: TWaitingFace;
  101. begin
  102. // Result := Format(MAP_IFRAME_TAG, [ExtractFilePath(Application.ExeName) + 'html\mp3.html']);
  103. AURL := TIdURI.Create();
  104. AURL.URI := AVoiceUrl;
  105. AMD5String := ChangeFileExt(ExtractFileName(AURL.Document),'');
  106. if not (CompareText(ExtractFileExt(AURL.Document), '.mp3') = 0) then
  107. begin
  108. Result := '对不起,目前只支持MP3音频格式';
  109. AURL.Free;
  110. Exit;
  111. end;
  112. ALocalPath := TRealICQClient.GetReceivedFaceDir + ExtractFileName(AURL.Document);
  113. AFileName := ReplaceStr(ALocalPath, '\', '/');
  114. // Dialog.ShowMessage(Format(VOICE_TAG, ['voice_'+AMD5String, AFileName]));
  115. Result := Format(VOICE_TAG, ['voice_'+AMD5String, AFileName]);
  116. if not FileExists(ALocalPath) then
  117. begin
  118. ATask := THttpDownloader.Create(AURL.URI, ALocalPath, AThreadPool.AcquireYarn);
  119. AThreadPool.StartYarn(ATask.Yarn, ATask);
  120. end;
  121. AURL.Free;
  122. end;
  123. procedure TTextMessageService.HandleAsycTextMessage(AData: array of Byte);
  124. var
  125. FontStrLength,
  126. SenderLoginNameLength,
  127. ReceiverLoginNameLength: Byte;
  128. nIndex, IsEncry,
  129. MessageStrLength: SmallInt;
  130. MessageID: Cardinal;
  131. SendDateTime: TDateTime;
  132. SenderLoginName,
  133. ReceiverLoginName,
  134. FontStr,
  135. MessageStr: String;
  136. RealICQMessage: TRealICQMessage;
  137. RealICQUser: TRealICQUser;
  138. TalkingForm: TTalkingForm;
  139. begin
  140. nIndex := 0;
  141. //取 (3)接收人用户名长度 1byte
  142. CopyMemory(@ReceiverLoginNameLength, @AData[nIndex], 1);
  143. Inc(nIndex, 1);
  144. //取 (4)接收人用户名 动态长度,由(3)指定,接收消息的用户的用户名,如果是服务器中转此处会变成消息的发送人。
  145. SetLength(ReceiverLoginName, ReceiverLoginNameLength);
  146. CopyMemory(PChar(ReceiverLoginName), @AData[nIndex], ReceiverLoginNameLength);
  147. Inc(nIndex, ReceiverLoginNameLength);
  148. //取 (5)发送人用户名长度 1byte
  149. CopyMemory(@SenderLoginNameLength, @AData[nIndex], 1);
  150. Inc(nIndex, 1);
  151. //取 (6)发送人用户名 动态长度,由(5)指定。
  152. SetLength(SenderLoginName, SenderLoginNameLength);
  153. CopyMemory(PChar(SenderLoginName), @AData[nIndex], SenderLoginNameLength);
  154. Inc(nIndex, SenderLoginNameLength);
  155. //取 (7)消息的编号 4byte,无符号32位整型数据
  156. CopyMemory(@MessageID, @AData[nIndex], 4);
  157. Inc(nIndex, 4);
  158. //取 (8)发送消息的时间 8byte,64位浮点类型(double即TDateTime类型)
  159. CopyMemory(@SendDateTime, @AData[nIndex], 8);
  160. Inc(nIndex, 8);
  161. //取 (9)字体信息长度 1byte,
  162. CopyMemory(@FontStrLength, @AData[nIndex], 1);
  163. Inc(nIndex, 1);
  164. //取 (10)字体信息 动态长度,由(9)指定。
  165. SetLength(FontStr, FontStrLength);
  166. CopyMemory(PChar(FontStr), @AData[nIndex], FontStrLength);
  167. Inc(nIndex, FontStrLength);
  168. //取 (11)消息的长度 2byte,无符号16位整型。
  169. CopyMemory(@MessageStrLength, @AData[nIndex], 2);
  170. Inc(nIndex, 2);
  171. //取 (12)消息内容 动态长度,由(11)指定。
  172. SetLength(MessageStr, MessageStrLength);
  173. CopyMemory(PChar(MessageStr), @AData[nIndex], MessageStrLength);
  174. Inc(nIndex, MessageStrLength);
  175. //取(11)是否是私密消息
  176. CopyMemory(@IsEncry, @AData[nIndex], 1);
  177. RealICQMessage := TRealICQMessage.Create(SenderLoginName,
  178. ReceiverLoginName,
  179. FontStr,
  180. MessageStr,IsEncry=1);
  181. RealICQMessage.MessageID := GetTickCount; //设为接收到此消息的时间,以便及时删除无用的消息
  182. RealICQMessage.SendDateTime := SendDateTime;
  183. MainForm.DBHistory.SaveMessage('-1', RealICQMessage.Sender, RealICQMessage.Receiver,
  184. RealICQMessage.SendDateTime,
  185. RealICQMessage.FontStr,
  186. RealICQMessage.MessageStr,RealICQMessage.IsEncryMessage);
  187. TalkingForm := GetTalkingForm(ReceiverLoginName, MainForm.RealICQClient);
  188. if (TalkingForm <> nil) and (TalkingForm.CanWriteMessage) then
  189. begin
  190. TalkingForm.ShowMessage(RealICQMessage, false);
  191. end;
  192. end;
  193. function TTextMessageService.PreProccess(ATalkingForm: TForm; ASender: String; AMessageContent: string; AShowCustomFace: Boolean = True): string;
  194. var
  195. Face: TFace;
  196. iLoop,
  197. iStart,
  198. iIndex: Integer;
  199. MD5String: String;
  200. WaitingFace: TWaitingFace;
  201. FaceID,
  202. AFileName,
  203. ContextMenuStr: String;
  204. reg: TPerlRegEx;
  205. procedure ReplacesTag;
  206. begin
  207. while reg.MatchAgain do
  208. begin
  209. MD5String := reg.Groups[1];
  210. iIndex := MainForm.FaceList.IndexOf(MD5String);
  211. if not AShowCustomFace then
  212. begin
  213. AFileName := ReplaceStr(FindRecvedFace(MD5String), '\', '/');
  214. FaceID := MD5String + IntToStr(GetTickCount) + IntToStr(WaitingFaces.Count) + IntToStr(iStart);
  215. reg.Replacement := Format(IMAGE_LOADING_TAG, [FaceID, MD5String, AFileName]);
  216. reg.Subject := ReplaceStr(reg.Subject, reg.Groups[0], reg.Replacement);
  217. end
  218. else if iIndex >= 0 then
  219. begin
  220. Face := MainForm.FaceList.Objects[iIndex] as TFace;
  221. reg.Replacement := Format(IMAGE_LOADED_TAG, [MD5String, Face.FileName]);
  222. reg.Subject := ReplaceStr(reg.Subject, reg.Groups[0], reg.Replacement);
  223. end
  224. else if FileExists(FindRecvedFace(MD5String)) then
  225. begin
  226. AFileName := ReplaceStr(FindRecvedFace(MD5String), '\', '/');
  227. reg.Replacement := Format(IMAGE_LOADED_TAG, [MD5String, AFileName]);
  228. reg.Subject := ReplaceStr(reg.Subject, reg.Groups[0], reg.Replacement);
  229. end
  230. else
  231. begin
  232. if ATalkingForm <> nil then
  233. with (ATalkingForm as TTalkingForm) do
  234. begin
  235. AFileName := ExtractFilePath(Application.ExeName) + 'Images\progress.gif';
  236. AFileName := ReplaceStr(AFileName, '\', '/');
  237. FaceID := MD5String + IntToStr(GetTickCount) + IntToStr(WaitingFaces.Count) + IntToStr(iStart);
  238. reg.Replacement := Format(IMAGE_LOADING_TAG, [FaceID, MD5String, AFileName]);
  239. reg.Subject := ReplaceStr(reg.Subject, reg.Groups[0], reg.Replacement);
  240. if WaitingFaces.IndexOf(MD5String) <> -1 then
  241. Continue;
  242. if Category = tcNormal then
  243. FRealICQClient.PleaseSendFaceToMe(Receiver, MD5String)
  244. else
  245. FRealICQClient.DownloadTeamFace(ASender, MD5String);
  246. if AShowCustomFace then
  247. begin
  248. WaitingFace := TWaitingFace.Create;
  249. WaitingFace.FFaceMD5Code := MD5String;
  250. WaitingFace.FWebBrowser := WebBrowser;
  251. WaitingFace.FFaceID := FaceID;
  252. WaitingFaces.AddObject(MD5String, WaitingFace);
  253. end;
  254. end
  255. else
  256. begin
  257. AFileName := ExtractFilePath(Application.ExeName) + 'Images\erre.gif';
  258. AFileName := ReplaceStr(AFileName, '\', '/');
  259. FaceID := MD5String + IntToStr(GetTickCount);
  260. reg.Replacement := Format(IMAGE_LOADING_TAG, [FaceID, MD5String, AFileName]);
  261. reg.Subject := ReplaceStr(reg.Subject, reg.Groups[0], reg.Replacement);
  262. end;
  263. end;
  264. end;
  265. end;
  266. begin
  267. reg := TPerlRegEx.Create;
  268. try
  269. reg.Subject := AMessageContent;
  270. reg.RegEx := '\[(\w+)\-src=\"(http://[\w\W]+?)\"\]';
  271. while reg.MatchAgain do
  272. begin
  273. if CompareText(reg.Groups[1], 'IMAGE') = 0 then
  274. begin
  275. reg.Replacement := GetImageReplacementStr(reg.Groups[2], ATalkingForm);
  276. reg.Subject := reg.Replace();
  277. end
  278. else if CompareText(reg.Groups[1], 'MAP') = 0 then
  279. begin
  280. reg.Replacement := GetMapReplacementStr(reg.Groups[2], ATalkingForm);
  281. reg.Subject := reg.Replace();
  282. end
  283. else if CompareText(reg.Groups[1], 'voice') = 0 then
  284. begin
  285. reg.Replacement := GetVoiceReplacementStr(reg.Groups[2]);
  286. reg.Subject := reg.Replace();
  287. end;
  288. end;
  289. AMessageContent := reg.Subject;
  290. finally
  291. reg.Free;
  292. end;
  293. reg := TPerlRegEx.Create;
  294. try
  295. reg.Subject := AMessageContent;
  296. reg.RegEx := '\[IMG:([\w\W]+?)\]';
  297. ReplacesTag;
  298. reg.RegEx := '\[image\-src=\"([\w\W]+?)\"\]';
  299. ReplacesTag;
  300. AMessageContent := reg.Subject;
  301. finally
  302. reg.Free;
  303. end;
  304. //取系统表情
  305. for iLoop := 0 to MainForm.SystemFaceCount - 1 do
  306. begin
  307. Face := MainForm.FaceList.Objects[iLoop] as TFace;
  308. ContextMenuStr := 'oncontextmenu="location.href=''StandardFaceMenu_' + Face.ShortCut + ''';return false;"';
  309. AMessageContent := AnsiReplaceStr(AMessageContent,
  310. Face.ShortCut,
  311. '<img ' + ContextMenuStr + ' src="' + Face.FileName + '" align="absBottom" hspace="1" >');
  312. end;
  313. Result := AMessageContent;
  314. end;
  315. function TTextMessageService.GetImageReplacementStr(AImgUrl: string; ATalkingForm: TForm): string;
  316. var
  317. AMD5String, ALocalPath, AFileName, AFaceID: string;
  318. AURL: TIdURI;
  319. ATask: TDownloadFaceTask;
  320. WaitingFace: TWaitingFace;
  321. begin
  322. AURL := TIdURI.Create();
  323. AURL.URI := AImgUrl;
  324. AMD5String := ChangeFileExt(ExtractFileName(AURL.Document),'');
  325. ALocalPath := TRealICQClient.GetReceivedFaceDir + AMD5String + ExtractFileExt(AURL.Params);
  326. if FileExists(ALocalPath) then
  327. begin
  328. AFileName := ReplaceStr(ALocalPath, '\', '/');
  329. Result := Format(IMAGE_LOADED_TAG, [AMD5String, AFileName]);
  330. end
  331. else
  332. begin
  333. if ATalkingForm <> nil then
  334. begin
  335. AFaceID := AMD5String + IntToStr(GetTickCount) + IntToStr(WaitingFaces.Count);
  336. AFileName := ExtractFilePath(Application.ExeName) + 'Images\progress.gif';
  337. Result := Format(IMAGE_LOADING_TAG, [AFaceID, AMD5String, AFileName]);
  338. WaitingFace := TWaitingFace.Create;
  339. WaitingFace.FFaceMD5Code := AMD5String;
  340. WaitingFace.FWebBrowser := (ATalkingForm as TTalkingForm).WebBrowser;
  341. WaitingFace.FFaceID := AFaceID;
  342. WaitingFaces.AddObject(AMD5String, WaitingFace);
  343. ATask := TDownloadFaceTask.Create(AURL.URI, ALocalPath, AThreadPool.AcquireYarn);
  344. AThreadPool.StartYarn(ATask.Yarn, ATask);
  345. end
  346. else
  347. begin
  348. AFaceID := AMD5String + IntToStr(GetTickCount);
  349. AFileName := ExtractFilePath(Application.ExeName) + 'Images\error.gif';
  350. Result := Format(IMAGE_LOADING_TAG, [AFaceID, AMD5String, AFileName]);
  351. end;
  352. end;
  353. AURL.Free;
  354. end;
  355. function TTextMessageService.GetMapReplacementStr(AImgUrl: string; ATalkingForm: TForm): string;
  356. var
  357. AMD5String, ALocalPath, AFileName, AFaceID: string;
  358. ATask: TDownloadFaceTask;
  359. WaitingFace: TWaitingFace;
  360. begin
  361. Result := Format(MAP_IFRAME_TAG, [AnsiReplaceText(AImgUrl, '&amp;', '&')]);
  362. // AMD5String := MD5En(AImgUrl);
  363. // ALocalPath := TRealICQClient.GetReceivedFaceDir + AMD5String + '.png';
  364. //
  365. // if FileExists(ALocalPath) then
  366. // begin
  367. // AFileName := ReplaceStr(ALocalPath, '\', '/');
  368. // Result := Format(MAP_IFRAME_TAG, [AMD5String, AFileName]);
  369. // end
  370. // else
  371. // begin
  372. // AFaceID := AMD5String + IntToStr(GetTickCount) + IntToStr(WaitingFaces.Count);
  373. // AFileName := ExtractFilePath(Application.ExeName) + 'Images\progress.gif';
  374. // Result := Format(IMAGE_LOADING_TAG, [AFaceID, AMD5String, AFileName]);
  375. //
  376. // WaitingFace := TWaitingFace.Create;
  377. // WaitingFace.FFaceMD5Code := AMD5String;
  378. // WaitingFace.FWebBrowser := (ATalkingForm as TTalkingForm).WebBrowser;
  379. // WaitingFace.FFaceID := AFaceID;
  380. // WaitingFaces.AddObject(AMD5String, WaitingFace);
  381. //
  382. // ATask := TDownloadFaceTask.Create(AImgUrl, ALocalPath, AThreadPool.AcquireYarn);
  383. // AThreadPool.StartYarn(ATask.Yarn, ATask);
  384. // end;
  385. end;
  386. end.