mirror of
https://codeberg.org/emersion/gamja
synced 2025-03-13 07:48:37 +01:00
Introduce State.handleMessage
Takes an IRC message, updates the state. Doesn't yet handle all messages, this will be a step-by-step process.
This commit is contained in:
parent
4d988cafeb
commit
2c1bb4ce6a
@ -561,6 +561,9 @@ export default class App extends Component {
|
|||||||
|
|
||||||
handleMessage(serverID, msg) {
|
handleMessage(serverID, msg) {
|
||||||
var client = this.clients.get(serverID);
|
var client = this.clients.get(serverID);
|
||||||
|
|
||||||
|
this.setState((state) => State.handleMessage(state, msg, serverID, client));
|
||||||
|
|
||||||
switch (msg.command) {
|
switch (msg.command) {
|
||||||
case irc.RPL_WELCOME:
|
case irc.RPL_WELCOME:
|
||||||
if (this.state.connectParams.autojoin.length > 0) {
|
if (this.state.connectParams.autojoin.length > 0) {
|
||||||
@ -585,91 +588,6 @@ export default class App extends Component {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case irc.RPL_MYINFO:
|
|
||||||
// TODO: parse available modes
|
|
||||||
var serverInfo = {
|
|
||||||
name: msg.params[1],
|
|
||||||
version: msg.params[2],
|
|
||||||
};
|
|
||||||
this.setBufferState({ server: serverID, name: SERVER_BUFFER }, { serverInfo });
|
|
||||||
break;
|
|
||||||
case irc.RPL_ISUPPORT:
|
|
||||||
this.setServerState(serverID, (server) => {
|
|
||||||
return { isupport: new Map(client.isupport) };
|
|
||||||
});
|
|
||||||
this.setState((state) => {
|
|
||||||
var buffers = new Map(state.buffers);
|
|
||||||
state.buffers.forEach((buf) => {
|
|
||||||
if (buf.server != serverID) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var members = new irc.CaseMapMap(buf.members, client.cm);
|
|
||||||
buffers.set(buf.id, { ...buf, members });
|
|
||||||
});
|
|
||||||
return { buffers };
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
case irc.RPL_NOTOPIC:
|
|
||||||
var channel = msg.params[1];
|
|
||||||
|
|
||||||
this.setBufferState({ server: serverID, name: channel }, { topic: null });
|
|
||||||
break;
|
|
||||||
case irc.RPL_TOPIC:
|
|
||||||
var channel = msg.params[1];
|
|
||||||
var topic = msg.params[2];
|
|
||||||
|
|
||||||
this.setBufferState({ server: serverID, name: channel }, { topic });
|
|
||||||
break;
|
|
||||||
case irc.RPL_TOPICWHOTIME:
|
|
||||||
// Ignore
|
|
||||||
break;
|
|
||||||
case irc.RPL_NAMREPLY:
|
|
||||||
var channel = msg.params[2];
|
|
||||||
var membersList = msg.params[3].split(" ");
|
|
||||||
|
|
||||||
this.setBufferState({ server: serverID, name: channel }, (buf) => {
|
|
||||||
var members = new irc.CaseMapMap(buf.members);
|
|
||||||
membersList.forEach((s) => {
|
|
||||||
var member = irc.parseTargetPrefix(s);
|
|
||||||
members.set(member.name, member.prefix);
|
|
||||||
});
|
|
||||||
|
|
||||||
return { members };
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
case irc.RPL_ENDOFNAMES:
|
|
||||||
break;
|
|
||||||
case irc.RPL_WHOREPLY:
|
|
||||||
var last = msg.params[msg.params.length - 1];
|
|
||||||
var who = {
|
|
||||||
username: msg.params[2],
|
|
||||||
hostname: msg.params[3],
|
|
||||||
server: msg.params[4],
|
|
||||||
nick: msg.params[5],
|
|
||||||
away: msg.params[6] == 'G', // H for here, G for gone
|
|
||||||
realname: last.slice(last.indexOf(" ") + 1),
|
|
||||||
};
|
|
||||||
|
|
||||||
this.setBufferState({ server: serverID, name: who.nick }, { who, offline: false });
|
|
||||||
|
|
||||||
this.addMessage(serverID, SERVER_BUFFER, msg);
|
|
||||||
break;
|
|
||||||
case irc.RPL_ENDOFWHO:
|
|
||||||
var target = msg.params[1];
|
|
||||||
if (!this.isChannel(target) && target.indexOf("*") < 0) {
|
|
||||||
// Not a channel nor a mask, likely a nick
|
|
||||||
this.setBufferState({ server: serverID, name: target }, (buf) => {
|
|
||||||
// TODO: mark user offline if we have old WHO info but this
|
|
||||||
// WHO reply is empty
|
|
||||||
if (buf.who) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
return { offline: true };
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
this.addMessage(serverID, SERVER_BUFFER, msg);
|
|
||||||
break;
|
|
||||||
case "MODE":
|
case "MODE":
|
||||||
var target = msg.params[0];
|
var target = msg.params[0];
|
||||||
if (this.isChannel(target)) {
|
if (this.isChannel(target)) {
|
||||||
@ -732,19 +650,7 @@ export default class App extends Component {
|
|||||||
break;
|
break;
|
||||||
case "KICK":
|
case "KICK":
|
||||||
var channel = msg.params[0];
|
var channel = msg.params[0];
|
||||||
var user = msg.params[1];
|
|
||||||
|
|
||||||
this.setBufferState({ server: serverID, name: channel }, (buf) => {
|
|
||||||
var members = new irc.CaseMapMap(buf.members);
|
|
||||||
members.delete(user);
|
|
||||||
return { members };
|
|
||||||
});
|
|
||||||
this.addMessage(serverID, channel, msg);
|
this.addMessage(serverID, channel, msg);
|
||||||
|
|
||||||
if (client.isMyNick(msg.prefix.name)) {
|
|
||||||
this.receipts.delete(channel);
|
|
||||||
this.saveReceipts();
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case "QUIT":
|
case "QUIT":
|
||||||
var affectedBuffers = [];
|
var affectedBuffers = [];
|
||||||
@ -790,12 +696,6 @@ export default class App extends Component {
|
|||||||
});
|
});
|
||||||
affectedBuffers.forEach((name) => this.addMessage(serverID, name, msg));
|
affectedBuffers.forEach((name) => this.addMessage(serverID, name, msg));
|
||||||
break;
|
break;
|
||||||
case "SETNAME":
|
|
||||||
this.setBufferState({ server: serverID, name: msg.prefix.name }, (buf) => {
|
|
||||||
var who = { ...buf.who, realname: msg.params[0] };
|
|
||||||
return { who }
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
case "TOPIC":
|
case "TOPIC":
|
||||||
var channel = msg.params[0];
|
var channel = msg.params[0];
|
||||||
var topic = msg.params[1];
|
var topic = msg.params[1];
|
||||||
@ -814,14 +714,6 @@ export default class App extends Component {
|
|||||||
|
|
||||||
this.addMessage(serverID, bufName, msg);
|
this.addMessage(serverID, bufName, msg);
|
||||||
break;
|
break;
|
||||||
case "AWAY":
|
|
||||||
var awayMessage = msg.params[0];
|
|
||||||
|
|
||||||
this.setBufferState({ server: serverID, name: msg.prefix.name }, (buf) => {
|
|
||||||
var who = { ...buf.who, away: !!awayMessage };
|
|
||||||
return { who };
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
case "BOUNCER":
|
case "BOUNCER":
|
||||||
if (msg.params[0] !== "NETWORK") {
|
if (msg.params[0] !== "NETWORK") {
|
||||||
break; // We're only interested in network updates
|
break; // We're only interested in network updates
|
||||||
@ -870,6 +762,15 @@ export default class App extends Component {
|
|||||||
var channel = msg.params[1];
|
var channel = msg.params[1];
|
||||||
this.addMessage(serverID, channel, msg);
|
this.addMessage(serverID, channel, msg);
|
||||||
break;
|
break;
|
||||||
|
case irc.RPL_MYINFO:
|
||||||
|
case irc.RPL_ISUPPORT:
|
||||||
|
case irc.RPL_NOTOPIC:
|
||||||
|
case irc.RPL_TOPIC:
|
||||||
|
case irc.RPL_TOPICWHOTIME:
|
||||||
|
case irc.RPL_NAMREPLY:
|
||||||
|
case irc.RPL_ENDOFNAMES:
|
||||||
|
case "AWAY":
|
||||||
|
case "SETNAME":
|
||||||
case "CAP":
|
case "CAP":
|
||||||
case "AUTHENTICATE":
|
case "AUTHENTICATE":
|
||||||
case "PING":
|
case "PING":
|
||||||
|
@ -466,6 +466,11 @@ export default class Client extends EventTarget {
|
|||||||
return this.cm(nick) == this.cm(this.nick);
|
return this.cm(nick) == this.cm(this.nick);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isChannel(name) {
|
||||||
|
// TODO: use the ISUPPORT token if available
|
||||||
|
return irc.STD_CHANNEL_TYPES.indexOf(name[0]) >= 0;
|
||||||
|
}
|
||||||
|
|
||||||
setPingInterval(sec) {
|
setPingInterval(sec) {
|
||||||
clearInterval(this.pingIntervalID);
|
clearInterval(this.pingIntervalID);
|
||||||
this.pingIntervalID = null;
|
this.pingIntervalID = null;
|
||||||
|
101
state.js
101
state.js
@ -161,4 +161,105 @@ export const State = {
|
|||||||
throw new Error("Invalid buffer ID type: " + (typeof id));
|
throw new Error("Invalid buffer ID type: " + (typeof id));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
handleMessage(state, msg, serverID, client) {
|
||||||
|
function updateServer(updater) {
|
||||||
|
return State.updateServer(state, serverID, updater);
|
||||||
|
}
|
||||||
|
function updateBuffer(name, updater) {
|
||||||
|
return State.updateBuffer(state, { server: serverID, name }, updater);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (msg.command) {
|
||||||
|
case irc.RPL_MYINFO:
|
||||||
|
// TODO: parse available modes
|
||||||
|
var serverInfo = {
|
||||||
|
name: msg.params[1],
|
||||||
|
version: msg.params[2],
|
||||||
|
};
|
||||||
|
return updateBuffer(SERVER_BUFFER, { serverInfo });
|
||||||
|
case irc.RPL_ISUPPORT:
|
||||||
|
var buffers = new Map(state.buffers);
|
||||||
|
state.buffers.forEach((buf) => {
|
||||||
|
if (buf.server != serverID) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var members = new irc.CaseMapMap(buf.members, client.cm);
|
||||||
|
buffers.set(buf.id, { ...buf, members });
|
||||||
|
});
|
||||||
|
return {
|
||||||
|
buffers,
|
||||||
|
...updateServer({ isupport: new Map(client.isupport) }),
|
||||||
|
};
|
||||||
|
case irc.RPL_NOTOPIC:
|
||||||
|
var channel = msg.params[1];
|
||||||
|
return updateBuffer(channel, { topic: null });
|
||||||
|
case irc.RPL_TOPIC:
|
||||||
|
var channel = msg.params[1];
|
||||||
|
var topic = msg.params[2];
|
||||||
|
return updateBuffer(channel, { topic });
|
||||||
|
case irc.RPL_TOPICWHOTIME:
|
||||||
|
// Ignore
|
||||||
|
break;
|
||||||
|
case irc.RPL_NAMREPLY:
|
||||||
|
var channel = msg.params[2];
|
||||||
|
var membersList = msg.params[3].split(" ");
|
||||||
|
|
||||||
|
return updateBuffer(channel, (buf) => {
|
||||||
|
var members = new irc.CaseMapMap(buf.members);
|
||||||
|
membersList.forEach((s) => {
|
||||||
|
var member = irc.parseTargetPrefix(s);
|
||||||
|
members.set(member.name, member.prefix);
|
||||||
|
});
|
||||||
|
return { members };
|
||||||
|
});
|
||||||
|
case irc.RPL_ENDOFNAMES:
|
||||||
|
break;
|
||||||
|
case irc.RPL_WHOREPLY:
|
||||||
|
var last = msg.params[msg.params.length - 1];
|
||||||
|
var who = {
|
||||||
|
username: msg.params[2],
|
||||||
|
hostname: msg.params[3],
|
||||||
|
server: msg.params[4],
|
||||||
|
nick: msg.params[5],
|
||||||
|
away: msg.params[6] == 'G', // H for here, G for gone
|
||||||
|
realname: last.slice(last.indexOf(" ") + 1),
|
||||||
|
};
|
||||||
|
return updateBuffer(who.nick, { who, offline: false });
|
||||||
|
case irc.RPL_ENDOFWHO:
|
||||||
|
var target = msg.params[1];
|
||||||
|
if (!client.isChannel(target) && target.indexOf("*") < 0) {
|
||||||
|
// Not a channel nor a mask, likely a nick
|
||||||
|
return updateBuffer(target, (buf) => {
|
||||||
|
// TODO: mark user offline if we have old WHO info but this
|
||||||
|
// WHO reply is empty
|
||||||
|
if (buf.who) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
return { offline: true };
|
||||||
|
});
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "KICK":
|
||||||
|
var channel = msg.params[0];
|
||||||
|
var nick = msg.params[1];
|
||||||
|
|
||||||
|
return updateBuffer(channel, (buf) => {
|
||||||
|
var members = new irc.CaseMapMap(buf.members);
|
||||||
|
members.delete(nick);
|
||||||
|
return { members };
|
||||||
|
});
|
||||||
|
case "SETNAME":
|
||||||
|
return updateBuffer(msg.prefix.name, (buf) => {
|
||||||
|
var who = { ...buf.who, realname: msg.params[0] };
|
||||||
|
return { who };
|
||||||
|
});
|
||||||
|
case "AWAY":
|
||||||
|
var awayMessage = msg.params[0];
|
||||||
|
|
||||||
|
return updateBuffer(msg.prefix.name, (buf) => {
|
||||||
|
var who = { ...buf.who, away: !!awayMessage };
|
||||||
|
return { who };
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user