Light12306/ChatRoomServer.Main/ChatSession.cs
2015-07-09 21:06:30 +08:00

355 lines
10 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 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>
/// ID
/// </summary>
public string Id { get; private set; }
bool IsBlocked()
{
DateTime? dt = null;
if ((AppServer as ChatServer).BlockUsers?.TryGetValue(UserName, out dt) == 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
};
db.UserConnectLogs.Add(ucl);
db.SaveChanges();
_connectId = ucl.Id;
//已经封锁?
if (user.Status == UserStatus.Blocked)
{
Block(blockRule.UnblockTime);
}
}
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:
//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);
break;
case UserMessageType.Receive:
break;
case UserMessageType.ReportAbuse:
ProcessReport(item.Content.ToInt64());
break;
default:
break;
}
}
void ProcessReport(long msgid)
{
if (msgid <= 0)
return;
var db = new ChatDb();
var msg = db.MsgLogs.Find(msgid);
if (msg == null)
return;
//此消息是否已经被举报过了?
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;
}
//没有处于屏蔽状态,则
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)
{
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);
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);
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);
}
db.SaveChanges();
//即时封锁
if (blocked)
{
(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));
}
}
}