Reduce usage of working objects in packet objects as much as possible.

This commit is contained in:
flash 2024-05-10 18:29:48 +00:00
parent 356409eb16
commit b95cd06cb1
27 changed files with 314 additions and 206 deletions

View file

@ -1,11 +1,11 @@
using System.Diagnostics.CodeAnalysis;
namespace SharpChat {
public struct ChatColour {
public byte Red { get; }
public byte Green { get; }
public byte Blue { get; }
public bool Inherits { get; }
public readonly struct ChatColour {
public readonly byte Red;
public readonly byte Green;
public readonly byte Blue;
public readonly bool Inherits;
public static ChatColour None { get; } = new();

View file

@ -192,7 +192,13 @@ namespace SharpChat {
if(previousName != null)
SendToUserChannels(user, new UserUpdateNotificationPacket(previousName, user.LegacyNameWithStatus));
SendToUserChannels(user, new UserUpdatePacket(user));
SendToUserChannels(user, new UserUpdatePacket(
user.UserId,
user.LegacyNameWithStatus,
user.Colour,
user.Rank,
user.Permissions
));
}
}
@ -213,17 +219,36 @@ namespace SharpChat {
public void HandleJoin(ChatUser user, ChatChannel chan, ChatConnection conn, int maxMsgLength) {
if(!IsInChannel(user, chan)) {
SendTo(chan, new UserConnectPacket(DateTimeOffset.Now, user));
SendTo(chan, new UserConnectPacket(
DateTimeOffset.Now,
user.UserId,
user.LegacyNameWithStatus,
user.Colour,
user.Rank,
user.Permissions
));
Events.AddEvent("user:connect", user, chan, flags: StoredEventFlags.Log);
}
conn.Send(new AuthSuccessPacket(user, chan, conn, maxMsgLength));
conn.Send(new ContextUsersPacket(GetChannelUsers(chan).Except(new[] { user }).OrderByDescending(u => u.Rank)));
conn.Send(new AuthSuccessPacket(
user.UserId,
user.LegacyNameWithStatus,
user.Colour,
user.Rank,
user.Permissions,
chan.Name,
maxMsgLength
));
conn.Send(new ContextUsersPacket(GetChannelUsers(chan).Except(new[] { user }).Select(
user => new ContextUsersPacket.ListEntry(user.UserId, user.LegacyNameWithStatus, user.Colour, user.Rank, user.Permissions, true)
).OrderByDescending(user => user.Rank).ToArray()));
foreach(StoredEventInfo msg in Events.GetChannelEventLog(chan.Name))
conn.Send(new ContextMessagePacket(msg));
conn.Send(new ContextChannelsPacket(Channels.Where(c => c.Rank <= user.Rank)));
conn.Send(new ContextChannelsPacket(Channels.Where(c => c.Rank <= user.Rank).Select(
channel => new ContextChannelsPacket.ListEntry(channel.Name, channel.HasPassword, channel.IsTemporary)
).ToArray()));
Users.Add(user);
@ -241,7 +266,7 @@ namespace SharpChat {
foreach(ChatChannel chan in channels) {
ChannelUsers.Remove(new ChannelUserAssoc(user.UserId, chan.Name));
SendTo(chan, new UserDisconnectPacket(DateTimeOffset.Now, user, reason));
SendTo(chan, new UserDisconnectPacket(DateTimeOffset.Now, user.UserId, user.LegacyNameWithStatus, reason));
Events.AddEvent("user:disconnect", user, chan, new { reason = (int)reason }, StoredEventFlags.Log);
if(chan.IsTemporary && chan.IsOwner(user))
@ -278,13 +303,15 @@ namespace SharpChat {
ChatChannel oldChan = UserLastChannel[user.UserId];
SendTo(oldChan, new UserChannelLeavePacket(user));
SendTo(oldChan, new UserChannelLeavePacket(user.UserId));
Events.AddEvent("chan:leave", user, oldChan, flags: StoredEventFlags.Log);
SendTo(chan, new UserChannelJoinPacket(user));
SendTo(chan, new UserChannelJoinPacket(user.UserId, user.LegacyNameWithStatus, user.Colour, user.Rank, user.Permissions));
Events.AddEvent("chan:join", user, oldChan, flags: StoredEventFlags.Log);
SendTo(user, new ContextClearPacket(chan, ContextClearMode.MessagesUsers));
SendTo(user, new ContextUsersPacket(GetChannelUsers(chan).Except(new[] { user }).OrderByDescending(u => u.Rank)));
SendTo(user, new ContextClearPacket(ContextClearMode.MessagesUsers));
SendTo(user, new ContextUsersPacket(GetChannelUsers(chan).Except(new[] { user }).Select(
user => new ContextUsersPacket.ListEntry(user.UserId, user.LegacyNameWithStatus, user.Colour, user.Rank, user.Permissions, true)
).OrderByDescending(u => u.Rank).ToArray()));
foreach(StoredEventInfo msg in Events.GetChannelEventLog(chan.Name))
SendTo(user, new ContextMessagePacket(msg));
@ -354,27 +381,29 @@ namespace SharpChat {
if(chan == null && !UserLastChannel.TryGetValue(user.UserId, out chan))
throw new ArgumentException("no channel???");
SendTo(user, new UserChannelForceJoinPacket(chan));
SendTo(user, new UserChannelForceJoinPacket(chan.Name));
}
public void UpdateChannel(ChatChannel channel, bool? temporary = null, int? hierarchy = null, string password = null) {
public void UpdateChannel(ChatChannel channel, bool? temporary = null, int? minRank = null, string password = null) {
if(channel == null)
throw new ArgumentNullException(nameof(channel));
if(!Channels.Contains(channel))
throw new ArgumentException("Provided channel is not registered with this manager.", nameof(channel));
string prevName = channel.Name;
if(temporary.HasValue)
channel.IsTemporary = temporary.Value;
if(hierarchy.HasValue)
channel.Rank = hierarchy.Value;
if(minRank.HasValue)
channel.Rank = minRank.Value;
if(password != null)
channel.Password = password;
// TODO: Users that no longer have access to the channel/gained access to the channel by the hierarchy change should receive delete and create packets respectively
// TODO: Users that no longer have access to the channel/gained access to the channel by the rank change should receive delete and create packets respectively
foreach(ChatUser user in Users.Where(u => u.Rank >= channel.Rank)) {
SendTo(user, new ChannelUpdatePacket(channel.Name, channel));
SendTo(user, new ChannelUpdatePacket(prevName, channel.Name, channel.HasPassword, channel.IsTemporary));
}
}
@ -396,7 +425,7 @@ namespace SharpChat {
// Broadcast deletion of channel
foreach(ChatUser user in Users.Where(u => u.Rank >= channel.Rank))
SendTo(user, new ChannelDeletePacket(channel));
SendTo(user, new ChannelDeletePacket(channel.Name));
}
}
}

View file

@ -1,6 +1,7 @@
using SharpChat.Misuzu;
using SharpChat.Packet;
using System;
using System.Linq;
using System.Threading.Tasks;
namespace SharpChat.Commands {
@ -24,7 +25,9 @@ namespace SharpChat.Commands {
Task.Run(async () => {
ctx.Chat.SendTo(ctx.User, new BanListPacket(
await Misuzu.GetBanListAsync()
(await Misuzu.GetBanListAsync()).Select(
ban => string.IsNullOrEmpty(ban.UserName) ? ban.RemoteAddress : ban.UserName
).ToArray()
));
}).Wait();
}

View file

@ -51,7 +51,11 @@ namespace SharpChat.Commands {
ctx.Chat.Channels.Add(createChan);
foreach(ChatUser ccu in ctx.Chat.Users.Where(u => u.Rank >= ctx.Channel.Rank))
ctx.Chat.SendTo(ccu, new ChannelCreatePacket(ctx.Channel));
ctx.Chat.SendTo(ccu, new ChannelCreatePacket(
ctx.Channel.Name,
ctx.Channel.HasPassword,
ctx.Channel.IsTemporary
));
ctx.Chat.SwitchChannel(ctx.User, createChan, createChan.Password);
ctx.Chat.SendTo(ctx.User, new LegacyCommandResponse(LCR.CHANNEL_CREATED, false, createChan.Name));

View file

@ -20,7 +20,7 @@ namespace SharpChat.Commands {
return;
}
ctx.Chat.UpdateChannel(ctx.Channel, hierarchy: chanHierarchy);
ctx.Chat.UpdateChannel(ctx.Channel, minRank: chanHierarchy);
ctx.Chat.SendTo(ctx.User, new LegacyCommandResponse(LCR.CHANNEL_HIERARCHY_CHANGED, false));
}
}

View file

@ -1,5 +1,4 @@
using SharpChat.Misuzu;
using System;
using System;
namespace SharpChat.Packet {
public enum AuthFailReason {
@ -9,14 +8,16 @@ namespace SharpChat.Packet {
}
public class AuthFailPacket : ServerPacket {
public AuthFailReason Reason { get; private set; }
public MisuzuBanInfo BanInfo { get; private set; }
private readonly AuthFailReason Reason;
private readonly DateTimeOffset Expires;
public AuthFailPacket(AuthFailReason reason, MisuzuBanInfo fbi = null) {
public AuthFailPacket(AuthFailReason reason) {
Reason = reason;
}
if(reason == AuthFailReason.Banned)
BanInfo = fbi ?? throw new ArgumentNullException(nameof(fbi));
public AuthFailPacket(DateTimeOffset expires) {
Reason = AuthFailReason.Banned;
Expires = expires;
}
public override string Pack() {
@ -28,7 +29,7 @@ namespace SharpChat.Packet {
});
if(Reason == AuthFailReason.Banned)
packet += string.Format("\t{0}", BanInfo.IsPermanent ? -1 : BanInfo.ExpiresAt.ToUnixTimeSeconds());
packet += string.Format("\t{0}", Expires.Year >= 2100 ? -1 : Expires.ToUnixTimeSeconds());
return packet;
}

View file

@ -2,37 +2,46 @@
namespace SharpChat.Packet {
public class AuthSuccessPacket : ServerPacket {
public ChatUser User { get; private set; }
public ChatChannel Channel { get; private set; }
public ChatConnection Connection { get; private set; }
public int MaxMessageLength { get; private set; }
private readonly long UserId;
private readonly string UserName;
private readonly ChatColour UserColour;
private readonly int UserRank;
private readonly ChatUserPermissions UserPerms;
private readonly string ChannelName;
private readonly int MaxMessageLength;
public AuthSuccessPacket(
ChatUser user,
ChatChannel channel,
ChatConnection connection,
long userId,
string userName,
ChatColour userColour,
int userRank,
ChatUserPermissions userPerms,
string channelName,
int maxMsgLength
) {
User = user ?? throw new ArgumentNullException(nameof(user));
Channel = channel ?? throw new ArgumentNullException(nameof(channel));
Connection = connection ?? throw new ArgumentNullException(nameof(connection));
UserId = userId;
UserName = userName ?? throw new ArgumentNullException(nameof(userName));
UserColour = userColour;
UserRank = userRank;
UserPerms = userPerms;
ChannelName = channelName ?? throw new ArgumentNullException(nameof(channelName));
MaxMessageLength = maxMsgLength;
}
public override string Pack() {
return string.Format(
"1\ty\t{0}\t{1}\t{2}\t{3} {4} {5} {6} {7}\t{8}\t{9}",
User.UserId,
User.LegacyNameWithStatus,
User.Colour,
User.Rank,
User.Can(ChatUserPermissions.KickUser) ? 1 : 0,
User.Can(ChatUserPermissions.ViewLogs) ? 1 : 0,
User.Can(ChatUserPermissions.SetOwnNickname) ? 1 : 0,
User.Can(ChatUserPermissions.CreateChannel | ChatUserPermissions.SetChannelPermanent, true) ? 2 : (
User.Can(ChatUserPermissions.CreateChannel) ? 1 : 0
),
Channel.Name,
UserId,
UserName,
UserColour,
UserRank,
UserPerms.HasFlag(ChatUserPermissions.KickUser) ? 1 : 0,
UserPerms.HasFlag(ChatUserPermissions.ViewLogs) ? 1 : 0,
UserPerms.HasFlag(ChatUserPermissions.SetOwnNickname) ? 1 : 0,
UserPerms.HasFlag(ChatUserPermissions.CreateChannel) ? (
UserPerms.HasFlag(ChatUserPermissions.SetChannelPermanent) ? 2 : 1
) : 0,
ChannelName,
MaxMessageLength
);
}

View file

@ -1,14 +1,12 @@
using SharpChat.Misuzu;
using System;
using System.Collections.Generic;
using System;
using System.Linq;
using System.Text;
namespace SharpChat.Packet {
public class BanListPacket : ServerPacket {
public IEnumerable<MisuzuBanInfo> Bans { get; private set; }
private readonly string[] Bans;
public BanListPacket(IEnumerable<MisuzuBanInfo> bans) {
public BanListPacket(string[] bans) {
Bans = bans ?? throw new ArgumentNullException(nameof(bans));
}
@ -17,10 +15,8 @@ namespace SharpChat.Packet {
sb.AppendFormat("2\t{0}\t-1\t0\fbanlist\f", DateTimeOffset.Now.ToUnixTimeSeconds());
foreach(MisuzuBanInfo ban in Bans) {
string banStr = string.IsNullOrEmpty(ban.UserName) ? ban.RemoteAddress : ban.UserName;
sb.AppendFormat(@"<a href=""javascript:void(0);"" onclick=""Chat.SendMessageWrapper('/unban '+ this.innerHTML);"">{0}</a>, ", banStr);
}
foreach(string ban in Bans)
sb.AppendFormat(@"<a href=""javascript:void(0);"" onclick=""Chat.SendMessageWrapper('/unban '+ this.innerHTML);"">{0}</a>, ", ban);
if(Bans.Any())
sb.Length -= 2;

View file

@ -1,17 +1,27 @@
namespace SharpChat.Packet {
public class ChannelCreatePacket : ServerPacket {
public ChatChannel Channel { get; private set; }
using System;
public ChannelCreatePacket(ChatChannel channel) {
Channel = channel;
namespace SharpChat.Packet {
public class ChannelCreatePacket : ServerPacket {
private readonly string ChannelName;
private readonly bool ChannelHasPassword;
private readonly bool ChannelIsTemporary;
public ChannelCreatePacket(
string channelName,
bool channelHasPassword,
bool channelIsTemporary
) {
ChannelName = channelName ?? throw new ArgumentNullException(nameof(channelName));
ChannelHasPassword = channelHasPassword;
ChannelIsTemporary = channelIsTemporary;
}
public override string Pack() {
return string.Format(
"4\t0\t{0}\t{1}\t{2}",
Channel.Name,
Channel.HasPassword ? 1 : 0,
Channel.IsTemporary ? 1 : 0
ChannelName,
ChannelHasPassword ? 1 : 0,
ChannelIsTemporary ? 1 : 0
);
}
}

View file

@ -2,14 +2,14 @@
namespace SharpChat.Packet {
public class ChannelDeletePacket : ServerPacket {
public ChatChannel Channel { get; private set; }
private readonly string ChannelName;
public ChannelDeletePacket(ChatChannel channel) {
Channel = channel ?? throw new ArgumentNullException(nameof(channel));
public ChannelDeletePacket(string channelName) {
ChannelName = channelName ?? throw new ArgumentNullException(nameof(channelName));
}
public override string Pack() {
return string.Format("4\t2\t{0}", Channel.Name);
return string.Format("4\t2\t{0}", ChannelName);
}
}
}

View file

@ -1,20 +1,31 @@
namespace SharpChat.Packet {
public class ChannelUpdatePacket : ServerPacket {
public string PreviousName { get; private set; }
public ChatChannel Channel { get; private set; }
using System;
public ChannelUpdatePacket(string previousName, ChatChannel channel) {
PreviousName = previousName;
Channel = channel;
namespace SharpChat.Packet {
public class ChannelUpdatePacket : ServerPacket {
private readonly string ChannelNamePrevious;
private readonly string ChannelNameNew;
private readonly bool ChannelHasPassword;
private readonly bool ChannelIsTemporary;
public ChannelUpdatePacket(
string channelNamePrevious,
string channelNameNew,
bool channelHasPassword,
bool channelIsTemporary
) {
ChannelNamePrevious = channelNamePrevious ?? throw new ArgumentNullException(nameof(channelNamePrevious));
ChannelNameNew = channelNameNew ?? throw new ArgumentNullException(nameof(channelNameNew));
ChannelHasPassword = channelHasPassword;
ChannelIsTemporary = channelIsTemporary;
}
public override string Pack() {
return string.Format(
"4\t1\t{0}\t{1}\t{2}\t{3}",
PreviousName,
Channel.Name,
Channel.HasPassword ? 1 : 0,
Channel.IsTemporary ? 1 : 0
ChannelNamePrevious,
ChannelNameNew,
ChannelHasPassword ? 1 : 0,
ChannelIsTemporary ? 1 : 0
);
}
}

View file

@ -2,29 +2,29 @@
namespace SharpChat.Packet {
public class ChatMessageAddPacket : ServerPacket {
public DateTimeOffset Created { get; }
public long UserId { get; }
public string Text { get; }
public bool IsAction { get; }
public bool IsPrivate { get; }
private readonly DateTimeOffset Created;
private readonly long UserId;
private readonly string Body;
private readonly bool IsAction;
private readonly bool IsPrivate;
public ChatMessageAddPacket(
long msgId,
DateTimeOffset created,
long userId,
string text,
string body,
bool isAction,
bool isPrivate
) : base(msgId) {
Created = created;
UserId = userId < 0 ? -1 : userId;
Text = text;
Body = body ?? throw new ArgumentNullException(nameof(body));
IsAction = isAction;
IsPrivate = isPrivate;
}
public override string Pack() {
string body = Text.Replace("<", "&lt;").Replace(">", "&gt;").Replace("\n", " <br/> ").Replace("\t", " ");
string body = Body.Replace("<", "&lt;").Replace(">", "&gt;").Replace("\n", " <br/> ").Replace("\t", " ");
if(IsAction)
body = string.Format("<i>{0}</i>", body);

View file

@ -1,6 +1,6 @@
namespace SharpChat.Packet {
public class ChatMessageDeletePacket : ServerPacket {
public long EventId { get; private set; }
private readonly long EventId;
public ChatMessageDeletePacket(long eventId) {
EventId = eventId;

View file

@ -1,27 +1,27 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace SharpChat.Packet {
public class ContextChannelsPacket : ServerPacket {
public IEnumerable<ChatChannel> Channels { get; private set; }
public record ListEntry(string Name, bool HasPassword, bool IsTemporary);
public ContextChannelsPacket(IEnumerable<ChatChannel> channels) {
Channels = channels?.Where(c => c != null) ?? throw new ArgumentNullException(nameof(channels));
private readonly ListEntry[] Entries;
public ContextChannelsPacket(ListEntry[] entries) {
Entries = entries ?? throw new ArgumentNullException(nameof(entries));
}
public override string Pack() {
StringBuilder sb = new();
sb.AppendFormat("7\t2\t{0}", Channels.Count());
sb.AppendFormat("7\t2\t{0}", Entries.Length);
foreach(ChatChannel channel in Channels)
foreach(ListEntry entry in Entries)
sb.AppendFormat(
"\t{0}\t{1}\t{2}",
channel.Name,
channel.HasPassword ? 1 : 0,
channel.IsTemporary ? 1 : 0
entry.Name,
entry.HasPassword ? 1 : 0,
entry.IsTemporary ? 1 : 0
);
return sb.ToString();

View file

@ -8,14 +8,9 @@
}
public class ContextClearPacket : ServerPacket {
public ChatChannel Channel { get; private set; }
public ContextClearMode Mode { get; private set; }
private readonly ContextClearMode Mode;
public bool IsGlobal
=> Channel == null;
public ContextClearPacket(ChatChannel channel, ContextClearMode mode) {
Channel = channel;
public ContextClearPacket(ContextClearMode mode) {
Mode = mode;
}

View file

@ -3,9 +3,10 @@ using System;
using System.Text;
namespace SharpChat.Packet {
// this entire class is disgusting
public class ContextMessagePacket : ServerPacket {
public StoredEventInfo Event { get; private set; }
public bool Notify { get; private set; }
private readonly StoredEventInfo Event;
private readonly bool Notify;
public ContextMessagePacket(StoredEventInfo evt, bool notify = false) {
Event = evt ?? throw new ArgumentNullException(nameof(evt));

View file

@ -1,35 +1,35 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace SharpChat.Packet {
public class ContextUsersPacket : ServerPacket {
public IEnumerable<ChatUser> Users { get; private set; }
public record ListEntry(long Id, string Name, ChatColour Colour, int Rank, ChatUserPermissions Perms, bool Visible);
public ContextUsersPacket(IEnumerable<ChatUser> users) {
Users = users?.Where(u => u != null) ?? throw new ArgumentNullException(nameof(users));
private readonly ListEntry[] Entries;
public ContextUsersPacket(ListEntry[] entries) {
Entries = entries ?? throw new ArgumentNullException(nameof(entries));
}
public override string Pack() {
StringBuilder sb = new();
sb.AppendFormat("7\t0\t{0}", Users.Count());
sb.AppendFormat("7\t0\t{0}", Entries.Length);
foreach(ChatUser user in Users)
foreach(ListEntry entry in Entries)
sb.AppendFormat(
"\t{0}\t{1}\t{2}\t{3} {4} {5} {6} {7}\t{8}",
user.UserId,
user.LegacyNameWithStatus,
user.Colour,
user.Rank,
user.Can(ChatUserPermissions.KickUser) ? 1 : 0,
user.Can(ChatUserPermissions.ViewLogs) ? 1 : 0,
user.Can(ChatUserPermissions.SetOwnNickname) ? 1 : 0,
user.Can(ChatUserPermissions.CreateChannel | ChatUserPermissions.SetChannelPermanent, true) ? 2 : (
user.Can(ChatUserPermissions.CreateChannel) ? 1 : 0
),
1 // visibility flag
entry.Id,
entry.Name,
entry.Colour,
entry.Rank,
entry.Perms.HasFlag(ChatUserPermissions.KickUser) ? 1 : 0,
entry.Perms.HasFlag(ChatUserPermissions.ViewLogs) ? 1 : 0,
entry.Perms.HasFlag(ChatUserPermissions.SetOwnNickname) ? 1 : 0,
entry.Perms.HasFlag(ChatUserPermissions.CreateChannel) ? (
entry.Perms.HasFlag(ChatUserPermissions.SetChannelPermanent) ? 2 : 1
) : 0,
entry.Visible ? 1 : 0
);
return sb.ToString();

View file

@ -2,17 +2,21 @@
namespace SharpChat.Packet {
public class ForceDisconnectPacket : ServerPacket {
public DateTimeOffset? Expires { get; private set; }
private readonly DateTimeOffset Expires;
public ForceDisconnectPacket(DateTimeOffset? expires = null) {
public ForceDisconnectPacket() {
Expires = DateTimeOffset.MinValue;
}
public ForceDisconnectPacket(DateTimeOffset expires) {
Expires = expires;
}
public override string Pack() {
if(Expires.HasValue)
if(Expires == DateTimeOffset.MinValue)
return string.Format(
"9\t1\t{0}",
Expires.Value.Year >= 2100 ? -1 : Expires.Value.ToUnixTimeSeconds()
Expires.Year >= 2100 ? -1 : Expires.ToUnixTimeSeconds()
);
return "9\t0";

View file

@ -1,13 +1,11 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace SharpChat.Packet {
public class LegacyCommandResponse : ServerPacket {
public bool IsError { get; private set; }
public string StringId { get; private set; }
public IEnumerable<object> Arguments { get; private set; }
private readonly bool IsError;
private readonly string StringId;
private readonly object[] Arguments;
public LegacyCommandResponse(
string stringId,
@ -39,9 +37,8 @@ namespace SharpChat.Packet {
StringId == LCR.WELCOME ? LCR.BROADCAST : StringId
);
if(Arguments?.Any() == true)
foreach(object arg in Arguments)
sb.AppendFormat("\f{0}", arg);
foreach(object arg in Arguments)
sb.AppendFormat("\f{0}", arg);
sb.Append('\t');

View file

@ -2,14 +2,14 @@
namespace SharpChat.Packet {
public class UserChannelForceJoinPacket : ServerPacket {
public ChatChannel Channel { get; private set; }
private readonly string ChannelName;
public UserChannelForceJoinPacket(ChatChannel channel) {
Channel = channel ?? throw new ArgumentNullException(nameof(channel));
public UserChannelForceJoinPacket(string channelName) {
ChannelName = channelName ?? throw new ArgumentNullException(nameof(channelName));
}
public override string Pack() {
return string.Format("5\t2\t{0}", Channel.Name);
return string.Format("5\t2\t{0}", ChannelName);
}
}
}

View file

@ -2,25 +2,39 @@
namespace SharpChat.Packet {
public class UserChannelJoinPacket : ServerPacket {
public ChatUser User { get; private set; }
private readonly long UserId;
private readonly string UserName;
private readonly ChatColour UserColour;
private readonly int UserRank;
private readonly ChatUserPermissions UserPerms;
public UserChannelJoinPacket(ChatUser user) {
User = user ?? throw new ArgumentNullException(nameof(user));
public UserChannelJoinPacket(
long userId,
string userName,
ChatColour userColour,
int userRank,
ChatUserPermissions userPerms
) {
UserId = userId;
UserName = userName ?? throw new ArgumentNullException(nameof(userName));
UserColour = userColour;
UserRank = userRank;
UserPerms = userPerms;
}
public override string Pack() {
return string.Format(
"5\t0\t{0}\t{1}\t{2}\t{3} {4} {5} {6} {7}\t{8}",
User.UserId,
User.LegacyNameWithStatus,
User.Colour,
User.Rank,
User.Can(ChatUserPermissions.KickUser) ? 1 : 0,
User.Can(ChatUserPermissions.ViewLogs) ? 1 : 0,
User.Can(ChatUserPermissions.SetOwnNickname) ? 1 : 0,
User.Can(ChatUserPermissions.CreateChannel | ChatUserPermissions.SetChannelPermanent, true) ? 2 : (
User.Can(ChatUserPermissions.CreateChannel) ? 1 : 0
),
UserId,
UserName,
UserColour,
UserRank,
UserPerms.HasFlag(ChatUserPermissions.KickUser) ? 1 : 0,
UserPerms.HasFlag(ChatUserPermissions.ViewLogs) ? 1 : 0,
UserPerms.HasFlag(ChatUserPermissions.SetOwnNickname) ? 1 : 0,
UserPerms.HasFlag(ChatUserPermissions.CreateChannel) ? (
UserPerms.HasFlag(ChatUserPermissions.SetChannelPermanent) ? 2 : 1
) : 0,
SequenceId
);
}

View file

@ -1,15 +1,13 @@
using System;
namespace SharpChat.Packet {
namespace SharpChat.Packet {
public class UserChannelLeavePacket : ServerPacket {
public ChatUser User { get; private set; }
private readonly long UserId;
public UserChannelLeavePacket(ChatUser user) {
User = user ?? throw new ArgumentNullException(nameof(user));
public UserChannelLeavePacket(long userId) {
UserId = userId;
}
public override string Pack() {
return string.Format("5\t1\t{0}\t{1}", User.UserId, SequenceId);
return string.Format("5\t1\t{0}\t{1}", UserId, SequenceId);
}
}
}

View file

@ -2,28 +2,43 @@
namespace SharpChat.Packet {
public class UserConnectPacket : ServerPacket {
public DateTimeOffset Joined { get; private set; }
public ChatUser User { get; private set; }
private readonly DateTimeOffset Joined;
private readonly long UserId;
private readonly string UserName;
private readonly ChatColour UserColour;
private readonly int UserRank;
private readonly ChatUserPermissions UserPerms;
public UserConnectPacket(DateTimeOffset joined, ChatUser user) {
public UserConnectPacket(
DateTimeOffset joined,
long userId,
string userName,
ChatColour userColour,
int userRank,
ChatUserPermissions userPerms
) {
Joined = joined;
User = user ?? throw new ArgumentNullException(nameof(user));
UserId = userId;
UserName = userName ?? throw new ArgumentNullException(nameof(userName));
UserColour = userColour;
UserRank = userRank;
UserPerms = userPerms;
}
public override string Pack() {
return string.Format(
"1\t{0}\t{1}\t{2}\t{3}\t{4} {5} {6} {7} {8}\t{9}",
Joined.ToUnixTimeSeconds(),
User.UserId,
User.LegacyNameWithStatus,
User.Colour,
User.Rank,
User.Can(ChatUserPermissions.KickUser) ? 1 : 0,
User.Can(ChatUserPermissions.ViewLogs) ? 1 : 0,
User.Can(ChatUserPermissions.SetOwnNickname) ? 1 : 0,
User.Can(ChatUserPermissions.CreateChannel | ChatUserPermissions.SetChannelPermanent, true) ? 2 : (
User.Can(ChatUserPermissions.CreateChannel) ? 1 : 0
),
UserId,
UserName,
UserColour,
UserRank,
UserPerms.HasFlag(ChatUserPermissions.KickUser) ? 1 : 0,
UserPerms.HasFlag(ChatUserPermissions.ViewLogs) ? 1 : 0,
UserPerms.HasFlag(ChatUserPermissions.SetOwnNickname) ? 1 : 0,
UserPerms.HasFlag(ChatUserPermissions.CreateChannel) ? (
UserPerms.HasFlag(ChatUserPermissions.SetChannelPermanent) ? 2 : 1
) : 0,
SequenceId
);
}

View file

@ -9,21 +9,28 @@ namespace SharpChat.Packet {
}
public class UserDisconnectPacket : ServerPacket {
public DateTimeOffset Disconnected { get; private set; }
public ChatUser User { get; private set; }
public UserDisconnectReason Reason { get; private set; }
private readonly DateTimeOffset Disconnected;
private readonly long UserId;
private readonly string UserName;
private readonly UserDisconnectReason Reason;
public UserDisconnectPacket(DateTimeOffset disconnected, ChatUser user, UserDisconnectReason reason) {
public UserDisconnectPacket(
DateTimeOffset disconnected,
long userId,
string userName,
UserDisconnectReason reason
) {
Disconnected = disconnected;
User = user ?? throw new ArgumentNullException(nameof(user));
UserId = userId;
UserName = userName ?? throw new ArgumentNullException(nameof(userName));
Reason = reason;
}
public override string Pack() {
return string.Format(
"3\t{0}\t{1}\t{2}\t{3}\t{4}",
User.UserId,
User.LegacyNameWithStatus,
UserId,
UserName,
Reason switch {
UserDisconnectReason.Leave => "leave",
UserDisconnectReason.TimeOut => "timeout",

View file

@ -2,9 +2,9 @@
namespace SharpChat.Packet {
public class UserUpdateNotificationPacket : ServerPacket {
public string PreviousName { get; private set; }
public string NewName { get; private set; }
public DateTimeOffset Timestamp { get; }
private readonly string PreviousName;
private readonly string NewName;
private readonly DateTimeOffset Timestamp;
public UserUpdateNotificationPacket(string previousName, string newName) {
PreviousName = previousName ?? throw new ArgumentNullException(nameof(previousName));

View file

@ -2,25 +2,39 @@
namespace SharpChat.Packet {
public class UserUpdatePacket : ServerPacket {
public ChatUser User { get; private set; }
private readonly long UserId;
private readonly string UserName;
private readonly ChatColour UserColour;
private readonly int UserRank;
private readonly ChatUserPermissions UserPerms;
public UserUpdatePacket(ChatUser user) {
User = user ?? throw new ArgumentNullException(nameof(user));
public UserUpdatePacket(
long userId,
string userName,
ChatColour userColour,
int userRank,
ChatUserPermissions userPerms
) {
UserId = userId;
UserName = userName ?? throw new ArgumentNullException(nameof(userName));
UserColour = userColour;
UserRank = userRank;
UserPerms = userPerms;
}
public override string Pack() {
return string.Format(
"10\t{0}\t{1}\t{2}\t{3} {4} {5} {6} {7}",
User.UserId,
User.LegacyNameWithStatus,
User.Colour,
User.Rank,
User.Can(ChatUserPermissions.KickUser) ? 1 : 0,
User.Can(ChatUserPermissions.ViewLogs) ? 1 : 0,
User.Can(ChatUserPermissions.SetOwnNickname) ? 1 : 0,
User.Can(ChatUserPermissions.CreateChannel | ChatUserPermissions.SetChannelPermanent, true) ? 2 : (
User.Can(ChatUserPermissions.CreateChannel) ? 1 : 0
)
UserId,
UserName,
UserColour,
UserRank,
UserPerms.HasFlag(ChatUserPermissions.KickUser) ? 1 : 0,
UserPerms.HasFlag(ChatUserPermissions.ViewLogs) ? 1 : 0,
UserPerms.HasFlag(ChatUserPermissions.SetOwnNickname) ? 1 : 0,
UserPerms.HasFlag(ChatUserPermissions.CreateChannel) ? (
UserPerms.HasFlag(ChatUserPermissions.SetChannelPermanent) ? 2 : 1
) : 0
);
}
}

View file

@ -93,7 +93,7 @@ namespace SharpChat.PacketHandlers {
if(fbi.IsBanned && !fbi.HasExpired) {
Logger.Write($"<{ctx.Connection.Id}> User is banned.");
ctx.Connection.Send(new AuthFailPacket(AuthFailReason.Banned, fbi));
ctx.Connection.Send(new AuthFailPacket(fbi.ExpiresAt));
ctx.Connection.Dispose();
return;
}