Light12306/ChatRoomServer.Main/ChatSession.cs

356 lines
10 KiB
C#
Raw Normal View History

2015-07-01 16:18:25 +08:00
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ChatRoomServer.Main
{
2015-07-08 17:24:45 +08:00
using ChatRoomServer.Db;
using ChatRoomServer.Db.Entities;
using ChatRoomServer.Main.Entities;
using FSLib.Logs.Log4Net;
2015-07-01 16:18:25 +08:00
using FSLib.Network.SuperSocket.Protocols.WebSocket;
2015-07-08 17:24:45 +08:00
using FSLib.Network.SuperSocket.SocketBase;
2015-07-01 16:18:25 +08:00
class ChatSession : WebSocketSession<ChatSession>
{
2015-07-08 17:24:45 +08:00
static ILog _log = ChatServer.GetLogger(typeof(ChatSession).Name);
DateTime _connecTime = DateTime.Now;
long _connectId;
2015-07-08 20:49:11 +08:00
bool _isAdmin;
2015-07-08 17:24:45 +08:00
/// <summary>
/// 路径分割
/// </summary>
public string[] PathSegements { get; private set; }
2015-07-01 16:18:25 +08:00
/// <summary>
/// 命令
/// </summary>
public string Command { get; private set; }
2015-07-08 17:24:45 +08:00
public string UserName { get; private set; }
public string NickName { get; private set; }
2015-07-01 16:18:25 +08:00
/// <summary>
/// ID
/// </summary>
public string Id { get; private set; }
2015-07-09 21:06:30 +08:00
bool IsBlocked()
{
DateTime? dt = null;
if ((AppServer as ChatServer).BlockUsers?.TryGetValue(UserName, out dt) == true)
{
Block(dt);
return true;
}
return false;
}
2015-07-01 16:18:25 +08:00
/// <summary>
2015-07-08 17:24:45 +08:00
/// Called when [session started].
2015-07-01 16:18:25 +08:00
/// </summary>
2015-07-08 17:24:45 +08:00
protected override void OnSessionStarted()
2015-07-01 16:18:25 +08:00
{
2015-07-08 17:24:45 +08:00
base.OnSessionStarted();
2015-07-01 16:18:25 +08:00
var path = Path.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
2015-07-08 17:24:45 +08:00
if (path.Length >= 4)
2015-07-01 16:18:25 +08:00
{
Command = path[0];
2015-07-08 17:24:45 +08:00
Id = System.Net.WebUtility.UrlDecode(path[1]);
UserName = System.Net.WebUtility.UrlDecode(path[2]);
NickName = System.Net.WebUtility.UrlDecode(path[3]);
}
PathSegements = path;
2015-07-08 20:49:11 +08:00
_isAdmin = ChatServer.PresetAdministrators.Contains(UserName);
2015-07-08 17:24:45 +08:00
2015-07-09 21:06:30 +08:00
if (IsBlocked())
return;
2015-07-08 17:24:45 +08:00
//更新统计
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,
2015-07-16 21:00:51 +08:00
RoomID = Id,
Ip = RemoteEndPoint.ToString()
2015-07-08 17:24:45 +08:00
};
db.UserConnectLogs.Add(ucl);
db.SaveChanges();
_connectId = ucl.Id;
//已经封锁?
if (user.Status == UserStatus.Blocked)
{
2015-07-09 21:06:30 +08:00
Block(blockRule.UnblockTime);
2015-07-08 17:24:45 +08:00
}
}
2015-07-09 21:06:30 +08:00
public void Block(DateTime? unblockTime)
{
TrySend(new MessageItem(SystemMessageType.OperationBlocked, content: "很抱歉,您的账户已经被封锁,暂时无法在聊天室暂住。封锁解除时间:" + (unblockTime == null ? "无限期" : unblockTime.Value.ToString())));
Close(CloseReason.TimeOut);
}
2015-07-08 17:24:45 +08:00
/// <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)
{
2015-07-09 21:06:30 +08:00
if (IsBlocked())
return;
2015-07-08 17:24:45 +08:00
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:
2015-07-09 21:06:30 +08:00
//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 = DateTime.Now,
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);
2015-07-08 17:24:45 +08:00
break;
case UserMessageType.Receive:
break;
case UserMessageType.ReportAbuse:
ProcessReport(item.Content.ToInt64());
break;
default:
break;
2015-07-01 16:18:25 +08:00
}
}
2015-07-08 17:24:45 +08:00
void ProcessReport(long msgid)
{
if (msgid <= 0)
return;
var db = new ChatDb();
var msg = db.MsgLogs.Find(msgid);
if (msg == null)
return;
2015-07-09 21:06:30 +08:00
//此消息是否已经被举报过了?
if (db.AbuseReports.Any(s => s.TargetId == msgid && s.ReportUser == UserName))
{
//重复举报
TrySend(new MessageItem(SystemMessageType.ReportAbuseResult, success: false, content: "这条消息您已经举报过哦。"));
return;
}
//是否已经有屏蔽记录了?
var currentRule = db.GetBlockRuleForUser(msg.UserName).LastOrDefault();
if (currentRule != null)
{
if (currentRule.UnblockTime != null)
{
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: $"已经举报成功。由于您的添砖加瓦,用户【{msg.UserName}】将会在小黑屋中多享受 {extra} 分钟的幸福时光 ♪(´ε`)"));
OnRequireSendMessage(new MessageItem(SystemMessageType.ReportAbuseResult, success: true, content: $"已经举报成功。由于您的添砖加瓦,用户【{msg.UserName}】将会在小黑屋中多享受 {extra} 分钟的幸福时光 ♪(´ε`)"), true);
db.SaveChanges();
}
else
{
TrySend(new MessageItem(SystemMessageType.ReportAbuseResult, success: true, content: $"无需举报,用户【{msg.UserName}】已经暂时不会从小黑屋里粗来了"));
OnRequireSendMessage(new MessageItem(SystemMessageType.ReportAbuseResult, success: true, content: $"无需举报,用户【{msg.UserName}】已经暂时不会从小黑屋里粗来了"), true);
}
return;
}
//没有处于屏蔽状态,则
2015-07-08 17:24:45 +08:00
var rlog = new AbuseReport()
{
ReportTime = DateTime.Now,
ReportUser = UserName,
2015-07-09 21:06:30 +08:00
Status = _isAdmin ? ReportState.AutoProcessed : ReportState.Submited,
2015-07-08 17:24:45 +08:00
TargetId = msgid,
TargetUser = msg.UserName
};
db.AbuseReports.Add(rlog);
db.SaveChanges();
//自动处理
2015-07-09 21:06:30 +08:00
//如果是管理员,则自动禁言两个小时
var blocked = false;
var currentReportCount = 0;
DateTime? unblockTime = null;
if (_isAdmin)
{
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: $"您已将用户【{msg.UserName}】请到小黑屋里享受幸福至少五个小时。如果有更多人举报,呆的时间将会延长。"));
OnRequireSendMessage(new MessageItem(SystemMessageType.ReportAbuseResult, success: true, content: $"用户【{msg.UserName}】已经被管理员请到小黑屋里享受幸福至少五个小时。如果有更多人举报,呆的时间将会延长。"), true);
2015-07-08 17:24:45 +08:00
2015-07-09 21:06:30 +08:00
blocked = true;
}
else if ((currentReportCount = db.GetUserAbuseReportCountInTime(msg.UserName, 15)) > 5)
{
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: $"您已将用户【{msg.UserName}】请到小黑屋里享受幸福至少十五分钟。"));
OnRequireSendMessage(new MessageItem(SystemMessageType.ReportAbuseResult, success: true, content: $"用户【{msg.UserName}】已经被管理员请到小黑屋里享受幸福至少十五分钟。如果有更多人举报,呆的时间将会延长。"), true);
2015-07-08 17:24:45 +08:00
2015-07-09 21:06:30 +08:00
blocked = true;
}
else
{
TrySend(new MessageItem(SystemMessageType.ReportAbuseResult, success: true, content: $"举报成功,等待管理员审核。用户【{msg.UserName}】在过去的十五分钟时间内已经被举报 {currentReportCount} 次,如果达到五次将会被自动封禁。"));
OnRequireSendMessage(new MessageItem(SystemMessageType.ReportAbuseResult, success: true, content: $"用户【{msg.UserName}】在过去的十五分钟时间内已经被举报 {currentReportCount} 次,如果达到五次将会被自动封禁。"), true);
}
2015-07-08 17:24:45 +08:00
db.SaveChanges();
2015-07-09 21:06:30 +08:00
//即时封锁
if (blocked)
{
(AppServer as ChatServer).AddBlockUser(msg.UserName, unblockTime);
}
}
public event EventHandler<RequireSendMessageEventArgs> RequireSendMessage;
2015-07-08 17:24:45 +08:00
2015-07-09 21:06:30 +08:00
protected virtual void OnRequireSendMessage(MessageItem e, bool excludeSender)
{
RequireSendMessage?.Invoke(this, new RequireSendMessageEventArgs(excludeSender, e));
2015-07-08 17:24:45 +08:00
}
2015-07-01 16:18:25 +08:00
}
}