Simplified packet building.

This commit is contained in:
flash 2024-05-10 17:28:52 +00:00
parent 1ba94a526c
commit 356409eb16
29 changed files with 234 additions and 431 deletions

4
.editorconfig Normal file
View file

@ -0,0 +1,4 @@
[*.{cs,vb}]
# IDE0046: Convert to conditional expression
dotnet_style_prefer_conditional_expression_over_return = false

View file

@ -127,7 +127,7 @@ Response to client packet `0`: Ping.
<table> <table>
<tr> <tr>
<td><code>string</code></td> <td><code>string</code></td>
<td>Any arbitrary string, do not rely on the data sent here. Original Sock Chat server sent <code>pong</code>, SharpChat currently sends the current Unix epoch timestamp in seconds.</td> <td>A string containing <code>pong</code>. Previously SharpChat sent the current Unix timestamp here, but has since been updated to conform to the Original Sock Chat server formatting.</td>
</tr> </tr>
</table> </table>

View file

@ -7,6 +7,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SharpChat", "SharpChat\Shar
EndProject EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{DF7A7073-A67A-4D93-92C6-F9D0F95E2359}" Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{DF7A7073-A67A-4D93-92C6-F9D0F95E2359}"
ProjectSection(SolutionItems) = preProject ProjectSection(SolutionItems) = preProject
.editorconfig = .editorconfig
.gitattributes = .gitattributes .gitattributes = .gitattributes
.gitignore = .gitignore .gitignore = .gitignore
LICENSE = LICENSE LICENSE = LICENSE

View file

@ -1,6 +1,5 @@
using System; using System;
using System.Linq; using System.Linq;
using System.Text;
namespace SharpChat { namespace SharpChat {
public class ChatChannel { public class ChatChannel {
@ -35,18 +34,6 @@ namespace SharpChat {
OwnerId = ownerId; OwnerId = ownerId;
} }
public string Pack() {
StringBuilder sb = new();
sb.Append(Name);
sb.Append('\t');
sb.Append(string.IsNullOrEmpty(Password) ? '0' : '1');
sb.Append('\t');
sb.Append(IsTemporary ? '1' : '0');
return sb.ToString();
}
public bool NameEquals(string name) { public bool NameEquals(string name) {
return string.Equals(name, Name, StringComparison.InvariantCultureIgnoreCase); return string.Equals(name, Name, StringComparison.InvariantCultureIgnoreCase);
} }

View file

@ -199,9 +199,9 @@ namespace SharpChat {
public void BanUser(ChatUser user, TimeSpan duration, UserDisconnectReason reason = UserDisconnectReason.Kicked) { public void BanUser(ChatUser user, TimeSpan duration, UserDisconnectReason reason = UserDisconnectReason.Kicked) {
if(duration > TimeSpan.Zero) { if(duration > TimeSpan.Zero) {
DateTimeOffset expires = duration >= TimeSpan.MaxValue ? DateTimeOffset.MaxValue : DateTimeOffset.Now + duration; DateTimeOffset expires = duration >= TimeSpan.MaxValue ? DateTimeOffset.MaxValue : DateTimeOffset.Now + duration;
SendTo(user, new ForceDisconnectPacket(ForceDisconnectReason.Banned, expires)); SendTo(user, new ForceDisconnectPacket(expires));
} else } else
SendTo(user, new ForceDisconnectPacket(ForceDisconnectReason.Kicked)); SendTo(user, new ForceDisconnectPacket());
foreach(ChatConnection conn in Connections) foreach(ChatConnection conn in Connections)
if(conn.User == user) if(conn.User == user)

View file

@ -51,6 +51,7 @@ namespace SharpChat {
NickName = nickName ?? string.Empty; NickName = nickName ?? string.Empty;
Status = status; Status = status;
StatusText = statusText ?? string.Empty; StatusText = statusText ?? string.Empty;
IsSuper = isSuper;
} }
public bool Can(ChatUserPermissions perm, bool strict = false) { public bool Can(ChatUserPermissions perm, bool strict = false) {
@ -58,30 +59,6 @@ namespace SharpChat {
return strict ? perms == perm : perms > 0; return strict ? perms == perm : perms > 0;
} }
public string Pack() {
StringBuilder sb = new();
sb.Append(UserId);
sb.Append('\t');
sb.Append(LegacyNameWithStatus);
sb.Append('\t');
sb.Append(Colour);
sb.Append('\t');
sb.Append(Rank);
sb.Append(' ');
sb.Append(Can(ChatUserPermissions.KickUser) ? '1' : '0');
sb.Append(' ');
sb.Append(Can(ChatUserPermissions.ViewLogs) ? '1' : '0');
sb.Append(' ');
sb.Append(Can(ChatUserPermissions.SetOwnNickname) ? '1' : '0');
sb.Append(' ');
sb.Append(Can(ChatUserPermissions.CreateChannel | ChatUserPermissions.SetChannelPermanent, true) ? '2' : (
Can(ChatUserPermissions.CreateChannel) ? '1' : '0'
));
return sb.ToString();
}
public bool NameEquals(string name) { public bool NameEquals(string name) {
return string.Equals(name, UserName, StringComparison.InvariantCultureIgnoreCase) return string.Equals(name, UserName, StringComparison.InvariantCultureIgnoreCase)
|| string.Equals(name, NickName, StringComparison.InvariantCultureIgnoreCase) || string.Equals(name, NickName, StringComparison.InvariantCultureIgnoreCase)

View file

@ -1,6 +1,5 @@
using SharpChat.Misuzu; using SharpChat.Misuzu;
using System; using System;
using System.Text;
namespace SharpChat.Packet { namespace SharpChat.Packet {
public enum AuthFailReason { public enum AuthFailReason {
@ -21,34 +20,17 @@ namespace SharpChat.Packet {
} }
public override string Pack() { public override string Pack() {
StringBuilder sb = new(); string packet = string.Format("1\tn\t{0}fail", Reason switch {
AuthFailReason.AuthInvalid => "auth",
AuthFailReason.MaxSessions => "sock",
AuthFailReason.Banned => "join",
_ => "user",
});
sb.Append('1'); if(Reason == AuthFailReason.Banned)
sb.Append("\tn\t"); packet += string.Format("\t{0}", BanInfo.IsPermanent ? -1 : BanInfo.ExpiresAt.ToUnixTimeSeconds());
switch(Reason) { return packet;
case AuthFailReason.AuthInvalid:
default:
sb.Append("authfail");
break;
case AuthFailReason.MaxSessions:
sb.Append("sockfail");
break;
case AuthFailReason.Banned:
sb.Append("joinfail");
break;
}
if(Reason == AuthFailReason.Banned) {
sb.Append('\t');
if(BanInfo.IsPermanent)
sb.Append("-1");
else
sb.Append(BanInfo.ExpiresAt.ToUnixTimeSeconds());
}
return sb.ToString();
} }
} }
} }

View file

@ -1,5 +1,4 @@
using System; using System;
using System.Text;
namespace SharpChat.Packet { namespace SharpChat.Packet {
public class AuthSuccessPacket : ServerPacket { public class AuthSuccessPacket : ServerPacket {
@ -21,17 +20,21 @@ namespace SharpChat.Packet {
} }
public override string Pack() { public override string Pack() {
StringBuilder sb = new(); return string.Format(
"1\ty\t{0}\t{1}\t{2}\t{3} {4} {5} {6} {7}\t{8}\t{9}",
sb.Append('1'); User.UserId,
sb.Append("\ty\t"); User.LegacyNameWithStatus,
sb.Append(User.Pack()); User.Colour,
sb.Append('\t'); User.Rank,
sb.Append(Channel.Name); User.Can(ChatUserPermissions.KickUser) ? 1 : 0,
sb.Append('\t'); User.Can(ChatUserPermissions.ViewLogs) ? 1 : 0,
sb.Append(MaxMessageLength); User.Can(ChatUserPermissions.SetOwnNickname) ? 1 : 0,
User.Can(ChatUserPermissions.CreateChannel | ChatUserPermissions.SetChannelPermanent, true) ? 2 : (
return sb.ToString(); User.Can(ChatUserPermissions.CreateChannel) ? 1 : 0
),
Channel.Name,
MaxMessageLength
);
} }
} }
} }

View file

@ -15,10 +15,7 @@ namespace SharpChat.Packet {
public override string Pack() { public override string Pack() {
StringBuilder sb = new(); StringBuilder sb = new();
sb.Append('2'); sb.AppendFormat("2\t{0}\t-1\t0\fbanlist\f", DateTimeOffset.Now.ToUnixTimeSeconds());
sb.Append('\t');
sb.Append(DateTimeOffset.Now.ToUnixTimeSeconds());
sb.Append("\t-1\t0\fbanlist\f");
foreach(MisuzuBanInfo ban in Bans) { foreach(MisuzuBanInfo ban in Bans) {
string banStr = string.IsNullOrEmpty(ban.UserName) ? ban.RemoteAddress : ban.UserName; string banStr = string.IsNullOrEmpty(ban.UserName) ? ban.RemoteAddress : ban.UserName;
@ -28,9 +25,7 @@ namespace SharpChat.Packet {
if(Bans.Any()) if(Bans.Any())
sb.Length -= 2; sb.Length -= 2;
sb.Append('\t'); sb.AppendFormat("\t{0}\t10010", SequenceId);
sb.Append(SequenceId);
sb.Append("\t10010");
return sb.ToString(); return sb.ToString();
} }

View file

@ -1,6 +1,4 @@
using System.Text; namespace SharpChat.Packet {
namespace SharpChat.Packet {
public class ChannelCreatePacket : ServerPacket { public class ChannelCreatePacket : ServerPacket {
public ChatChannel Channel { get; private set; } public ChatChannel Channel { get; private set; }
@ -9,15 +7,12 @@ namespace SharpChat.Packet {
} }
public override string Pack() { public override string Pack() {
StringBuilder sb = new(); return string.Format(
"4\t0\t{0}\t{1}\t{2}",
sb.Append('4'); Channel.Name,
sb.Append('\t'); Channel.HasPassword ? 1 : 0,
sb.Append('0'); Channel.IsTemporary ? 1 : 0
sb.Append('\t'); );
sb.Append(Channel.Pack());
return sb.ToString();
} }
} }
} }

View file

@ -1,5 +1,4 @@
using System; using System;
using System.Text;
namespace SharpChat.Packet { namespace SharpChat.Packet {
public class ChannelDeletePacket : ServerPacket { public class ChannelDeletePacket : ServerPacket {
@ -10,15 +9,7 @@ namespace SharpChat.Packet {
} }
public override string Pack() { public override string Pack() {
StringBuilder sb = new(); return string.Format("4\t2\t{0}", Channel.Name);
sb.Append('4');
sb.Append('\t');
sb.Append('2');
sb.Append('\t');
sb.Append(Channel.Name);
return sb.ToString();
} }
} }
} }

View file

@ -1,6 +1,4 @@
using System.Text; namespace SharpChat.Packet {
namespace SharpChat.Packet {
public class ChannelUpdatePacket : ServerPacket { public class ChannelUpdatePacket : ServerPacket {
public string PreviousName { get; private set; } public string PreviousName { get; private set; }
public ChatChannel Channel { get; private set; } public ChatChannel Channel { get; private set; }
@ -11,17 +9,13 @@ namespace SharpChat.Packet {
} }
public override string Pack() { public override string Pack() {
StringBuilder sb = new(); return string.Format(
"4\t1\t{0}\t{1}\t{2}\t{3}",
sb.Append('4'); PreviousName,
sb.Append('\t'); Channel.Name,
sb.Append('1'); Channel.HasPassword ? 1 : 0,
sb.Append('\t'); Channel.IsTemporary ? 1 : 0
sb.Append(PreviousName); );
sb.Append('\t');
sb.Append(Channel.Pack());
return sb.ToString();
} }
} }
} }

View file

@ -1,5 +1,4 @@
using System; using System;
using System.Text;
namespace SharpChat.Packet { namespace SharpChat.Packet {
public class ChatMessageAddPacket : ServerPacket { public class ChatMessageAddPacket : ServerPacket {
@ -25,40 +24,22 @@ namespace SharpChat.Packet {
} }
public override string Pack() { public override string Pack() {
StringBuilder sb = new(); string body = Text.Replace("<", "&lt;").Replace(">", "&gt;").Replace("\n", " <br/> ").Replace("\t", " ");
sb.Append('2');
sb.Append('\t');
sb.Append(Created.ToUnixTimeSeconds());
sb.Append('\t');
sb.Append(UserId);
sb.Append('\t');
if(IsAction) if(IsAction)
sb.Append("<i>"); body = string.Format("<i>{0}</i>", body);
sb.Append( return string.Format(
Text.Replace("<", "&lt;") "2\t{0}\t{1}\t{2}\t{3}\t{4}{5}{6}{7}{8}",
.Replace(">", "&gt;") Created.ToUnixTimeSeconds(),
.Replace("\n", " <br/> ") UserId,
.Replace("\t", " ") body,
SequenceId,
1,
IsAction ? 1 : 0,
0,
IsAction ? 0 : 1,
IsPrivate ? 1 : 0
); );
if(IsAction)
sb.Append("</i>");
sb.Append('\t');
sb.Append(SequenceId);
sb.AppendFormat(
"\t1{0}0{1}{2}",
IsAction ? '1' : '0',
IsAction ? '0' : '1',
IsPrivate ? '1' : '0'
);
return sb.ToString();
} }
} }
} }

View file

@ -1,6 +1,4 @@
using System.Text; namespace SharpChat.Packet {
namespace SharpChat.Packet {
public class ChatMessageDeletePacket : ServerPacket { public class ChatMessageDeletePacket : ServerPacket {
public long EventId { get; private set; } public long EventId { get; private set; }
@ -9,13 +7,7 @@ namespace SharpChat.Packet {
} }
public override string Pack() { public override string Pack() {
StringBuilder sb = new(); return string.Format("6\t{0}", EventId);
sb.Append('6');
sb.Append('\t');
sb.Append(EventId);
return sb.ToString();
} }
} }
} }

View file

@ -14,16 +14,15 @@ namespace SharpChat.Packet {
public override string Pack() { public override string Pack() {
StringBuilder sb = new(); StringBuilder sb = new();
sb.Append('7'); sb.AppendFormat("7\t2\t{0}", Channels.Count());
sb.Append('\t');
sb.Append('2');
sb.Append('\t');
sb.Append(Channels.Count());
foreach(ChatChannel channel in Channels) { foreach(ChatChannel channel in Channels)
sb.Append('\t'); sb.AppendFormat(
sb.Append(channel.Pack()); "\t{0}\t{1}\t{2}",
} channel.Name,
channel.HasPassword ? 1 : 0,
channel.IsTemporary ? 1 : 0
);
return sb.ToString(); return sb.ToString();
} }

View file

@ -1,6 +1,4 @@
using System.Text; namespace SharpChat.Packet {
namespace SharpChat.Packet {
public enum ContextClearMode { public enum ContextClearMode {
Messages = 0, Messages = 0,
Users = 1, Users = 1,
@ -22,13 +20,7 @@ namespace SharpChat.Packet {
} }
public override string Pack() { public override string Pack() {
StringBuilder sb = new(); return string.Format("8\t{0}", (int)Mode);
sb.Append('8');
sb.Append('\t');
sb.Append((int)Mode);
return sb.ToString();
} }
} }
} }

View file

@ -12,7 +12,7 @@ namespace SharpChat.Packet {
Notify = notify; Notify = notify;
} }
private const string V1_CHATBOT = "-1\tChatBot\tinherit\t\t"; private const string V1_CHATBOT = "-1\tChatBot\tinherit\t";
public override string Pack() { public override string Pack() {
bool isAction = Event.Flags.HasFlag(StoredEventFlags.Action); bool isAction = Event.Flags.HasFlag(StoredEventFlags.Action);
@ -21,95 +21,82 @@ namespace SharpChat.Packet {
StringBuilder sb = new(); StringBuilder sb = new();
sb.Append('7'); sb.AppendFormat("7\t1\t{0}\t", Event.Created.ToUnixTimeSeconds());
sb.Append('\t');
sb.Append('1');
sb.Append('\t');
sb.Append(Event.Created.ToUnixTimeSeconds());
sb.Append('\t');
switch(Event.Type) { switch(Event.Type) {
case "msg:add": case "msg:add":
case "SharpChat.Events.ChatMessage": case "SharpChat.Events.ChatMessage":
if(isBroadcast) { if(isBroadcast) {
sb.Append(V1_CHATBOT); sb.Append(V1_CHATBOT);
sb.Append("0\fsay\f");
} else { } else {
sb.Append(Event.Sender.Pack()); sb.AppendFormat(
sb.Append('\t'); "{0}\t{1}\t{2}\t{3} {4} {5} {6} {7}",
Event.Sender.UserId,
Event.Sender.LegacyNameWithStatus,
Event.Sender.Colour,
Event.Sender.Rank,
Event.Sender.Can(ChatUserPermissions.KickUser) ? 1 : 0,
Event.Sender.Can(ChatUserPermissions.ViewLogs) ? 1 : 0,
Event.Sender.Can(ChatUserPermissions.SetOwnNickname) ? 1 : 0,
Event.Sender.Can(ChatUserPermissions.CreateChannel | ChatUserPermissions.SetChannelPermanent, true) ? 2 : (
Event.Sender.Can(ChatUserPermissions.CreateChannel) ? 1 : 0
)
);
} }
if(isAction) sb.Append('\t');
sb.Append("<i>");
sb.Append( if(isBroadcast)
Event.Data.RootElement.GetProperty("text").GetString() sb.Append("0\fsay\f");
.Replace("<", "&lt;")
.Replace(">", "&gt;")
.Replace("\n", " <br/> ")
.Replace("\t", " ")
);
string body = Event.Data.RootElement.GetProperty("text").GetString().Replace("<", "&lt;").Replace(">", "&gt;").Replace("\n", " <br/> ").Replace("\t", " ");
if(isAction) if(isAction)
sb.Append("</i>"); body = string.Format("<i>{0}</i>", body);
sb.Append(body);
break; break;
case "user:connect": case "user:connect":
case "SharpChat.Events.UserConnectEvent": case "SharpChat.Events.UserConnectEvent":
sb.Append(V1_CHATBOT); sb.AppendFormat("{0}\t0\fjoin\f{1}", V1_CHATBOT, Event.Sender.LegacyName);
sb.Append("0\fjoin\f");
sb.Append(Event.Sender.LegacyName);
break; break;
case "chan:join": case "chan:join":
case "SharpChat.Events.UserChannelJoinEvent": case "SharpChat.Events.UserChannelJoinEvent":
sb.Append(V1_CHATBOT); sb.AppendFormat("{0}\t0\fjchan\f{1}", V1_CHATBOT, Event.Sender.LegacyName);
sb.Append("0\fjchan\f");
sb.Append(Event.Sender.LegacyName);
break; break;
case "chan:leave": case "chan:leave":
case "SharpChat.Events.UserChannelLeaveEvent": case "SharpChat.Events.UserChannelLeaveEvent":
sb.Append(V1_CHATBOT); sb.AppendFormat("{0}\t0\flchan\f{1}", V1_CHATBOT, Event.Sender.LegacyName);
sb.Append("0\flchan\f");
sb.Append(Event.Sender.LegacyName);
break; break;
case "user:disconnect": case "user:disconnect":
case "SharpChat.Events.UserDisconnectEvent": case "SharpChat.Events.UserDisconnectEvent":
sb.Append(V1_CHATBOT); sb.AppendFormat(
sb.Append("0\f"); "{0}\t0\f{1}\f{2}",
V1_CHATBOT,
switch((UserDisconnectReason)Event.Data.RootElement.GetProperty("reason").GetByte()) { (UserDisconnectReason)Event.Data.RootElement.GetProperty("reason").GetByte() switch {
case UserDisconnectReason.Flood: UserDisconnectReason.Flood => "flood",
sb.Append("flood"); UserDisconnectReason.Kicked => "kick",
break; UserDisconnectReason.TimeOut => "timeout",
case UserDisconnectReason.Kicked: UserDisconnectReason.Leave => "leave",
sb.Append("kick"); _ => "leave",
break; },
case UserDisconnectReason.TimeOut: Event.Sender.LegacyName
sb.Append("timeout"); );
break;
case UserDisconnectReason.Leave:
default:
sb.Append("leave");
break;
}
sb.Append('\f');
sb.Append(Event.Sender.LegacyName);
break; break;
} }
sb.Append('\t');
sb.Append(Event.Id < 1 ? SequenceId : Event.Id);
sb.Append('\t');
sb.Append(Notify ? '1' : '0');
sb.AppendFormat( sb.AppendFormat(
"\t1{0}0{1}{2}", "\t{0}\t{1}\t{2}{3}{4}{5}{6}",
isAction ? '1' : '0', Event.Id < 1 ? SequenceId : Event.Id,
isAction ? '0' : '1', Notify ? 1 : 0,
isPrivate ? '1' : '0' 1,
isAction ? 1 : 0,
0,
isAction ? 0 : 1,
isPrivate ? 1 : 0
); );
return sb.ToString(); return sb.ToString();

View file

@ -14,18 +14,23 @@ namespace SharpChat.Packet {
public override string Pack() { public override string Pack() {
StringBuilder sb = new(); StringBuilder sb = new();
sb.Append('7'); sb.AppendFormat("7\t0\t{0}", Users.Count());
sb.Append('\t');
sb.Append('0');
sb.Append('\t');
sb.Append(Users.Count());
foreach(ChatUser user in Users) { foreach(ChatUser user in Users)
sb.Append('\t'); sb.AppendFormat(
sb.Append(user.Pack()); "\t{0}\t{1}\t{2}\t{3} {4} {5} {6} {7}\t{8}",
sb.Append('\t'); user.UserId,
sb.Append('1'); // visibility flag 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
);
return sb.ToString(); return sb.ToString();
} }

View file

@ -1,42 +1,21 @@
using System; using System;
using System.Text;
namespace SharpChat.Packet { namespace SharpChat.Packet {
public enum ForceDisconnectReason {
Kicked = 0,
Banned = 1,
}
public class ForceDisconnectPacket : ServerPacket { public class ForceDisconnectPacket : ServerPacket {
public ForceDisconnectReason Reason { get; private set; } public DateTimeOffset? Expires { get; private set; }
public DateTimeOffset Expires { get; private set; }
public ForceDisconnectPacket(ForceDisconnectReason reason, DateTimeOffset? expires = null) { public ForceDisconnectPacket(DateTimeOffset? expires = null) {
Reason = reason; Expires = expires;
if(reason == ForceDisconnectReason.Banned) {
if(!expires.HasValue)
throw new ArgumentNullException(nameof(expires));
Expires = expires.Value;
}
} }
public override string Pack() { public override string Pack() {
StringBuilder sb = new(); if(Expires.HasValue)
return string.Format(
"9\t1\t{0}",
Expires.Value.Year >= 2100 ? -1 : Expires.Value.ToUnixTimeSeconds()
);
sb.Append('9'); return "9\t0";
sb.Append('\t');
sb.Append((int)Reason);
if(Reason == ForceDisconnectReason.Banned) {
sb.Append('\t');
if(Expires.Year >= 2100)
sb.Append("-1");
else
sb.Append(Expires.ToUnixTimeSeconds());
}
return sb.ToString();
} }
} }
} }

View file

@ -22,45 +22,35 @@ namespace SharpChat.Packet {
public override string Pack() { public override string Pack() {
StringBuilder sb = new(); StringBuilder sb = new();
if(StringId == LCR.WELCOME) { if(StringId == LCR.WELCOME)
sb.Append('7'); sb.AppendFormat(
sb.Append('\t'); "7\t1\t{0}\t-1\tChatBot\tinherit\t\t",
sb.Append('1'); DateTimeOffset.Now.ToUnixTimeSeconds()
sb.Append('\t'); );
sb.Append(DateTimeOffset.Now.ToUnixTimeSeconds()); else
sb.Append("\t-1\tChatBot\tinherit\t\t"); sb.AppendFormat(
} else { "2\t{0}\t-1\t",
sb.Append('2'); DateTimeOffset.Now.ToUnixTimeSeconds()
sb.Append('\t'); );
sb.Append(DateTimeOffset.Now.ToUnixTimeSeconds());
sb.Append("\t-1\t");
}
sb.Append(IsError ? '1' : '0'); sb.AppendFormat(
sb.Append('\f'); "{0}\f{1}",
sb.Append(StringId == LCR.WELCOME ? LCR.BROADCAST : StringId); IsError ? 1 : 0,
StringId == LCR.WELCOME ? LCR.BROADCAST : StringId
);
if(Arguments?.Any() == true) if(Arguments?.Any() == true)
foreach(object arg in Arguments) { foreach(object arg in Arguments)
sb.Append('\f'); sb.AppendFormat("\f{0}", arg);
sb.Append(arg);
}
sb.Append('\t'); sb.Append('\t');
if(StringId == LCR.WELCOME) { if(StringId == LCR.WELCOME)
sb.Append(StringId); sb.AppendFormat("{0}\t0", StringId);
sb.Append("\t0"); else
} else
sb.Append(SequenceId); sb.Append(SequenceId);
sb.Append("\t10010"); sb.Append("\t10010");
/*sb.AppendFormat(
"\t1{0}0{1}{2}",
Flags.HasFlag(ChatMessageFlags.Action) ? '1' : '0',
Flags.HasFlag(ChatMessageFlags.Action) ? '0' : '1',
Flags.HasFlag(ChatMessageFlags.Private) ? '1' : '0'
);*/
return sb.ToString(); return sb.ToString();
} }

View file

@ -1,22 +1,7 @@
using System; namespace SharpChat.Packet {
using System.Text;
namespace SharpChat.Packet {
public class PongPacket : ServerPacket { public class PongPacket : ServerPacket {
public DateTimeOffset PongTime { get; private set; }
public PongPacket(DateTimeOffset dto) {
PongTime = dto;
}
public override string Pack() { public override string Pack() {
StringBuilder sb = new(); return "0\tpong";
sb.Append('0');
sb.Append('\t');
sb.Append(PongTime.ToUnixTimeSeconds());
return sb.ToString();
} }
} }
} }

View file

@ -1,5 +1,4 @@
using System; using System;
using System.Text;
namespace SharpChat.Packet { namespace SharpChat.Packet {
public class UserChannelForceJoinPacket : ServerPacket { public class UserChannelForceJoinPacket : ServerPacket {
@ -10,15 +9,7 @@ namespace SharpChat.Packet {
} }
public override string Pack() { public override string Pack() {
StringBuilder sb = new(); return string.Format("5\t2\t{0}", Channel.Name);
sb.Append('5');
sb.Append('\t');
sb.Append('2');
sb.Append('\t');
sb.Append(Channel.Name);
return sb.ToString();
} }
} }
} }

View file

@ -1,5 +1,4 @@
using System; using System;
using System.Text;
namespace SharpChat.Packet { namespace SharpChat.Packet {
public class UserChannelJoinPacket : ServerPacket { public class UserChannelJoinPacket : ServerPacket {
@ -10,17 +9,20 @@ namespace SharpChat.Packet {
} }
public override string Pack() { public override string Pack() {
StringBuilder sb = new(); return string.Format(
"5\t0\t{0}\t{1}\t{2}\t{3} {4} {5} {6} {7}\t{8}",
sb.Append('5'); User.UserId,
sb.Append('\t'); User.LegacyNameWithStatus,
sb.Append('0'); User.Colour,
sb.Append('\t'); User.Rank,
sb.Append(User.Pack()); User.Can(ChatUserPermissions.KickUser) ? 1 : 0,
sb.Append('\t'); User.Can(ChatUserPermissions.ViewLogs) ? 1 : 0,
sb.Append(SequenceId); User.Can(ChatUserPermissions.SetOwnNickname) ? 1 : 0,
User.Can(ChatUserPermissions.CreateChannel | ChatUserPermissions.SetChannelPermanent, true) ? 2 : (
return sb.ToString(); User.Can(ChatUserPermissions.CreateChannel) ? 1 : 0
),
SequenceId
);
} }
} }
} }

View file

@ -1,5 +1,4 @@
using System; using System;
using System.Text;
namespace SharpChat.Packet { namespace SharpChat.Packet {
public class UserChannelLeavePacket : ServerPacket { public class UserChannelLeavePacket : ServerPacket {
@ -10,17 +9,7 @@ namespace SharpChat.Packet {
} }
public override string Pack() { public override string Pack() {
StringBuilder sb = new(); return string.Format("5\t1\t{0}\t{1}", User.UserId, SequenceId);
sb.Append('5');
sb.Append('\t');
sb.Append('1');
sb.Append('\t');
sb.Append(User.UserId);
sb.Append('\t');
sb.Append(SequenceId);
return sb.ToString();
} }
} }
} }

View file

@ -1,5 +1,4 @@
using System; using System;
using System.Text;
namespace SharpChat.Packet { namespace SharpChat.Packet {
public class UserConnectPacket : ServerPacket { public class UserConnectPacket : ServerPacket {
@ -12,17 +11,21 @@ namespace SharpChat.Packet {
} }
public override string Pack() { public override string Pack() {
StringBuilder sb = new(); return string.Format(
"1\t{0}\t{1}\t{2}\t{3}\t{4} {5} {6} {7} {8}\t{9}",
sb.Append('1'); Joined.ToUnixTimeSeconds(),
sb.Append('\t'); User.UserId,
sb.Append(Joined.ToUnixTimeSeconds()); User.LegacyNameWithStatus,
sb.Append('\t'); User.Colour,
sb.Append(User.Pack()); User.Rank,
sb.Append('\t'); User.Can(ChatUserPermissions.KickUser) ? 1 : 0,
sb.Append(SequenceId); User.Can(ChatUserPermissions.ViewLogs) ? 1 : 0,
User.Can(ChatUserPermissions.SetOwnNickname) ? 1 : 0,
return sb.ToString(); User.Can(ChatUserPermissions.CreateChannel | ChatUserPermissions.SetChannelPermanent, true) ? 2 : (
User.Can(ChatUserPermissions.CreateChannel) ? 1 : 0
),
SequenceId
);
} }
} }
} }

View file

@ -1,5 +1,4 @@
using System; using System;
using System.Text;
namespace SharpChat.Packet { namespace SharpChat.Packet {
public enum UserDisconnectReason { public enum UserDisconnectReason {
@ -21,37 +20,20 @@ namespace SharpChat.Packet {
} }
public override string Pack() { public override string Pack() {
StringBuilder sb = new(); return string.Format(
"3\t{0}\t{1}\t{2}\t{3}\t{4}",
sb.Append('3'); User.UserId,
sb.Append('\t'); User.LegacyNameWithStatus,
sb.Append(User.UserId); Reason switch {
sb.Append('\t'); UserDisconnectReason.Leave => "leave",
sb.Append(User.LegacyNameWithStatus); UserDisconnectReason.TimeOut => "timeout",
sb.Append('\t'); UserDisconnectReason.Kicked => "kick",
UserDisconnectReason.Flood => "flood",
switch(Reason) { _ => "leave",
case UserDisconnectReason.Leave: },
default: Disconnected.ToUnixTimeSeconds(),
sb.Append("leave"); SequenceId
break; );
case UserDisconnectReason.TimeOut:
sb.Append("timeout");
break;
case UserDisconnectReason.Kicked:
sb.Append("kick");
break;
case UserDisconnectReason.Flood:
sb.Append("flood");
break;
}
sb.Append('\t');
sb.Append(Disconnected.ToUnixTimeSeconds());
sb.Append('\t');
sb.Append(SequenceId);
return sb.ToString();
} }
} }
} }

View file

@ -1,5 +1,4 @@
using System; using System;
using System.Text;
namespace SharpChat.Packet { namespace SharpChat.Packet {
public class UserUpdateNotificationPacket : ServerPacket { public class UserUpdateNotificationPacket : ServerPacket {
@ -14,20 +13,13 @@ namespace SharpChat.Packet {
} }
public override string Pack() { public override string Pack() {
StringBuilder sb = new(); return string.Format(
"2\t{0}\t-1\t0\fnick\f{1}\f{2}\t{3}\t10010",
sb.Append('2'); Timestamp.ToUnixTimeSeconds(),
sb.Append('\t'); PreviousName,
sb.Append(Timestamp.ToUnixTimeSeconds()); NewName,
sb.Append("\t-1\t0\fnick\f"); SequenceId
sb.Append(PreviousName); );
sb.Append('\f');
sb.Append(NewName);
sb.Append('\t');
sb.Append(SequenceId);
sb.Append("\t10010");
return sb.ToString();
} }
} }
} }

View file

@ -1,5 +1,4 @@
using System; using System;
using System.Text;
namespace SharpChat.Packet { namespace SharpChat.Packet {
public class UserUpdatePacket : ServerPacket { public class UserUpdatePacket : ServerPacket {
@ -10,13 +9,19 @@ namespace SharpChat.Packet {
} }
public override string Pack() { public override string Pack() {
StringBuilder sb = new(); return string.Format(
"10\t{0}\t{1}\t{2}\t{3} {4} {5} {6} {7}",
sb.Append("10"); User.UserId,
sb.Append('\t'); User.LegacyNameWithStatus,
sb.Append(User.Pack()); User.Colour,
User.Rank,
return sb.ToString(); 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
)
);
} }
} }
} }

View file

@ -26,7 +26,7 @@ namespace SharpChat.PacketHandlers {
return; return;
ctx.Connection.BumpPing(); ctx.Connection.BumpPing();
ctx.Connection.Send(new PongPacket(ctx.Connection.LastPing)); ctx.Connection.Send(new PongPacket());
ctx.Chat.ContextAccess.Wait(); ctx.Chat.ContextAccess.Wait();
try { try {