This commit is contained in:
木鱼(iFish) 2015-07-09 21:06:30 +08:00
parent 71aa8be4d5
commit a32cdb0e74
12 changed files with 323 additions and 78 deletions

View File

@ -63,5 +63,36 @@ namespace ChatRoomServer.Db
public virtual DbSet<UserConnectLog> UserConnectLogs { get; set; }
public virtual DbSet<BlockUser> BlockUsers { get; set; }
/// <summary>
/// 异步获得指定用户的屏蔽列表
/// </summary>
/// <param name="username"></param>
/// <returns></returns>
public Task<BlockUser[]> GetBlockRuleForUserAsync(string username)
{
return BlockUsers.SqlQuery("exec usp_BlockUser_GetUserBlockRule {0}", username).ToArrayAsync();
}
/// <summary>
/// 异步获得指定用户的屏蔽列表
/// </summary>
/// <param name="username"></param>
/// <returns></returns>
public BlockUser[] GetBlockRuleForUser(string username)
{
return BlockUsers.SqlQuery("exec usp_BlockUser_GetUserBlockRule {0}", username).ToArray();
}
/// <summary>
/// 查询指定用户在单位时间内被举报的人数
/// </summary>
/// <param name="username"></param>
/// <param name="minutes"></param>
/// <returns></returns>
public int GetUserAbuseReportCountInTime(string username, int minutes)
{
return Database.SqlQuery<int>("exec usp_BlockUser_GetUserReportCount {0}, {1}", username, minutes).First();
}
}
}

View File

@ -79,6 +79,7 @@
<Compile Include="Entities\UserMessageType.cs" />
<Compile Include="Progam.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="RequireSendMessageEventArgs.cs" />
<Compile Include="Room\RoomContainer.cs" />
<Compile Include="Room\RoomSessionContext.cs" />
</ItemGroup>

View File

@ -9,6 +9,8 @@ namespace ChatRoomServer.Main
using System.Collections.Concurrent;
using System.Net;
using System.Timers;
using ChatRoomServer.Db;
using ChatRoomServer.Db.Entities;
using ChatRoomServer.Main.Room;
using FSLib.Logs.Log4Net;
using FSLib.Network.Http;
@ -20,7 +22,7 @@ namespace ChatRoomServer.Main
{
static ILog _log;
static readonly object _lockObject = new object();
internal static HashSet<string> PresetAdministrators = (System.Configuration.ConfigurationManager.AppSettings["chat:admin"] ?? "").Split(new[] {';'}, StringSplitOptions.RemoveEmptyEntries).ToHashSet(StringComparer.OrdinalIgnoreCase);
internal static HashSet<string> PresetAdministrators = (System.Configuration.ConfigurationManager.AppSettings["chat:admin"] ?? "").Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries).ToHashSet(StringComparer.OrdinalIgnoreCase);
static ChatServer()
{
@ -31,6 +33,69 @@ namespace ChatRoomServer.Main
ConcurrentDictionary<ChatSession, RoomContainer> _containers = new ConcurrentDictionary<ChatSession, RoomContainer>();
ConcurrentDictionary<string, RoomContainer> _roomContainers = new ConcurrentDictionary<string, RoomContainer>();
#region block users
Timer _blockUserReloadTimer;
Dictionary<string, DateTime?> _blockUsers = new Dictionary<string, DateTime?>(StringComparer.OrdinalIgnoreCase);
readonly object _blockUserLockObject = new object();
public Dictionary<string, DateTime?> BlockUsers
{
get { return _blockUsers; }
}
void ReloadBlockUsers()
{
var db = new ChatDb();
var blockUsers = db.Database.SqlQuery<BlockUser>("exec usp_BlockUser_GetList").ToArray();
lock (_blockUserLockObject)
{
_blockUsers.Clear();
blockUsers.ForEach(s =>
{
if (!_blockUsers.ContainsKey(s.UserName))
_blockUsers.Add(s.UserName, s.UnblockTime);
else
{
var item = _blockUsers[s.UserName];
if (item != null && (s.UnblockTime == null || s.UnblockTime > item.Value))
{
_blockUsers[s.UserName] = s.UnblockTime;
}
}
});
}
//处理连接
GetAllSessions().ForEach(s =>
{
if (_blockUsers.ContainsKey(s.UserName))
s.Block(_blockUsers[s.UserName]);
});
}
public void AddBlockUser(string username, DateTime? unblockTime)
{
lock (_blockUserLockObject)
{
if (!_blockUsers.ContainsKey(username))
_blockUsers.Add(username, unblockTime);
else
{
var item = _blockUsers[username];
if (item != null && (unblockTime == null || unblockTime > item.Value))
{
_blockUsers[username] = unblockTime;
}
}
}
}
#endregion
internal static ILog GetLogger(string name)
{
return LogManager.GetLogger("Server", name);
@ -48,6 +113,15 @@ namespace ChatRoomServer.Main
SessionClosed += ChatServer_SessionClosed;
InitOnlineCountSync();
//黑名单
_blockUserReloadTimer = new Timer(1000 * 60 * 5) { AutoReset = false };
_blockUserReloadTimer.Elapsed += (s, e) =>
{
ReloadBlockUsers();
_blockUserReloadTimer.Start();
};
ReloadBlockUsers();
}
#region 线
@ -63,19 +137,18 @@ namespace ChatRoomServer.Main
UploadOnlineCount();
_syncOnlineCountTimer.Start();
};
UploadOnlineCount();
_syncOnlineCountTimer.Start();
}
void UploadOnlineCount()
{
var datas = _roomContainers.ToArray();
var data = new
var data = datas.Select(s => new
{
data = JsonConvert.SerializeObject(datas.Select(s => new
{
id = s.Key,
count = s.Value.SessionCount
}).ToArray())
};
id = s.Key,
count = s.Value.SessionCount
}).ToArray();
var client = new HttpClient();
string url;
@ -84,7 +157,7 @@ namespace ChatRoomServer.Main
#else
url = "http://127.0.0.1/api/room/updateOnlineCount";
#endif
var ctx = client.Create<string>(HttpMethod.Post, url, data: data).Send();
var ctx = client.Create<string>(HttpMethod.Post, url, data: data, payloadType: RequestPayloadType.Json).Send();
if (ctx.IsValid())
{

View File

@ -40,6 +40,19 @@ namespace ChatRoomServer.Main
/// </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>
@ -58,6 +71,9 @@ namespace ChatRoomServer.Main
PathSegements = path;
_isAdmin = ChatServer.PresetAdministrators.Contains(UserName);
if (IsBlocked())
return;
//更新统计
var db = new ChatDb();
BlockUser blockRule = null;
@ -74,14 +90,6 @@ namespace ChatRoomServer.Main
db.Users.Add(user);
}
user.LastConnect = DateTime.Now;
if (user.Status == UserStatus.Blocked)
{
//查询封锁记录
blockRule = db.BlockUsers.FirstOrDefault(s => s.UserName == UserName && s.UnblockTime == null || s.UnblockTime > DateTime.Now);
if (blockRule == null)
user.Status = UserStatus.Normal;
}
//当前连接记录
var ucl = new UserConnectLog()
{
UserName = UserName,
@ -95,11 +103,16 @@ namespace ChatRoomServer.Main
//已经封锁?
if (user.Status == UserStatus.Blocked)
{
TrySend(new MessageItem(SystemMessageType.OperationBlocked, content: "很抱歉,您的账户已经被封锁,暂时无法在聊天室暂住。封锁解除时间:" + (blockRule.UnblockTime == null ? "无限期" : blockRule.UnblockTime.Value.ToString())));
Close(CloseReason.TimeOut);
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>
@ -134,6 +147,9 @@ namespace ChatRoomServer.Main
public void ProcessData(byte[] data)
{
if (IsBlocked())
return;
MessageItem item;
try
{
@ -185,7 +201,27 @@ namespace ChatRoomServer.Main
switch (item.UserMsgType)
{
case UserMessageType.Send:
OnRequireSendMessage(item);
//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;
@ -207,11 +243,52 @@ namespace ChatRoomServer.Main
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 = ReportState.Submited,
Status = _isAdmin ? ReportState.AutoProcessed : ReportState.Submited,
TargetId = msgid,
TargetUser = msg.UserName
};
@ -219,34 +296,59 @@ namespace ChatRoomServer.Main
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<MessageItem> RequireSendMessage;
public event EventHandler<RequireSendMessageEventArgs> RequireSendMessage;
protected virtual void OnRequireSendMessage(MessageItem e)
protected virtual void OnRequireSendMessage(MessageItem e, bool excludeSender)
{
//log to db
var db = new ChatDb();
var msg = new MsgLog()
{
AtUser = e.ToUsers?.Select(s => s.UserName).JoinAsString(";"),
Color = e.Color,
Image = e.Images?.JoinAsString(";"),
Content = e.Content,
Ip = RemoteEndPoint.ToString(),
RoomId = PathSegements[1],
SendTime = DateTime.Now,
UserName = UserName
};
db.MsgLogs.Add(msg);
db.SaveChanges();
e.Id = msg.Id;
//更新统计
db.Database.ExecuteSqlCommand("UPDATE Chat_User SET LastSend=GETDATE(), FirstSend=ISNULL(FirstSend, GETDATE()), SendTimes=SendTimes+1 WHERE UserName={0}", UserName);
RequireSendMessage?.Invoke(this, e);
RequireSendMessage?.Invoke(this, new RequireSendMessageEventArgs(excludeSender, e));
}
}
}

View File

@ -0,0 +1,19 @@
namespace ChatRoomServer.Main
{
using System;
using ChatRoomServer.Main.Entities;
class RequireSendMessageEventArgs : EventArgs
{
public MessageItem MessageItem { get; private set; }
public bool ExcludeSender { get; private set; }
public RequireSendMessageEventArgs(bool excludeSender, MessageItem messageItem)
{
ExcludeSender = excludeSender;
MessageItem = messageItem;
}
}
}

View File

@ -43,12 +43,13 @@ namespace ChatRoomServer.Main.Room
session.RequireSendMessage += Session_RequireSendMessage;
}
private void Session_RequireSendMessage(object sender, MessageItem e)
private void Session_RequireSendMessage(object sender, RequireSendMessageEventArgs e)
{
var enumerator = _contexts.GetEnumerator();
while (enumerator.MoveNext())
{
enumerator.Current.Key.TrySend(e);
if (!e.ExcludeSender || sender != enumerator.Current.Key)
enumerator.Current.Key.TrySend(e.MessageItem);
}
}

View File

@ -9,16 +9,17 @@ namespace ChatRoomServer.Www.Areas.Api.Controllers
{
using System.Data.Entity;
using System.Threading.Tasks;
using System.Web.Mvc;
using ChatRoomServer.Db;
using ChatRoomServer.Db.Entities;
using ChatRoomServer.Www.Areas.Api.Models;
using Newtonsoft.Json;
[System.Web.Http.RoutePrefix("api/room")]
[RoutePrefix("api/room")]
public class RoomController : ApiController
{
[AllowAnonymous]
[System.Web.Http.Route("list"), System.Web.Http.HttpGet, OutputCache(Duration = 600)]
public async Task<object> GetAnnouncements()
[Route("list"), HttpGet]
public async Task<object> GetRoomss()
{
var db = new ChatDb();
var items = await db.Rooms.AsNoTracking().ToArrayAsync();
@ -38,26 +39,36 @@ namespace ChatRoomServer.Www.Areas.Api.Controllers
return result;
}
[AllowAnonymous]
[Route("updateOnlineCount")]
[HttpPost]
public async Task<string> UpdateOnlineCount(string data)
public async Task<string> UpdateOnlineCount([FromBody]List<OnlineCountModel> idata)
{
//limit to local
if (!RequestContext.IsLocal)
return "Invalid operation.";
var db = new ChatDb();
var rooms = await db.Rooms.ToDictionaryAsync(s => s.ID);
var idata = JsonConvert.DeserializeAnonymousType(data, System.FishLib.CollectionUtility.CreateAnymousTypeList(new { id = "", count = 0 }));
foreach (var x1 in idata)
{
var room = rooms.GetValue(x1.id);
var room = rooms.GetValue(x1.Id);
if (room != null)
room.OnlineCount = x1.count;
{
room.OnlineCount = x1.Count;
db.OnlineHistories.Add(new OnlineHistory()
{
Time = DateTime.Now,
RoomID = x1.Id,
OnlineCount = x1.Count
});
}
}
//log to history
await db.SaveChangesAsync();
return "Operation succeed";
}
}
}

View File

@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ChatRoomServer.Www.Areas.Api.Models
{
public class OnlineCountModel
{
public string Id { get; set; }
public int Count { get; set; }
}
}

View File

@ -144,6 +144,7 @@
<Compile Include="Areas\Api\Controllers\RoomController.cs" />
<Compile Include="Areas\Api\Controllers\StatController.cs" />
<Compile Include="Areas\Api\Controllers\UsersController.cs" />
<Compile Include="Areas\Api\Models\OnlineCountModel.cs" />
<Compile Include="Controllers\AnnouncementController.cs" />
<Compile Include="Controllers\RoomController.cs" />
<Compile Include="Global.asax.cs">
@ -167,7 +168,6 @@
</ItemGroup>
<ItemGroup>
<Folder Include="App_Data\" />
<Folder Include="Areas\Api\Models\" />
<Folder Include="Content\" />
<Folder Include="Models\" />
<Folder Include="Views\Announcement\" />

View File

@ -203,7 +203,6 @@
item.toUsers.push(readMessageUser());
}
}
console.log(item);
return item;
};
});

View File

@ -5,6 +5,7 @@
exports.SYS_SENDFAILED = 5;
exports.SYS_UPDATEONLINECOUNT = 6;
exports.SYS_OPERATIONBLOCKED = 7;
exports.SYS_REPORTABUSERESULT = 9;
exports.USER_SENDMSG = 1;
exports.USER_RECEIVEMSG = 2;

View File

@ -202,8 +202,11 @@
}
} else if (msg.sysMsgType === cmds.SYS_SENDFAILED) {
} else if (msg.sysMsgType === cmds.SYS_OPERATIONBLOCKED) {
mp.showMessagePopup("error", msg.content);
} else if (msg.sysMsgType === cmds.SYS_UPDATEONLINECOUNT) {
that.appendMessageItem(roomSysMessage({ stateIcon: "fa-info-circle", state: "system", msg: "您已离开房间,当前房间在线 " + room.onlinecount + " 人。" }));
} else if (msg.sysMsgType === cmds.SYS_REPORTABUSERESULT) {
that.appendMessageItem(roomSysMessage({ stateIcon: "fa-info-circle", state: "system", msg: msg.content }));
}
};
this.processUserMessage = function (msg) {
@ -439,36 +442,25 @@
var a = $(this);
var item = a.closest(".chat-item");
var chatid = parseInt(item[0].dataset.chatid);
var authorlink = item.find(".chat-item-at:eq(0)");
var username = authorlink[0].dataset.un;
var authorlink = item.find(".chat-item-at:eq(0)")[0];
var username = authorlink.dataset.un;
if (username === '*') {
mp.showMessagePopup("error", "亲,不可以举报我们伟大的管理员哦 ♪(´ε`)");
return;
}
if (!confirm("确定要举报 " + (username.innerText) + " 吗?"))
if (!confirm("确定要举报 " + (authorlink.innerText) + " 吗?"))
return;
var data = {
sysMsgType: cmds.USER_REPORTABUSE,
content: chatid,
systemMessage: false,
userMsgType: cmds.USER_REPORTABUSE,
content: chatid + "",
time: new Date()
};
var dlg = new mp.MessagePopup("loading", "举报受理中,请稍候...");
dlg.show();
$.post("http://12306.liebao.cn/index.php?r=Api/AbuseReport", { ar_data: JSON.stringify(reportData) }, "json").done(function (json) {
if (json.resCode !== 0) {
dlg.setState("error", "未能成功举报:" + json.message);
} else {
dlg.setState("ok", "举报已受理,感谢您的合作。");
}
}).fail(function () {
dlg.setState("error", "未能成功举报,请稍后重试。");
}).always(function () {
dlg.delayClose();
});
port.postMessage("chatRoomSendMsg", coder.encode(data));
});
$(document).on("click", "a.chat-frame-reconnect", function () {
$(".chat-item").remove();