Light12306/ChatRoomServer.Main/ChatSession.cs
2015-10-21 12:40:04 +08:00

399 lines
13 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ChatRoomServer.Main
{
using ChatRoomServer.Db;
using ChatRoomServer.Db.Entities;
using ChatRoomServer.Main.Entities;
using ChatRoomServer.Main.Room;
using FSLib.Logs.Log4Net;
using FSLib.Network.SuperSocket.Protocols.WebSocket;
using FSLib.Network.SuperSocket.SocketBase;
class ChatSession : WebSocketSession<ChatSession>
{
static ILog _log = ChatServer.GetLogger(typeof(ChatSession).Name);
DateTime _connecTime = DateTime.Now;
long _connectId;
bool _isAdmin;
/// <summary>
/// 路径分割
/// </summary>
public string[] PathSegements { get; private set; }
/// <summary>
/// 命令
/// </summary>
public string Command { get; private set; }
public string UserName { get; private set; }
public string NickName { get; private set; }
/// <summary>
/// 获得或设置房间
/// </summary>
public RoomContainer RoomContainer { get; set; }
/// <summary>
/// ID
/// </summary>
public string Id { get; private set; }
bool IsBlocked()
{
DateTime? dt = null;
if ((AppServer as ChatServer).BlockUsers?.TryGetValue(UserName, out dt) == true)
{
IsSessionBlocked = true;
Block(dt);
return true;
}
return false;
}
/// <summary>
/// Called when [session started].
/// </summary>
protected override void OnSessionStarted()
{
base.OnSessionStarted();
var path = Path.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
if (path.Length >= 4)
{
Command = path[0];
Id = System.Net.WebUtility.UrlDecode(path[1]);
UserName = System.Net.WebUtility.UrlDecode(path[2]);
NickName = System.Net.WebUtility.UrlDecode(path[3]);
}
PathSegements = path;
_isAdmin = ChatServer.PresetAdministrators.Contains(UserName);
if (IsBlocked())
return;
//更新统计
var db = new ChatDb();
BlockUser blockRule = null;
var user = db.Users.FirstOrDefault(s => s.UserName == UserName);
if (user == null)
{
user = new User()
{
UserName = UserName,
NickName = NickName,
FirstConnect = DateTime.Now,
Status = UserStatus.Normal
};
db.Users.Add(user);
}
user.LastConnect = DateTime.Now;
var ucl = new UserConnectLog()
{
UserName = UserName,
ConnectTime = DateTime.Now,
RoomID = Id,
Ip = RemoteEndPoint.ToString()
};
db.UserConnectLogs.Add(ucl);
db.SaveChanges();
_connectId = ucl.Id;
}
public bool IsSessionBlocked { get; private set; }
public void Block(DateTime? unblockTime)
{
TrySend(new MessageItem(SystemMessageType.OperationBlocked, content: "很抱歉,您的账户已经被封锁,暂时无法在聊天室暂住。封锁解除时间:" + (unblockTime == null ? "无限期" : unblockTime.Value.ToString())));
Close(CloseReason.TimeOut);
}
/// <summary>
/// Called when [session closed].
/// </summary>
/// <param name="reason">The reason.</param>
protected override void OnSessionClosed(CloseReason reason)
{
base.OnSessionClosed(reason);
//更新统计
if (_connectId > 0)
{
var elapsed = (int)(DateTime.Now - _connecTime).TotalSeconds;
var db = new ChatDb();
db.Database.ExecuteSqlCommand("UPDATE Chat_UserConnectLog SET DisconnectTime=GETDATE(), ElapsedTime={1} WHERE Id={0}", _connectId, elapsed);
db.Database.ExecuteSqlCommand("UPDATE Chat_User SET OnlineTime=OnlineTime+{1} WHERE UserName={0}", UserName, elapsed);
}
}
public bool TrySend(MessageItem message)
{
var buffer = message.ToBuffer();
var value = TrySend(buffer, 0, buffer.Length);
if (!value)
{
_log.Warn($"数据发送失败连接ID={SessionID}");
}
return value;
}
public void ProcessData(byte[] data)
{
if (IsBlocked())
return;
MessageItem item;
try
{
item = MessageItem.Decode(data);
}
catch (Exception)
{
return;
}
if (item.From == null || item.From.UserName.IsNullOrEmpty())
{
item.From = new MessageUser(UserName, NickName);
}
if (item.SystemMessage)
{
ProcessSystemMessage(item);
}
else
{
ProcessUserMessage(item);
}
}
void ProcessSystemMessage(MessageItem item)
{
switch (item.SysMsgType)
{
case SystemMessageType.UserEnter:
break;
case SystemMessageType.UserExit:
break;
case SystemMessageType.Disconnect:
break;
case SystemMessageType.UpdateStat:
break;
case SystemMessageType.SendFailed:
break;
case SystemMessageType.UpdateOnlineCount:
break;
default:
break;
}
}
void ProcessUserMessage(MessageItem item)
{
switch (item.UserMsgType)
{
case UserMessageType.Send:
//check username
if (item.ToUsers != null && item.ToUsers.Length > 0)
{
var notOnlineUsers = item.ToUsers.Where(x => !RoomContainer.IsUserInRoom(x.UserName)).ToArray();
if (!notOnlineUsers.IsEmpty())
{
item.Content += $"【系统提示:用户 {notOnlineUsers.Select(s => s.NickName).JoinAsString("")} 已不在线。】";
}
}
//log to db
var db = new ChatDb();
var msg = new MsgLog()
{
AtUser = item.ToUsers?.Select(s => s.UserName).JoinAsString(";"),
Color = item.Color,
Image = item.Images?.JoinAsString(";"),
Content = item.Content,
Ip = RemoteEndPoint.ToString(),
RoomId = PathSegements[1],
SendTime = item.Time,
UserName = UserName
};
db.MsgLogs.Add(msg);
db.SaveChanges();
item.Id = msg.Id;
//更新统计
db.Database.ExecuteSqlCommand("UPDATE Chat_User SET LastSend=GETDATE(), FirstSend=ISNULL(FirstSend, GETDATE()), SendTimes=SendTimes+1 WHERE UserName={0}", UserName);
OnRequireSendMessage(item, false);
break;
case UserMessageType.Receive:
break;
case UserMessageType.ReportAbuse:
ProcessReport(item.Content.ToInt64());
break;
default:
break;
}
}
async void ProcessReport(long msgid)
{
if (msgid <= 0)
return;
var db = new ChatDb();
//查找当前用户资料
var currentUser = db.Users.Find(UserName);
if (currentUser.DisableAbuseReport)
{
TrySend(new MessageItem(SystemMessageType.ReportAbuseResult, success: false, content: "很抱歉,管理员已暂时关闭了您的举报权限。"));
return;
}
if (currentUser.AbuseReportSuccRate < 0.1)
{
TrySend(new MessageItem(SystemMessageType.ReportAbuseResult, success: false, content: "很抱歉,您当前举报成功率过低(<0.2),系统暂时不接受您新的举报。已有举报未通过审核时,请等待管理员审核。"));
return;
}
//此消息是否已经被举报过了?
if (db.AbuseReports.Any(s => s.TargetId == msgid && s.ReportUser == UserName))
{
//重复举报
TrySend(new MessageItem(SystemMessageType.ReportAbuseResult, success: false, content: "这条消息您已经举报过哦,请不要重复举报消息。"));
return;
}
var msg = db.MsgLogs.Find(msgid);
if (msg == null)
return;
var dispName = db.Users.Find(msg.UserName)?.NickName ?? "";
//是否已经有屏蔽记录了?
currentUser.AbuseReportCount++;
var currentRule = db.GetBlockRuleForUser(msg.UserName).LastOrDefault();
if (currentRule != null)
{
if (currentRule.UnblockTime != null)
{
currentUser.AbuseReportSuccCount++;
db.AbuseReports.Add(new AbuseReport()
{
ReportTime = DateTime.Now,
ReportUser = UserName,
Status = ReportState.AutoProcessed,
TargetId = msgid,
TargetUser = msg.UserName
});
//如果是隔期解开的,那么将会延长十五分钟
var extra = _isAdmin ? 300 : 15;
currentRule.UnblockTime = currentRule.UnblockTime.Value.AddMinutes(_isAdmin ? 300 : 15);
TrySend(new MessageItem(SystemMessageType.ReportAbuseResult, success: true, content: $"您已举报成功。由于您的添砖加瓦,用户【{dispName}({msg.UserName})】将会在小黑屋中多享受 {extra} 分钟的幸福时光。(您已举报 {currentUser.AbuseReportCount}次,成功 {currentUser.AbuseReportSuccCount}次,成功率 {currentUser.AbuseReportSuccRate:P1})"));
OnRequireSendMessage(new MessageItem(SystemMessageType.ReportAbuseResult, success: true, content: $"{currentUser.NickName} 已经举报成功。由于TA的添砖加瓦用户【{dispName}({msg.UserName})】将会在小黑屋中多享受 {extra} 分钟的幸福时光。({currentUser.NickName} 已举报 {currentUser.AbuseReportCount}次,成功 {currentUser.AbuseReportSuccCount}次,成功率 {currentUser.AbuseReportSuccRate:P1})"), true);
db.SaveChanges();
}
else
{
TrySend(new MessageItem(SystemMessageType.ReportAbuseResult, success: true, content: $"无需举报,用户【{dispName}({msg.UserName})】已经暂时不会从小黑屋里粗来了"));
}
return;
}
//没有处于屏蔽状态,则
var rlog = new AbuseReport()
{
ReportTime = DateTime.Now,
ReportUser = UserName,
Status = _isAdmin ? ReportState.AutoProcessed : ReportState.Submited,
TargetId = msgid,
TargetUser = msg.UserName
};
db.AbuseReports.Add(rlog);
db.SaveChanges();
//自动处理
//如果是管理员,则自动禁言两个小时
var blocked = false;
var currentReportCount = 0;
DateTime? unblockTime = null;
if (_isAdmin)
{
currentUser.AbuseReportSuccCount++;
currentRule = new BlockUser()
{
BlockTime = DateTime.Now,
UserName = msg.UserName,
UnblockTime = DateTime.Now.AddMinutes(300)
};
db.BlockUsers.Add(currentRule);
unblockTime = currentRule.UnblockTime;
TrySend(new MessageItem(SystemMessageType.ReportAbuseResult, success: true, content: $"您已将用户【{dispName}({msg.UserName})】请到小黑屋里享受幸福至少五个小时。如果有更多人举报,呆的时间将会延长。(您已举报 {currentUser.AbuseReportCount}次,成功 {currentUser.AbuseReportSuccCount}次,成功率 {currentUser.AbuseReportSuccRate:P1})"));
OnRequireSendMessage(new MessageItem(SystemMessageType.ReportAbuseResult, success: true, content: $"用户【{dispName}({msg.UserName})】已经被管理员 {currentUser.NickName} 请到小黑屋里享受幸福至少五个小时。如果有更多人举报,呆的时间将会延长。({currentUser.NickName} 已举报 {currentUser.AbuseReportCount}次,成功 {currentUser.AbuseReportSuccCount}次,成功率 {currentUser.AbuseReportSuccRate:P1})"), true);
blocked = true;
}
else if ((currentReportCount = db.GetUserAbuseReportCountInTime(msg.UserName, 15)) > 5)
{
currentUser.AbuseReportSuccCount++;
currentRule = new BlockUser()
{
BlockTime = DateTime.Now,
UserName = msg.UserName,
UnblockTime = DateTime.Now.AddMinutes(30)
};
db.BlockUsers.Add(currentRule);
unblockTime = currentRule.UnblockTime;
TrySend(new MessageItem(SystemMessageType.ReportAbuseResult, success: true, content: $"您的举报已经触发自动处理规则,用户【{dispName}({msg.UserName})】将被请到小黑屋里享受幸福至少十五分钟。(您已举报 {currentUser.AbuseReportCount}次,成功 {currentUser.AbuseReportSuccCount}次,成功率 {currentUser.AbuseReportSuccRate:P1})"));
OnRequireSendMessage(new MessageItem(SystemMessageType.ReportAbuseResult, success: true, content: $"【{currentUser.NickName}】 对【{dispName}({msg.UserName})】的举报已经满足自动处理规则,{dispName} 将会被请到小黑屋里享受幸福至少十五分钟。如果有更多人举报,呆的时间将会延长。({currentUser.NickName} 已举报 {currentUser.AbuseReportCount}次,成功 {currentUser.AbuseReportSuccCount}次,成功率 {currentUser.AbuseReportSuccRate:P1})"), true);
blocked = true;
}
else
{
TrySend(new MessageItem(SystemMessageType.ReportAbuseResult, success: true, content: $"举报成功,等待管理员审核。用户【{dispName}({msg.UserName})】在过去的十五分钟时间内已经被举报 {currentReportCount} 次,如果达到五次将会被自动封禁。(您已举报 {currentUser.AbuseReportCount}次,成功 {currentUser.AbuseReportSuccCount}次,成功率 {currentUser.AbuseReportSuccRate:P1})"));
OnRequireSendMessage(new MessageItem(SystemMessageType.ReportAbuseResult, success: true, content: $"【{currentUser.NickName}】 对【{dispName}({msg.UserName})】的举报已记录。用户【{dispName}({msg.UserName})】在过去的十五分钟时间内已经被举报 {currentReportCount} 次,如果达到五次将会被自动封禁。({currentUser.NickName} 已举报 {currentUser.AbuseReportCount}次,成功 {currentUser.AbuseReportSuccCount}次,成功率 {currentUser.AbuseReportSuccRate:P1})"), true);
}
await db.SaveChangesAsync();
//即时封锁
if (blocked)
{
//自动标记之前的举报
await db.MarkProcessedAbuseReportAsync(msg.UserName, 3);
(AppServer as ChatServer).AddBlockUser(msg.UserName, unblockTime);
}
}
public event EventHandler<RequireSendMessageEventArgs> RequireSendMessage;
protected virtual void OnRequireSendMessage(MessageItem e, bool excludeSender)
{
RequireSendMessage?.Invoke(this, new RequireSendMessageEventArgs(excludeSender, e));
}
}
}