Made packet handlers more readable.

This commit is contained in:
flash 2024-02-24 02:25:20 +00:00
parent 5b5ca888a4
commit 49f00b00d8

View file

@ -48,6 +48,8 @@ Umi.Protocol.SockChat.Protocol = function() {
let selfUserId, selfChannelName, selfPseudoChannelName; let selfUserId, selfChannelName, selfPseudoChannelName;
let lastPing, lastPong, pingTimer, pingWatcher; let lastPing, lastPong, pingTimer, pingWatcher;
const handlers = {};
const stopPingWatcher = () => { const stopPingWatcher = () => {
if(pingWatcher !== undefined) { if(pingWatcher !== undefined) {
clearTimeout(pingWatcher); clearTimeout(pingWatcher);
@ -64,18 +66,16 @@ Umi.Protocol.SockChat.Protocol = function() {
}, 2000); }, 2000);
}; };
const send = (opcode, data) => { const send = (...args) => {
if(sock === undefined) if(args.length < 1)
return; throw 'you must specify at least one argument as an opcode';
let msg = opcode; const pack = args.join("\t");
if(data)
msg += `\t${data.join("\t")}`;
if(dumpPackets) if(dumpPackets)
console.log(msg); console.log(pack);
sock.send(msg); sock?.send(pack);
}; };
const onSendPing = () => { const onSendPing = () => {
@ -90,7 +90,7 @@ Umi.Protocol.SockChat.Protocol = function() {
}; };
const sendAuth = args => { const sendAuth = args => {
if(selfUserId === undefined) if(selfUserId === undefined)
send('1', args); send('1', ...args);
}; };
const sendMessage = text => { const sendMessage = text => {
if(selfUserId === undefined) if(selfUserId === undefined)
@ -99,7 +99,7 @@ Umi.Protocol.SockChat.Protocol = function() {
if(text.substring(0, 1) !== '/' && selfPseudoChannelName !== undefined) if(text.substring(0, 1) !== '/' && selfPseudoChannelName !== undefined)
text = `/msg ${selfPseudoChannelName} ${text}`; text = `/msg ${selfPseudoChannelName} ${text}`;
send('2', [selfUserId, text]); send('2', selfUserId, text);
}; };
const startKeepAlive = () => sock?.sendInterval(`0\t${selfUserId}`, futami.get('ping') * 1000); const startKeepAlive = () => sock?.sendInterval(`0\t${selfUserId}`, futami.get('ping') * 1000);
@ -165,60 +165,54 @@ Umi.Protocol.SockChat.Protocol = function() {
}; };
const onMessage = ev => { const onMessage = ev => {
const data = ev.data.split("\t"); const args = ev.data.split("\t");
let handler = handlers;
if(dumpPackets) if(dumpPackets)
console.log(data); console.log(args);
switch(data[0]) { for(;;) {
case '0': // ping handler = handler[args.shift()];
if(handler === undefined)
break;
if(typeof handler === 'function') {
handler(...args);
break;
}
}
};
// pong handler
handlers['0'] = () => {
lastPong = Date.now(); lastPong = Date.now();
watchers.call('ping:recv', { watchers.call('ping:recv', {
ping: lastPing, ping: lastPing,
pong: lastPong, pong: lastPong,
diff: lastPong - lastPing, diff: lastPong - lastPing,
}); });
break; };
case '1': // join // join/auth
if(data[1] !== 'y' && data[1] !== 'n') { handlers['1'] = (successOrTimeStamp, userIdOrReason, userNameOrExpiry, userColour, userPerms, chanNameOrMsgId, maxLength) => {
watchers.call('user:add', { if(successOrTimeStamp === 'y') {
msg: { selfUserId = userIdOrReason;
id: data[6], selfChannelName = chanNameOrMsgId;
time: new Date(parseInt(data[1]) * 1000),
channel: selfChannelName,
botInfo: {
type: 'join',
args: [data[3]],
},
},
user: {
id: data[2],
self: data[2] === selfUserId,
name: data[3],
colour: parseUserColour(data[4]),
perms: parseUserPerms(data[5]),
permsRaw: data[5],
},
});
} else {
if(data[1] == 'y') {
selfUserId = data[2];
selfChannelName = data[6];
watchers.call('session:start', { watchers.call('session:start', {
wasConnected: wasConnected, wasConnected: wasConnected,
session: { success: true }, session: { success: true },
ctx: { ctx: {
maxMsgLength: parseInt(data[7]), maxMsgLength: parseInt(maxLength),
}, },
user: { user: {
id: selfUserId, id: selfUserId,
self: true, self: true,
name: data[3], name: userNameOrExpiry,
colour: parseUserColour(data[4]), colour: parseUserColour(userColour),
perms: parseUserPerms(data[5]), perms: parseUserPerms(userPerms),
permsRaw: data[5], permsRaw: userPerms,
}, },
channel: { channel: {
name: selfChannelName, name: selfChannelName,
@ -227,57 +221,84 @@ Umi.Protocol.SockChat.Protocol = function() {
startKeepAlive(); startKeepAlive();
wasConnected = true; wasConnected = true;
} else { return;
}
if(successOrTimeStamp === 'n') {
wasKicked = true; wasKicked = true;
const failInfo = { const failInfo = {
session: { session: {
success: false, success: false,
reason: data[2], reason: userIdOrReason,
needsAuth: data[2] === 'authfail', needsAuth: userIdOrReason === 'authfail',
}, },
}; };
if(data[3] !== undefined) if(userNameOrExpiry !== undefined)
failInfo.baka = { failInfo.baka = {
type: 'join', type: 'join',
perma: data[3] === '-1', perma: userNameOrExpiry === '-1',
until: data[3] === '-1' ? undefined : new Date(parseInt(data[3]) * 1000), until: userNameOrExpiry === '-1' ? undefined : new Date(parseInt(userNameOrExpiry) * 1000),
}; };
watchers.call('session:fail', failInfo); watchers.call('session:fail', failInfo);
return;
} }
}
break;
case '2': // message watchers.call('user:add', {
let mText = unfuckText(data[3]); msg: {
id: chanNameOrMsgId,
time: new Date(parseInt(successOrTimeStamp) * 1000),
channel: selfChannelName,
botInfo: {
type: 'join',
args: [userNameOrExpiry],
},
},
user: {
id: userIdOrReason,
self: userIdOrReason === selfUserId,
name: userNameOrExpiry,
colour: parseUserColour(userColour),
perms: parseUserPerms(userPerms),
permsRaw: userPerms,
},
});
};
// message add
handlers['2'] = (timeStamp, userId, msgText, msgId, msgFlags) => {
let mText = unfuckText(msgText);
let mChannelName = selfChannelName; let mChannelName = selfChannelName;
if(data[5][4] !== '0') { if(msgFlags[4] !== '0') {
if(data[2] === selfUserId) { if(userId === selfUserId) {
const mTextParts = mText.split(' '); const mTextParts = mText.split(' ');
mChannelName = `@${mTextParts.shift()}`; mChannelName = `@${mTextParts.shift()}`;
mText = mTextParts.join(' '); mText = mTextParts.join(' ');
} else { } else {
mChannelName = `@~${data[2]}`; mChannelName = `@~${userId}`;
} }
} }
const msgInfo = { const msgInfo = {
msg: { msg: {
id: data[4], id: msgId,
time: new Date(parseInt(data[1]) * 1000), time: new Date(parseInt(timeStamp) * 1000),
channel: mChannelName, channel: mChannelName,
sender: { id: data[2], }, sender: {
flags: parseMsgFlags(data[5]), id: userId,
flagsRaw: data[5], self: userId === selfUserId,
isBot: data[2] === '-1', },
flags: parseMsgFlags(msgFlags),
flagsRaw: msgFlags,
isBot: userId === '-1',
text: mText, text: mText,
}, },
}; };
if(msgInfo.msg.isBot) { if(msgInfo.msg.isBot) {
const botParts = data[3].split("\f"); const botParts = msgText.split("\f");
msgInfo.msg.botInfo = { msgInfo.msg.botInfo = {
isError: botParts[0] === '1', isError: botParts[0] === '1',
type: botParts[1], type: botParts[1],
@ -286,189 +307,200 @@ Umi.Protocol.SockChat.Protocol = function() {
} }
watchers.call('msg:add', msgInfo); watchers.call('msg:add', msgInfo);
break; };
case '3': // leave // user leave
handlers['3'] = (userId, userName, reason, timeStamp, msgId) => {
watchers.call('user:remove', { watchers.call('user:remove', {
leave: { type: data[3] }, leave: { type: reason },
msg: { msg: {
id: data[5], id: msgId,
time: new Date(parseInt(data[4]) * 1000), time: new Date(parseInt(timeStamp) * 1000),
channel: selfChannelName, channel: selfChannelName,
botInfo: { botInfo: {
type: data[3], type: reason,
args: [data[2]], args: [userName],
}, },
}, },
user: { user: {
id: data[1], id: userId,
self: data[1] === selfUserId, self: userId === selfUserId,
name: data[2], name: userName,
}, },
}); });
break; };
case '4': // channel // channel add/upd/del
switch(data[1]) { handlers['4'] = {};
case '0':
// channel add
handlers['4']['0'] = (name, hasPass, isTemp) => {
watchers.call('chan:add', { watchers.call('chan:add', {
channel: { channel: {
name: data[2], name: name,
hasPassword: data[3] !== '0', hasPassword: hasPass !== '0',
isTemporary: data[4] !== '0', isTemporary: isTemp !== '0',
}, },
}); });
break; };
case '1': // channel update
handlers['4']['1'] = (prevName, name, hasPass, isTemp) => {
watchers.call('chan:update', { watchers.call('chan:update', {
channel: { channel: {
previousName: data[2], previousName: prevName,
name: data[3], name: name,
hasPassword: data[4] !== '0', hasPassword: hasPass !== '0',
isTemporary: data[5] !== '0', isTemporary: isTemp !== '0',
}, },
}); });
break; };
case '2': // channel remove
handlers['4']['2'] = name => {
watchers.call('chan:remove', { watchers.call('chan:remove', {
channel: { name: data[2] }, channel: { name: name },
}); });
break; };
}
break;
case '5': // user move // user channel move
switch(data[1]) { handlers['5'] = {};
case '0':
// user join channel
handlers['5']['0'] = (userId, userName, userColour, userPerms, msgId) => {
watchers.call('chan:join', { watchers.call('chan:join', {
user: { user: {
id: data[2], id: userId,
self: data[2] === selfUserId, self: userId === selfUserId,
name: data[3], name: userName,
colour: parseUserColour(data[4]), colour: parseUserColour(userColour),
perms: parseUserPerms(data[5]), perms: parseUserPerms(userPerms),
permsRaw: data[5], permsRaw: userPerms,
}, },
msg: { msg: {
id: data[6], id: msgId,
channel: selfChannelName, channel: selfChannelName,
botInfo: { botInfo: {
type: 'jchan', type: 'jchan',
args: [data[3]], args: [userName],
}, },
}, },
}); });
break; };
case '1': // user leave channel
handlers['5']['1'] = (userId, msgId) => {
watchers.call('chan:leave', { watchers.call('chan:leave', {
user: { user: {
id: data[2], id: userId,
self: data[2] === selfUserId, self: userId === selfUserId,
}, },
msg: { msg: {
id: data[3], id: msgId,
channel: selfChannelName, channel: selfChannelName,
botInfo: { botInfo: {
type: 'lchan', type: 'lchan',
args: [data[2]], args: [userId],
}, },
}, },
}); });
break; };
case '2': // user forced switch channel
selfChannelName = data[2]; handlers['5']['2'] = name => {
selfChannelName = name;
watchers.call('chan:focus', { watchers.call('chan:focus', {
channel: { name: selfChannelName }, channel: { name: selfChannelName },
}); });
break; };
}
break;
case '6': // message delete // message delete
handlers['6'] = msgId => {
watchers.call('msg:remove', { watchers.call('msg:remove', {
msg: { msg: {
id: data[1], id: msgId,
channel: selfChannelName, channel: selfChannelName,
}, },
}); });
break; };
case '7': // context populate // context populate
switch(data[1]) { handlers['7'] = {};
case '0': // users
const cpuamount = parseInt(data[2]);
for(let i = 0; i < cpuamount; ++i) { // existing users
const cpuoffset = 3 + 5 * i; handlers['7']['0'] = (count, ...args) => {
count = parseInt(count);
for(let i = 0; i < count; ++i) {
const offset = 5 * i;
watchers.call('user:add', { watchers.call('user:add', {
user: { user: {
id: data[cpuoffset], id: args[offset],
self: data[cpuoffset] === selfUserId, self: args[offset] === selfUserId,
name: data[cpuoffset + 1], name: args[offset + 1],
colour: parseUserColour(data[cpuoffset + 2]), colour: parseUserColour(args[offset + 2]),
perms: parseUserPerms(data[cpuoffset + 3]), perms: parseUserPerms(args[offset + 3]),
permsRaw: data[cpuoffset + 3], permsRaw: args[offset + 3],
hidden: data[cpuoffset + 4] !== '0', hidden: args[offset + 4] !== '0',
}, },
}); });
} }
break; };
case '1': // message // existing message
const cmMsgInfo = { handlers['7']['1'] = (timeStamp, userId, userName, userColour, userPerms, msgText, msgId, msgNotify, msgFlags) => {
const info = {
msg: { msg: {
id: data[8], id: msgId,
time: new Date(parseInt(data[2]) * 1000), time: new Date(parseInt(timeStamp) * 1000),
channel: selfChannelName, channel: selfChannelName,
sender: { sender: {
id: data[3], id: userId,
name: data[4], self: userId === selfUserId,
colour: parseUserColour(data[5]), name: userName,
perms: parseUserColour(data[6]), colour: parseUserColour(userColour),
permsRaw: data[6], perms: parseUserColour(userPerms),
permsRaw: userPerms,
}, },
isBot: data[3] === '-1', isBot: userId === '-1',
silent: data[9] === '0', silent: msgNotify === '0',
flags: parseMsgFlags(data[10]), flags: parseMsgFlags(msgFlags),
flagsRaw: data[10], flagsRaw: msgFlags,
text: unfuckText(data[7]), text: unfuckText(msgText),
}, },
}; };
const cmMsgIdFirst = cmMsgInfo.msg.id.charCodeAt(0); const msgIdFirst = info.msg.id.charCodeAt(0);
if(cmMsgIdFirst < 48 || cmMsgIdFirst > 57) if(msgIdFirst < 48 || msgIdFirst > 57)
cmMsgInfo.msg.id = (Math.round(Number.MIN_SAFE_INTEGER * Math.random())).toString(); info.msg.id = (Math.round(Number.MIN_SAFE_INTEGER * Math.random())).toString();
if(cmMsgInfo.msg.isBot) { if(info.msg.isBot) {
const cmBotParts = data[7].split("\f"); const botParts = msgText.split("\f");
cmMsgInfo.msg.botInfo = { info.msg.botInfo = {
isError: cmBotParts[0] === '1', isError: botParts[0] === '1',
type: cmBotParts[1], type: botParts[1],
args: cmBotParts.slice(2), args: botParts.slice(2),
}; };
} }
watchers.call('msg:add', cmMsgInfo); watchers.call('msg:add', info);
break; };
case '2': // channels // existing channels
const ecpamount = parseInt(data[2]); handlers['7']['2'] = (count, ...args) => {
count = parseInt(count);
for(let i = 0; i < ecpamount; ++i) { for(let i = 0; i < count; ++i) {
const ecpoffset = 3 + 3 * i; const offset = 3 * i;
watchers.call('chan:add', { watchers.call('chan:add', {
channel: { channel: {
name: data[ecpoffset], name: args[offset],
hasPassword: data[ecpoffset + 1] !== '0', hasPassword: args[offset + 1] !== '0',
isTemporary: data[ecpoffset + 2] !== '0', isTemporary: args[offset + 2] !== '0',
isCurrent: data[ecpoffset] === selfChannelName, isCurrent: args[offset] === selfChannelName,
}, },
}); });
} }
@ -476,54 +508,55 @@ Umi.Protocol.SockChat.Protocol = function() {
watchers.call('chan:focus', { watchers.call('chan:focus', {
channel: { name: selfChannelName }, channel: { name: selfChannelName },
}); });
break; };
}
break;
case '8': // context clear // context clear
if(data[1] === '0' || data[1] === '3' || data[1] === '4') handlers['8'] = mode => {
if(mode === '0' || mode === '3' || mode === '4')
watchers.call('msg:clear'); watchers.call('msg:clear');
if(data[1] === '1' || data[1] === '3' || data[1] === '4') if(mode === '1' || mode === '3' || mode === '4')
watchers.call('user:clear'); watchers.call('user:clear');
if(data[1] === '2' || data[1] === '4') if(mode === '2' || mode === '4')
watchers.call('chan:clear'); watchers.call('chan:clear');
break; };
case '9': // baka // baka (ban/kick)
handlers['9'] = (type, expiry) => {
noReconnect = true; noReconnect = true;
wasKicked = true; wasKicked = true;
const bakaInfo = { const bakaInfo = {
session: { success: false }, session: { success: false },
baka: { baka: {
type: data[1] === '0' ? 'kick' : 'ban', type: type === '0' ? 'kick' : 'ban',
}, },
}; };
if(bakaInfo.baka.type === 'ban') { if(bakaInfo.baka.type === 'ban') {
bakaInfo.baka.perma = data[2] === '-1'; bakaInfo.baka.perma = expiry === '-1';
bakaInfo.baka.until = data[2] === '-1' ? undefined : new Date(parseInt(data[2]) * 1000); bakaInfo.baka.until = expiry === '-1' ? undefined : new Date(parseInt(expiry) * 1000);
} }
watchers.call('session:term', bakaInfo); watchers.call('session:term', bakaInfo);
break; };
case '10': // user update // user update
handlers['10'] = (userId, userName, userColour, userPerms) => {
watchers.call('user:update', { watchers.call('user:update', {
user: { user: {
id: data[1], id: userId,
self: data[1] === selfUserId, self: userId === selfUserId,
name: data[2], name: userName,
colour: parseUserColour(data[3]), colour: parseUserColour(userColour),
perms: parseUserPerms(data[4]), perms: parseUserPerms(userPerms),
permsRaw: data[4], permsRaw: userPerms,
}, },
}); });
break;
}
}; };
const beginConnecting = () => { const beginConnecting = () => {
sock?.close(); sock?.close();