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 ;
2015-10-21 12:40:04 +08:00
using ChatRoomServer.Main.Room ;
2015-07-08 17:24:45 +08:00
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-10-21 12:40:04 +08:00
/// <summary>
/// 获得或设置房间
/// </summary>
public RoomContainer RoomContainer { get ; 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 )
{
2015-08-03 15:07:49 +08:00
IsSessionBlocked = true ;
2015-07-09 21:06:30 +08:00
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 ;
}
2015-08-03 15:07:49 +08:00
public bool IsSessionBlocked { get ; private set ; }
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-10-21 12:40:04 +08:00
//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(" 、 ")} 已不在线。】" ;
}
}
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 ] ,
2015-08-03 15:07:49 +08:00
SendTime = item . Time ,
2015-07-09 21:06:30 +08:00
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
2015-10-21 12:40:04 +08:00
async void ProcessReport ( long msgid )
2015-07-08 17:24:45 +08:00
{
if ( msgid < = 0 )
return ;
var db = new ChatDb ( ) ;
2015-10-21 12:40:04 +08:00
//查找当前用户资料
var currentUser = db . Users . Find ( UserName ) ;
if ( currentUser . DisableAbuseReport )
{
TrySend ( new MessageItem ( SystemMessageType . ReportAbuseResult , success : false , content : "很抱歉,管理员已暂时关闭了您的举报权限。" ) ) ;
2015-07-08 17:24:45 +08:00
return ;
2015-10-21 12:40:04 +08:00
}
if ( currentUser . AbuseReportSuccRate < 0.1 )
{
TrySend ( new MessageItem ( SystemMessageType . ReportAbuseResult , success : false , content : "很抱歉,您当前举报成功率过低(<0.2),系统暂时不接受您新的举报。已有举报未通过审核时,请等待管理员审核。" ) ) ;
return ;
}
2015-07-08 17:24:45 +08:00
2015-07-09 21:06:30 +08:00
//此消息是否已经被举报过了?
if ( db . AbuseReports . Any ( s = > s . TargetId = = msgid & & s . ReportUser = = UserName ) )
{
//重复举报
2015-10-21 12:40:04 +08:00
TrySend ( new MessageItem ( SystemMessageType . ReportAbuseResult , success : false , content : "这条消息您已经举报过哦,请不要重复举报消息。" ) ) ;
2015-07-09 21:06:30 +08:00
return ;
}
2015-10-21 12:40:04 +08:00
var msg = db . MsgLogs . Find ( msgid ) ;
if ( msg = = null )
return ;
var dispName = db . Users . Find ( msg . UserName ) ? . NickName ? ? "" ;
2015-07-09 21:06:30 +08:00
//是否已经有屏蔽记录了?
2015-10-21 12:40:04 +08:00
currentUser . AbuseReportCount + + ;
2015-07-09 21:06:30 +08:00
var currentRule = db . GetBlockRuleForUser ( msg . UserName ) . LastOrDefault ( ) ;
if ( currentRule ! = null )
{
2015-10-21 12:40:04 +08:00
2015-07-09 21:06:30 +08:00
if ( currentRule . UnblockTime ! = null )
{
2015-10-21 12:40:04 +08:00
currentUser . AbuseReportSuccCount + + ;
2015-07-09 21:06:30 +08:00
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 ) ;
2015-10-21 12:40:04 +08:00
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 ) ;
2015-07-09 21:06:30 +08:00
db . SaveChanges ( ) ;
}
else
{
2015-10-21 12:40:04 +08:00
TrySend ( new MessageItem ( SystemMessageType . ReportAbuseResult , success : true , content : $"无需举报,用户【{dispName}({msg.UserName})】已经暂时不会从小黑屋里粗来了" ) ) ;
2015-07-09 21:06:30 +08:00
}
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 )
{
2015-10-21 12:40:04 +08:00
currentUser . AbuseReportSuccCount + + ;
2015-07-09 21:06:30 +08:00
currentRule = new BlockUser ( )
{
BlockTime = DateTime . Now ,
UserName = msg . UserName ,
UnblockTime = DateTime . Now . AddMinutes ( 300 )
} ;
db . BlockUsers . Add ( currentRule ) ;
unblockTime = currentRule . UnblockTime ;
2015-10-21 12:40:04 +08:00
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 ) ;
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 )
{
2015-10-21 12:40:04 +08:00
currentUser . AbuseReportSuccCount + + ;
2015-07-09 21:06:30 +08:00
currentRule = new BlockUser ( )
{
BlockTime = DateTime . Now ,
UserName = msg . UserName ,
UnblockTime = DateTime . Now . AddMinutes ( 30 )
} ;
db . BlockUsers . Add ( currentRule ) ;
unblockTime = currentRule . UnblockTime ;
2015-10-21 12:40:04 +08:00
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 ) ;
2015-07-08 17:24:45 +08:00
2015-07-09 21:06:30 +08:00
blocked = true ;
}
else
{
2015-10-21 12:40:04 +08:00
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 ) ;
2015-07-09 21:06:30 +08:00
}
2015-10-21 12:40:04 +08:00
await db . SaveChangesAsync ( ) ;
2015-07-08 17:24:45 +08:00
2015-07-09 21:06:30 +08:00
//即时封锁
if ( blocked )
{
2015-10-21 12:40:04 +08:00
//自动标记之前的举报
await db . MarkProcessedAbuseReportAsync ( msg . UserName , 3 ) ;
2015-07-09 21:06:30 +08:00
( 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
}
}