private void LoadPunishments() { if (!File.Exists(PunishmentFile)) { return; } lock (m_fileSyncObj) { using (var br = new BinaryReader(new FileStream(PunishmentFile, FileMode.Open))) { int cnt = br.ReadInt32(); for (int i = 0; i < cnt; ++i) { ulong id = br.ReadUInt64(); DateTime endTime = DateTime.FromBinary(br.ReadInt64()); m_endTimes.AddOrUpdate(id, endTime, (key, val) => endTime); int punishCount = br.ReadInt32(); var spamUser = new SpamUser { PunishCount = punishCount }; m_spamUsers.AddOrUpdate(id, spamUser, (key, val) => spamUser); } br.Close(); } } }
public SpamUser ResetSpamGage() { SpamUser temp = this; temp.SpamGage = 0; return(temp); }
private int UpdateSpamGage(ulong userId, ulong channelId, DateTimeOffset timestamp) { // 조용, 인증 채널에선 도배 판정하지 않음. if (channelId == DiscordConstants.QuietChannelId || channelId == DiscordConstants.AuthChannelId) { return(0); } var newMsg = new SpamMessage { Author = userId, CreationTime = timestamp, }; if (m_lastChannelMsg.TryGetValue(channelId, out SpamMessage prevMsg)) { // 가장 최근의 메세지로 갱신. m_lastChannelMsg.AddOrUpdate(channelId, newMsg, (key, val) => { return((newMsg.CreationTime > val.CreationTime) ? newMsg : val); }); if (userId == prevMsg.Author) { var delay = timestamp - prevMsg.CreationTime; if (delay >= m_maxSpamDelay) { // 스팸 게이지 초기화. m_spamUsers.AddOrUpdate(userId, SpamUser.Empty, (key, usr) => usr.ResetSpamGage()); } else { if (timestamp == prevMsg.CreationTime) { // 시간 해상도가 1초이므로 시간이 같다는 것은 시간차가 최대 1초라는 것. // 따라서 충분히 작은 시간으로 딜레이를 가정한다. delay = TimeSpan.FromSeconds(0.01); } // 기존 유저 정보 얻음. SpamUser spamUser; if (!m_spamUsers.TryGetValue(userId, out spamUser)) { spamUser = new SpamUser(); } // 스팸 수치 계산. int spamGage = (int)Math.Round((1.0 - (delay / m_maxSpamDelay)) * m_spamGageScale); spamUser.SpamGage += spamGage; int punishTime = spamUser.SpamGage / m_spamGageScale; // 처벌 시간이 트리거에 도달하면 처벌이 이뤄지고 가중되도록 카운트를 증가시킴. if (punishTime >= m_triggerPunishTime) { spamUser.PunishCount += 1; } // 변경된 유저 정보 갱신. m_spamUsers.AddOrUpdate(userId, spamUser, (key, old) => { return((spamUser.PunishCount >= old.PunishCount) ? spamUser : old); }); if (punishTime >= m_triggerPunishTime) { // 가중 처벌이 계산된 처벌 시간 반환. return(punishTime * spamUser.PunishCount * spamUser.PunishCount); } } } else { // 대화 중인 것으로 판정하여 도배로 보지 않음. m_spamUsers.AddOrUpdate(userId, SpamUser.Empty, (key, usr) => usr.ResetSpamGage()); m_spamUsers.AddOrUpdate(prevMsg.Author, SpamUser.Empty, (key, usr) => usr.ResetSpamGage()); } } else { // 가장 최근의 메세지로 초기화. m_lastChannelMsg.AddOrUpdate(channelId, newMsg, (key, val) => { return((newMsg.CreationTime > val.CreationTime) ? newMsg : val); }); } return(0); }