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