IMService.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using System.IO.Compression;
  5. using System.Net;
  6. using System.Text;
  7. using System.Threading.Tasks;
  8. using GxPress.Common.Address;
  9. using GxPress.Common.Http;
  10. using GxPress.Common.Tools;
  11. using GxPress.Repository.Interface;
  12. using GxPress.Request.App.ChatRecord;
  13. using GxPress.Service.Interface.IM;
  14. using Microsoft.AspNetCore.Hosting;
  15. using Microsoft.Extensions.Caching.Distributed;
  16. using Newtonsoft.Json;
  17. using GxPress.Common.Extensions;
  18. using GxPress.Service.Interface.GroupChat;
  19. namespace GxPress.Service.Implement.IM
  20. {
  21. public partial class IMService : IIMService
  22. {
  23. private readonly IWebHostEnvironment _environment;
  24. private readonly IDistributedCache _cache;
  25. private readonly IChatRecordRepository _chatRecordRepository;
  26. private readonly IUserRepository _userRepository;
  27. private readonly IGroupChatRepository _groupChatRepository;
  28. private readonly IGroupChatService groupChatService;
  29. private readonly IGroupChatUserRepository _groupChatUserRepository;
  30. private readonly IFileLibraryRepository _fileLibraryRepository;
  31. private readonly IBlacklistUserRepository _blacklistUserRepository;
  32. private readonly IOftenContactRepository _oftenContactRepository;
  33. public IMService(IWebHostEnvironment environment, IDistributedCache cache, IChatRecordRepository chatRecordRepository,
  34. IUserRepository userRepository, IFileLibraryRepository fileLibraryRepository,
  35. IGroupChatRepository groupChatRepository, IGroupChatUserRepository groupChatUserRepository,
  36. IBlacklistUserRepository blacklistUserRepository, IOftenContactRepository oftenContactRepository,IGroupChatService groupChatService)
  37. {
  38. _environment = environment;
  39. _cache = cache;
  40. _chatRecordRepository = chatRecordRepository;
  41. _userRepository = userRepository;
  42. _fileLibraryRepository = fileLibraryRepository;
  43. _groupChatRepository = groupChatRepository;
  44. _groupChatUserRepository = groupChatUserRepository;
  45. _blacklistUserRepository = blacklistUserRepository;
  46. _oftenContactRepository = oftenContactRepository;
  47. this.groupChatService=groupChatService;
  48. }
  49. /// <summary>
  50. /// 获取环信历史记录
  51. /// </summary>
  52. /// <returns></returns>
  53. public async Task<bool> GatherChatDataAsync()
  54. {
  55. var token = await _cache.GetAsync<string>("ImToken");
  56. // var times = DateTime.Now.AddHours(-2).ToString("YYYYMMDDHH");
  57. var times = "2019112711";
  58. var headers = new Dictionary<string, string> { { "Authorization", "Bearer " + token } };
  59. var requestUrl = Address.GetImChatMassageUrl(times);
  60. var response = await HttpClientHelper.GetHeadersAsync(requestUrl, headers);
  61. //请求成功
  62. if (!response.IsSuccessStatusCode)
  63. {
  64. //token过期重新拉去
  65. if (response.StatusCode == HttpStatusCode.Unauthorized)
  66. {
  67. var result = await GetTokenImAsync();
  68. if (result)
  69. {
  70. headers = new Dictionary<string, string>
  71. {{"Authorization", "Bearer " + await _cache.GetAsync<string>("ImToken")}};
  72. requestUrl = Address.GetImChatMassageUrl(times);
  73. response = await HttpClientHelper.GetHeadersAsync(requestUrl, headers);
  74. }
  75. }
  76. else
  77. return false;
  78. }
  79. //获取返回的内容
  80. var content = await response.Content.ReadAsStringAsync();
  81. var dataJson = JsonConvert.DeserializeObject<dynamic>(content);
  82. var url = dataJson["data"][0]["url"];
  83. //下载GZ解压包
  84. var gzUrl = await DecompressionGzip(url.ToString());
  85. //获取文本内容
  86. StreamReader sr = new StreamReader(gzUrl, Encoding.Default);
  87. string jsonText;
  88. while ((jsonText = sr.ReadLine()) != null)
  89. {
  90. await InsertChatHistory(jsonText);
  91. }
  92. return true;
  93. }
  94. /// <summary>
  95. /// 强制下线
  96. /// </summary>
  97. /// <param name="phone"></param>
  98. /// <returns></returns>
  99. public async Task<bool> DisconnectAsync(string phone)
  100. {
  101. var imServiceUrl = ConfigHelper.GetValue("ServiceAddress:ImUrl");
  102. var token = await _cache.GetAsync<string>("ImToken");
  103. var url = $"{imServiceUrl}/{phone}/disconnect";
  104. var headers = new Dictionary<string, string> { { "Authorization", "Bearer " + token } };
  105. var response = await HttpClientHelper.GetHeadersAsync(url, headers);
  106. if (response.IsSuccessStatusCode)
  107. return true;
  108. return false;
  109. }
  110. /// <summary>
  111. /// 解压GzZIP
  112. /// </summary>
  113. /// <returns></returns>
  114. public async Task<string> DecompressionGzip(string url)
  115. {
  116. var response = await HttpClientHelper.GetByteArrayAsync(url);
  117. string filePath;
  118. //获取路径
  119. var path = FileHelper.SaveFile(StringUtils.GetWebRootPath(_environment.WebRootPath), ".gz", response);
  120. //解压
  121. using (FileStream fr = File.OpenRead(path.AbsolutePath))
  122. {
  123. using (GZipStream gz = new GZipStream(fr, CompressionMode.Decompress))
  124. {
  125. filePath = FileHelper.GetSavePath(StringUtils.GetWebRootPath(_environment.WebRootPath), ".txt")
  126. .AbsolutePath;
  127. using (FileStream fw = File.OpenWrite(filePath))
  128. {
  129. byte[] by = new byte[1024 * 1024];
  130. int r = gz.Read(by, 0, by.Length);
  131. while (r > 0)
  132. {
  133. fw.Write(by, 0, r);
  134. r = gz.Read(by, 0, r);
  135. }
  136. }
  137. }
  138. }
  139. return filePath;
  140. }
  141. /// <summary>
  142. /// 分析并插入
  143. /// </summary>
  144. /// <param name="json"></param>
  145. /// <returns></returns>
  146. public async Task<bool> InsertChatHistory(string json)
  147. {
  148. var dataJson = JsonConvert.DeserializeObject<dynamic>(json);
  149. //获取 单聊 或者 群聊
  150. var chatType = dataJson.chat_type;
  151. //获取发起人的imId
  152. var imId = dataJson.from.ToString();
  153. var toImId = dataJson.to.ToString();
  154. //获取用户
  155. var user = await _userRepository.GetByPhoneAsync(imId);
  156. var request = new ChatRecordInRequest
  157. {
  158. ChatType = chatType.ToString().Equals("chat") ? 1 : 2,
  159. SendUserId = user.Id
  160. };
  161. if (request.ChatType == 1)
  162. {
  163. var toUser = await _userRepository.GetByPhoneAsync(imId);
  164. request.ReceiveUserId = toUser.Id.ToString();
  165. }
  166. else
  167. {
  168. var toGroupChat = _groupChatRepository.GetGroupChatByImIdAsync(int.Parse(toImId));
  169. request.ReceiveUserId = toGroupChat.GroupChatImId;
  170. }
  171. foreach (var bodies in dataJson.payload.bodies)
  172. {
  173. var typeName = bodies.type.ToString();
  174. if (typeName.Equals("txt"))
  175. request.MsgType = 1;
  176. if (typeName.Equals("loc"))
  177. request.MsgType = 6;
  178. if (typeName.Equals("audio"))
  179. request.MsgType = 5;
  180. if (typeName.Equals("video"))
  181. request.MsgType = 4;
  182. if (typeName.Equals("file"))
  183. request.MsgType = 3;
  184. if (typeName.Equals("loc"))
  185. request.MsgType = 6;
  186. if (typeName.Equals("img"))
  187. request.MsgType = 2;
  188. //判断是否是文本
  189. if (request.MsgType == 1)
  190. {
  191. string msg = bodies.msg.ToString();
  192. request.Content = msg;
  193. }
  194. else if (request.MsgType == 6)
  195. {
  196. string msg = bodies.lat.ToString() + "," + bodies.lng.ToString();
  197. request.Content = msg;
  198. }
  199. else
  200. {
  201. //获取用户数据
  202. var url = bodies.url.ToString();
  203. var fileName = bodies.filename.ToString();
  204. var fileType = bodies.type.ToString().Equals("img")
  205. ? "image"
  206. : (string)Path.GetExtension(fileName);
  207. //下载
  208. var response = await HttpClientHelper.GetByteArrayAsync(url);
  209. //获取路径
  210. var path = FileHelper.SaveFile(StringUtils.GetWebRootPath(_environment.WebRootPath), fileName,
  211. response);
  212. var fileLibrary = new Entity.FileLibrary
  213. { FileName = fileName, FileType = fileType, FileUrl = path.RelativePath };
  214. //file
  215. var fileLibraryId = await _fileLibraryRepository.InsertAsync(fileLibrary);
  216. request.Content = fileLibraryId.ToString();
  217. }
  218. //保存
  219. await _chatRecordRepository.InsertAsync(request);
  220. }
  221. return true;
  222. }
  223. /// <summary>
  224. /// 获取token
  225. /// </summary>
  226. /// <returns></returns>
  227. public async Task<bool> GetTokenImAsync()
  228. {
  229. var imServiceUrl = ConfigHelper.GetValue("ServiceAddress:ImUrl");
  230. var grantType = ConfigHelper.GetValue("ServiceAddress:GrantType");
  231. var clientId = ConfigHelper.GetValue("ServiceAddress:ClientId");
  232. var clientSecret = ConfigHelper.GetValue("ServiceAddress:ClientSecret");
  233. var requestUrl = $"{imServiceUrl}/token";
  234. var jsonObj = new
  235. {
  236. grant_type = grantType,
  237. client_id = clientId,
  238. client_secret = clientSecret
  239. };
  240. var response = await HttpClientHelper.PostAsync(requestUrl, jsonObj);
  241. if (!response.IsSuccessStatusCode)
  242. {
  243. return false;
  244. }
  245. var key = "ImToken";
  246. var tokenJson = await response.Content.ReadAsStringAsync();
  247. var dataJsonDynamic = JsonConvert.DeserializeObject<dynamic>(tokenJson);
  248. string value = dataJsonDynamic.access_token.ToString();
  249. await _cache.SetAsync<string>(key, value, new DistributedCacheEntryOptions
  250. {
  251. AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(Convert.ToInt32(dataJsonDynamic.expires_in))
  252. });
  253. return true;
  254. }
  255. }
  256. }