RepositoryExtension.User.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. using Elasticsearch.Net;
  2. using JiaZhiQuan.Common.ElasticSearch;
  3. using Newtonsoft.Json;
  4. using Newtonsoft.Json.Linq;
  5. using Senparc.Weixin.MP.Containers;
  6. using System;
  7. using System.Collections.Generic;
  8. using System.Data;
  9. using System.Diagnostics;
  10. using System.Dynamic;
  11. using System.Linq;
  12. using System.Net.Http;
  13. using System.Reflection;
  14. using System.Security.Cryptography;
  15. using System.Text;
  16. using System.Threading.Tasks;
  17. using Wicture.DbRESTFul;
  18. using Wicture.DbRESTFul.Cache;
  19. using Wicture.DbRESTFul.Infrastructure.Repository;
  20. namespace JiaZhiQuan.Common
  21. {
  22. public static partial class RepositoryExtension
  23. {
  24. /// <summary>
  25. /// 保存用户信息到ES。创建新的或者更新部分字段
  26. /// <param name="userInfo">必须包含id字段</param>
  27. /// <param name="ignorePost">是否忽略更新文章索引中用户昵称(暂时仅用于用户注销时,指定为true)</param>
  28. /// </summary>
  29. public static async Task UserInfoSave2ES(this DbRESTFulRepository repository, object userInfo, bool ignorePost = false)
  30. {
  31. var id = userInfo.GetType().GetProperty("id").GetValue(userInfo);
  32. var idStr = id.ToString();
  33. bool exist = await ESHelper.CheckExist("user", idStr);
  34. if (exist)
  35. {
  36. var rsp = await ESHelper.Client.UpdateAsync<StringResponse>("user", idStr, PostData.Serializable(new { doc = userInfo }));
  37. if (!rsp.Success)
  38. {
  39. LoggerManager.Logger.Error("更新用户信息到ES失败:" + rsp.Body);
  40. return;
  41. }
  42. // 如果存在,还需要更新 Post 中的用户昵称
  43. if (IsPropertyExist(userInfo, "alias"))
  44. {
  45. string alias = userInfo.GetType().GetProperty("alias").GetValue(userInfo) as string;
  46. alias = alias.Replace("'", "");
  47. var query = new
  48. {
  49. script = new { source = $"ctx._source['userAlias']='{alias}'" },
  50. query = new
  51. {
  52. term = new { userId = id }
  53. }
  54. };
  55. rsp = await ESHelper.Client.UpdateByQueryAsync<StringResponse>(ESConstants.ESIndexName.Post, PostData.Serializable(query));
  56. if (!rsp.Success)
  57. {
  58. LoggerManager.Logger.Error("更新ES中POST用户信息失败:" + rsp.Body);
  59. }
  60. }
  61. }
  62. else
  63. {
  64. var rsp = await ESHelper.Client.CreateAsync<StringResponse>("user", idStr, PostData.Serializable(userInfo));
  65. if (!rsp.Success)
  66. {
  67. LoggerManager.Logger.Error("创建用户信息到ES失败:" + rsp.Body);
  68. return;
  69. }
  70. }
  71. }
  72. /// <summary>
  73. /// 通过用户Id加载用户信息
  74. /// id(string), alias, authType, authName, vip, headImage, domainTalent, publicTags, official, curProvince,watermark
  75. /// </summary>
  76. /// <param name="userIds"></param>
  77. /// <param name="conn">可以为空</param>
  78. /// <returns></returns>
  79. public static async Task<Dictionary<long, T>> UsersInfoByIds<T>(this DbRESTFulRepository repository, IEnumerable<long> userIds, IDbConnection conn = null) where T : UserInfoBase
  80. {
  81. userIds = userIds.Distinct();
  82. var list = await repository.QueryAsync<T>("select id, alias, authType, authName, vip, headImage, domainTalent, description, publicTags, official, curProvince,watermark from n_user where id in @userIds", new { userIds }, conn);
  83. var dic = new Dictionary<long, T>(userIds.Count());
  84. foreach (var id in userIds)
  85. {
  86. dic[id] = list.FirstOrDefault(e => id.ToString() == e.id);
  87. }
  88. return dic;
  89. }
  90. /// <summary>
  91. /// 通过用户Id加载用户信息
  92. /// id(string), username, alias, authType, authName, vip, headImage, domainTalent, mpRole, publicTags, official, curProvince,watermark
  93. /// </summary>
  94. /// <param name="userIds"></param>
  95. /// <param name="conn">可以为空</param>
  96. /// <returns></returns>
  97. public static async Task<Dictionary<long, T>> UsersInfoFullByIds<T>(this DbRESTFulRepository repository, IEnumerable<long> userIds, IDbConnection conn = null) where T : UserInfoFull
  98. {
  99. userIds = userIds.Distinct();
  100. var list = await repository.QueryAsync<T>("select id, username, alias, authType, authName, vip, headImage, domainTalent, description, mpRole, superior, publicTags, official, curProvince,watermark from n_user where id in @userIds", new { userIds }, conn);
  101. var dic = new Dictionary<long, T>(userIds.Count());
  102. foreach (var id in userIds)
  103. {
  104. dic[id] = list.FirstOrDefault(e => id.ToString() == e.id);
  105. }
  106. return dic;
  107. }
  108. /// <summary>
  109. /// 通过用户Id加载用户信息,附带是否关注
  110. /// id(string), alias, authType, authName, vip, headImage, domainTalent, publicTags, official, curProvince, focused,watermark
  111. /// </summary>
  112. /// <param name="userId">当前用户</param>
  113. /// <param name="conn">可以为空</param>
  114. /// <param name="ignoreFocusState">忽略当前用户关注用户列表的状态</param>
  115. /// <param name="ignoreFanState">忽略用户列表是否关注当前用户的状态</param>
  116. /// <returns></returns>
  117. public static async Task<Dictionary<long, T>> UsersInfoWithFocusStateByIds<T>(this DbRESTFulRepository repository, long userId, IEnumerable<long> userIds, IDbConnection conn = null, bool ignoreFocusState = false, bool ignoreFanState = false) where T : UserInfoBaseWithFocusState
  118. {
  119. userIds = userIds.Distinct();
  120. var dic = new Dictionary<long, T>(userIds.Count());
  121. if (userIds.Count() == 0)
  122. {
  123. return dic;
  124. }
  125. if (userId < 1)
  126. {
  127. ignoreFanState = true;
  128. ignoreFocusState = true;
  129. }
  130. var list = await repository.QueryAsync<T>("select id, alias, authType, authName, vip, headImage, domainTalent, description, publicTags, official, curProvince,watermark,growLevel level from n_user where id in @userIds", new { userIds }, conn);
  131. HashSet<long> focusState = null;
  132. if (!ignoreFocusState)
  133. {
  134. focusState = await CheckFocusState(repository, userId, userIds, conn);
  135. }
  136. HashSet<long> fanState = null;
  137. if (!ignoreFanState)
  138. {
  139. fanState = await CheckFanState(repository, userId, userIds, conn);
  140. }
  141. foreach (var id in userIds)
  142. {
  143. var user = list.FirstOrDefault(e => id.ToString() == e.id);
  144. if (user != null)
  145. {
  146. if (focusState != null) user.focused = focusState.Contains(id) ? 1 : 0;
  147. if (fanState != null) user.isFan = fanState.Contains(id) ? 1 : 0;
  148. }
  149. dic[id] = user;
  150. }
  151. return dic;
  152. }
  153. /// <summary>
  154. /// 返回 userIds 参数中 userId 所关注的用户Id列表
  155. /// </summary>
  156. public static async Task<HashSet<long>> CheckFocusState(this DbRESTFulRepository repository, long userId, IEnumerable<long> userIds, IDbConnection conn = null)
  157. {
  158. var list = await repository.QueryAsync<long>("select userId from n_user_fan where fanId=@userId and userId in @userIds", new { userId, userIds }, conn);
  159. var count = list.Count();
  160. if (count > 0)
  161. {
  162. return list.ToHashSet();
  163. }
  164. return new HashSet<long>(0);
  165. }
  166. /// <summary>
  167. /// 返回 userIds 参数中 userId 所被关注的用户Id列表
  168. /// </summary>
  169. public static async Task<HashSet<long>> CheckFanState(this DbRESTFulRepository repository, long userId, IEnumerable<long> userIds, IDbConnection conn = null)
  170. {
  171. var list = await repository.QueryAsync<long>("select fanId from n_user_fan where userId=@userId and fanId in @userIds", new { userId, userIds }, conn);
  172. var count = list.Count();
  173. if (count > 0)
  174. {
  175. return list.ToHashSet();
  176. }
  177. return new HashSet<long>(0);
  178. }
  179. /// <summary>
  180. /// 通过用户编号查询用户的隐私设置
  181. /// </summary>
  182. public static async Task<UserPrivacySetting> GetPrivacySettingByUserId(this DbRESTFulRepository repository, long userId, RedisCacheProvider cacheProvider, IDbConnection conn = null)
  183. {
  184. var cacheKey = CacheKeys.UserPrivacySetting(userId);
  185. var cacheVal = await cacheProvider.Get<int?>(cacheKey);
  186. if (cacheVal != null)
  187. {
  188. return UserPrivacySetting.InstanceByIntValue(cacheVal.Value);
  189. }
  190. else
  191. {
  192. UserPrivacySetting setting = await repository.QuerySingleOrDefaultAsync<UserPrivacySetting>($"select likePostRecordsHidden, collectPostRecordsHidden, focusRecordsHidden, fansHidden, personalRecommend from n_user_settings where userId={userId}", null, conn);
  193. bool watermark = await repository.QuerySingleOrDefaultAsync<bool>($"SELECT watermark FROM n_user WHERE id={userId}", null, conn);
  194. if (setting == null) setting = new UserPrivacySetting();
  195. setting.watermark = watermark;
  196. await cacheProvider.Set(cacheKey, setting.GetIntValue(), CacheKeys.UserPrivacySettingCacheSecs);
  197. return setting;
  198. }
  199. }
  200. public static async Task<int> GetUserState(this DbRESTFulRepository repository, long userId, RedisCacheProvider cacheProvider, IDbConnection conn = null)
  201. {
  202. var cacheKey = CacheKeys.UserStateValue(userId);
  203. var cacheVal = await cacheProvider.Get<int?>(cacheKey);
  204. if (cacheVal != null)
  205. {
  206. return cacheVal.Value;
  207. }
  208. else
  209. {
  210. var info = await repository.QuerySingleOrDefaultAsync<dynamic>($"select state from n_user where id={userId}", null, conn);
  211. var state = info?.state ?? -1;
  212. await cacheProvider.Set(cacheKey, state, CacheKeys.UserStateValueCacheSecs);
  213. return state;
  214. }
  215. }
  216. }
  217. }