/// <summary> /// 取群成员信息。 /// <para> /// 多线程同步等待,采用阻塞线程的方式等待客户端返回群成员信息,响应时间较慢,建议使用缓存。 /// </para> /// <para> /// 缓存时长1天,超过1天的成员,在下次访问时会通过酷Q重新获取最新信息。 /// </para> /// </summary> /// <param name="groupNumber">群号码。</param> /// <param name="qqNumber">被操作的QQ号码。</param> /// <param name="cache">是否使用缓存(使用缓存后,当后第一次访问会通过客户端读取,之后每次都通过缓存获得)。</param> public static CQGroupMemberInfo GetGroupMemberInfo(long groupNumber, long qqNumber, bool cache = true) { lock (_syncRoot) { Dictionary <long, CQGroupMemberInfo> dicMemebers = new Dictionary <long, CQGroupMemberInfo>(); if (_dicCache.ContainsKey(groupNumber)) { dicMemebers = _dicCache[groupNumber]; } else { _dicCache.Add(groupNumber, dicMemebers); } CQGroupMemberInfo member = new CQGroupMemberInfo(); if (dicMemebers.ContainsKey(qqNumber)) { member = dicMemebers[qqNumber]; } else { dicMemebers.Add(qqNumber, member); } if (!cache || member.RefreshDate.Date.AddDays(1) < DateTime.Now) { CQLogger.GetInstance().AddLog(String.Format("[↓][成员] 群:{0} QQ:{1}", groupNumber, qqNumber)); string content = String.Empty; if (CQ.ProxyType == CQProxyType.UDP) { content = String.Format("GroupMemberRequest|{0}|{1}", groupNumber, qqNumber); member = CQUDPProxy.GetInstance().GetGroupMemberInfo(content); } if (CQ.ProxyType == CQProxyType.NativeClr) { content = CQAPI.GetGroupMemberInfo(CQAPI.GetAuthCode(), groupNumber, qqNumber, cache ? 1 : 0); member = CQMessageAnalysis.AnalyzeGroupMember(content); } if (cache) { dicMemebers[qqNumber] = member; } } return(member); } return(new CQGroupMemberInfo()); }
public static List <CQGroupMemberInfo> GetGroupMemberList(long groupNumber) { List <CQGroupMemberInfo> list = new List <CQGroupMemberInfo>(); if (ProxyType == CQProxyType.UDP) { try { CQLogger.GetInstance().AddLog(String.Format("[↓][帐号] 群:{0} 取群成员列表", groupNumber)); string content = String.Format("GetGroupMemberListRequest|{0}", groupNumber); string result = CQUDPProxy.GetInstance().GetStringMessage(content); string[] msQQIds = result.GetMidStrings("\"uin\":", "}"); string[] msQQNames = result.GetMidStrings("\"nick\":\"", "\",\"uin\":"); string[] msIsAdmins = result.GetMidStrings("\"ismanager\":", ","); string[] msIsCreators = result.GetMidStrings("\"iscreator\":", ","); if (msQQIds.Length == msQQNames.Length && msQQNames.Length == msIsAdmins.Length && msIsAdmins.Length == msIsCreators.Length) { for (int i = 0; i < msQQIds.Length; i++) { CQGroupMemberInfo info = new CQGroupMemberInfo(); info.GroupNumber = groupNumber; info.QQNumber = Convert.ToInt64(msQQIds[i]); info.QQName = msQQNames[i]; int isAdmin = Convert.ToInt32(msIsAdmins[i]); int isCreator = Convert.ToInt32(msIsCreators[i]); info.Authority = isCreator == 1 ? "群主" : isAdmin == 1 ? "管理" : "成员"; list.Add(info); } } } catch { } } return(list); }
/// <summary> /// 获取群成员列表,阻塞线程,等待客户端响应(有风险,待测试)。 /// </summary> internal CQGroupMemberInfo GetGroupMemberInfo(string message) { byte[] data = Encoding.Default.GetBytes(message); this.mySocket.SendTo(data, data.Length, SocketFlags.None, RemotePoint); myResetEvent.WaitOne(2000); try { CQGroupMemberInfo info = CQMessageAnalysis.AnalyzeGroupMember(this._strMessage); this._strMessage = String.Empty; return(info); } catch { return(new CQGroupMemberInfo()); } }
/// <summary> /// 解析群成员信息。 /// </summary> /// <param name="data"></param> /// <returns></returns> internal static CQGroupMemberInfo AnalyzeGroupMember(string data) { CQGroupMemberInfo info = new CQGroupMemberInfo(); if (CQ.ProxyType == CQProxyType.UDP) { try { string[] args = data.Split(new char[] { '|' }); info.GroupNumber = String.IsNullOrEmpty(args[1]) ? 0 : Convert.ToInt64(args[1]); info.QQNumber = String.IsNullOrEmpty(args[2]) ? 0 : Convert.ToInt64(args[2]); info.QQName = args[3]; info.GroupCard = args[4]; info.Gender = String.IsNullOrEmpty(args[5]) ? "保密" : args[5] == "0" ? "男" : " 女"; info.Age = String.IsNullOrEmpty(args[6]) ? 0 : Convert.ToInt32(args[6]); info.JoinTime = new DateTime(1970, 1, 1, 0, 0, 0).ToLocalTime().AddSeconds(String.IsNullOrEmpty(args[7]) ? 0 : Convert.ToInt32(args[7])); info.LastSpeakingTime = new DateTime(1970, 1, 1, 0, 0, 0).ToLocalTime().AddSeconds(String.IsNullOrEmpty(args[8]) ? 0 : Convert.ToInt32(args[8])); info.Authority = String.IsNullOrEmpty(args[9]) ? "成员" : args[9] == "3" ? "群主" : args[9] == "2" ? "管理员" : "成员"; info.GroupHonor = args[10]; info.Area = args[11]; info.LevelName = args[12]; info.HasBadRecord = String.IsNullOrEmpty(args[13]) ? false : args[13] == "真" ? true : false; info.CanModifyVestCard = String.IsNullOrEmpty(args[14]) ? false : args[14] == "真" ? true : false; info.HonorExpirationTimes = String.IsNullOrEmpty(args[15]) ? 0 : Convert.ToInt32(args[15]); info.RefreshDate = DateTime.Now; } catch { } } if (CQ.ProxyType == CQProxyType.NativeClr) { try { byte[] memberBytes = Convert.FromBase64String(data); byte[] groupNumberBytes = new byte[8]; Array.Copy(memberBytes, 0, groupNumberBytes, 0, 8); Array.Reverse(groupNumberBytes); info.GroupNumber = BitConverter.ToInt64(groupNumberBytes, 0); byte[] qqNumberBytes = new byte[8]; Array.Copy(memberBytes, 8, qqNumberBytes, 0, 8); Array.Reverse(qqNumberBytes); info.QQNumber = BitConverter.ToInt64(qqNumberBytes, 0); byte[] nameLengthBytes = new byte[2]; Array.Copy(memberBytes, 16, nameLengthBytes, 0, 2); Array.Reverse(nameLengthBytes); short nameLength = BitConverter.ToInt16(nameLengthBytes, 0); byte[] nameBytes = new byte[nameLength]; Array.Copy(memberBytes, 18, nameBytes, 0, nameLength); info.QQName = System.Text.Encoding.Default.GetString(nameBytes); byte[] cardLengthBytes = new byte[2]; Array.Copy(memberBytes, 18 + nameLength, cardLengthBytes, 0, 2); Array.Reverse(cardLengthBytes); short cardLength = BitConverter.ToInt16(cardLengthBytes, 0); byte[] cardBytes = new byte[cardLength]; Array.Copy(memberBytes, 20 + nameLength, cardBytes, 0, cardLength); info.GroupCard = System.Text.Encoding.Default.GetString(cardBytes); byte[] genderBytes = new byte[4]; Array.Copy(memberBytes, 20 + nameLength + cardLength, genderBytes, 0, 4); Array.Reverse(genderBytes); info.Gender = BitConverter.ToInt32(genderBytes, 0) == 0 ? "男" : " 女"; byte[] ageBytes = new byte[4]; Array.Copy(memberBytes, 24 + nameLength + cardLength, ageBytes, 0, 4); Array.Reverse(ageBytes); info.Age = BitConverter.ToInt32(ageBytes, 0); byte[] areaLengthBytes = new byte[2]; Array.Copy(memberBytes, 28 + nameLength + cardLength, areaLengthBytes, 0, 2); Array.Reverse(areaLengthBytes); short areaLength = BitConverter.ToInt16(areaLengthBytes, 0); byte[] areaBytes = new byte[areaLength]; Array.Copy(memberBytes, 30 + nameLength + cardLength, areaBytes, 0, areaLength); info.Area = System.Text.Encoding.Default.GetString(areaBytes); byte[] addGroupTimesBytes = new byte[4]; Array.Copy(memberBytes, 30 + nameLength + cardLength + areaLength, addGroupTimesBytes, 0, 4); Array.Reverse(addGroupTimesBytes); info.JoinTime = new DateTime(1970, 1, 1, 0, 0, 0).ToLocalTime().AddSeconds(BitConverter.ToInt32(addGroupTimesBytes, 0)); byte[] lastSpeakTimesBytes = new byte[4]; Array.Copy(memberBytes, 34 + nameLength + cardLength + areaLength, lastSpeakTimesBytes, 0, 4); Array.Reverse(lastSpeakTimesBytes); info.LastSpeakingTime = new DateTime(1970, 1, 1, 0, 0, 0).ToLocalTime().AddSeconds(BitConverter.ToInt32(lastSpeakTimesBytes, 0)); byte[] levelNameLengthBytes = new byte[2]; Array.Copy(memberBytes, 38 + nameLength + cardLength + areaLength, levelNameLengthBytes, 0, 2); Array.Reverse(levelNameLengthBytes); short levelNameLength = BitConverter.ToInt16(levelNameLengthBytes, 0); byte[] levelNameBytes = new byte[levelNameLength]; Array.Copy(memberBytes, 40 + nameLength + cardLength + areaLength, levelNameBytes, 0, levelNameLength); info.LevelName = System.Text.Encoding.Default.GetString(levelNameBytes); byte[] authorBytes = new byte[4]; Array.Copy(memberBytes, 40 + nameLength + cardLength + areaLength + levelNameLength, authorBytes, 0, 4); Array.Reverse(authorBytes); int authority = BitConverter.ToInt32(authorBytes, 0); info.Authority = authority == 3 ? "群主" : (authority == 2 ? "管理员" : "成员"); byte[] badBytes = new byte[4]; Array.Copy(memberBytes, 44 + nameLength + cardLength + areaLength + levelNameLength, badBytes, 0, 4); Array.Reverse(badBytes); info.HasBadRecord = BitConverter.ToInt32(badBytes, 0) == 1; byte[] titleLengthBytes = new byte[2]; Array.Copy(memberBytes, 48 + nameLength + cardLength + areaLength + levelNameLength, titleLengthBytes, 0, 2); Array.Reverse(titleLengthBytes); short titleLength = BitConverter.ToInt16(titleLengthBytes, 0); byte[] titleBytes = new byte[titleLength]; Array.Copy(memberBytes, 50 + nameLength + cardLength + areaLength + levelNameLength, titleBytes, 0, titleLength); info.GroupHonor = System.Text.Encoding.Default.GetString(titleBytes); byte[] titleExpireBytes = new byte[4]; Array.Copy(memberBytes, 50 + nameLength + cardLength + areaLength + levelNameLength + titleLength, titleExpireBytes, 0, 4); Array.Reverse(titleExpireBytes); info.HonorExpirationTimes = BitConverter.ToInt32(titleExpireBytes, 0); byte[] modifyCardBytes = new byte[4]; Array.Copy(memberBytes, 54 + nameLength + cardLength + areaLength + levelNameLength + titleLength, titleExpireBytes, 0, 4); Array.Reverse(titleExpireBytes); info.CanModifyVestCard = BitConverter.ToInt32(titleExpireBytes, 0) == 1; } catch { } } return(info); }