add more IRC-side error checking

This commit is contained in:
emerson 2022-01-24 12:25:30 -05:00
parent ddbdcc9981
commit 2e973a18db
3 changed files with 135 additions and 34 deletions

View file

@ -3,6 +3,7 @@ import { MatrixUser } from "./MatrixUser.js";
import { IRCUser } from "./IRCUser.js";
import { Client } from "./Client.js";
import numerics from "./numerics.js";
import { IRCMessage } from "./Message.js";
export class Channel {
public name: string
@ -46,7 +47,9 @@ export class Channel {
if (!newName || newName === this.name)
return;
const oldName = this.name;
this.server.ircChannels.delete(oldName);
this.name = newName;
this.server.ircChannels.set(newName, this);
this.ircUsers.forEach((user, username) => {
user.getClients().forEach(client => {
if (client.enabledCaps.has("draft/channel-rename")) {
@ -136,7 +139,11 @@ export class Channel {
]
client.sendMessage(client.server.name, '352', userParams, passedTags);
}
client.sendMessage(client.server.name, '315', [this.name], passedTags);
client.sendMessage(client.server.name, '315', [client.user.nick, this.name, "End of /WHO"], passedTags);
}
handleModeChange(client: Client, message: IRCMessage) {
}
routeMatrixEvent(event: any) {

View file

@ -49,6 +49,56 @@ export class Client {
});
}
checkIfRegistered(passedTags: Map<string, string> = new Map()) {
if (this.user === null)
this.sendMessage(this.server.name, "451", [this.localNick, "You have not registered"], passedTags);
return this.user !== null;
}
getMatrixUserFromNick(targetNick: string, passedTags: Map<string, string> = new Map()) {
if (!this.user) return false;
const targetMxid = this.server.nickToMxid.get(targetNick);
if (!targetMxid) {
this.sendMessage(this.server.name, "401", [this.user.nick, targetNick, "No such nick"], passedTags);
return false;
}
const target = this.server.matrixUsers.get(targetMxid);
if (!target) {
this.sendMessage(this.server.name, "401", [this.user.nick, targetNick, "No such nick"], passedTags);
return false;
}
return target;
}
getChannel(channel: string, passedTags: Map<string, string> = new Map()) {
if (!this.user) return false;
const targetChannel = this.server.ircChannels.get(channel);
if (!targetChannel) {
this.sendMessage(this.server.name, "403", [this.user.nick, channel, "No such channel"], passedTags);
return false;
}
return targetChannel;
}
checkIfInChannel(channel: Channel, passedTags: Map<string, string> = new Map()) {
if (!this.user) return false;
if (!channel.ircUsers.has(this.user.nick)) {
this.sendMessage(this.server.name, "442", [this.user.nick, "You're not on that channel"], passedTags);
return false;
}
return true;
}
checkMinParams(message: IRCMessage, neededNumber: number) {
if (!this.user) return false;
if (message.params.length < neededNumber) {
this.sendMessage(this.server.name, "461", [this.user.nick, message.command, "Not enough parameters"], message.tags);
return false;
}
return true;
}
routeMessage(data: string) {
const message = parseIRCMessage(data);
switch (message.command.toUpperCase()) {
@ -61,47 +111,80 @@ export class Client {
break;
}
case 'INVITE': {
const targetUser = this.server.getOrCreateMatrixUser(message.params[0])
const targetChannel = this.server.ircChannels.get(message.params[1]);
if (!this.checkIfRegistered(message.tags) || !this.checkMinParams(message, 2))
return;
const targetUser = this.getMatrixUserFromNick(message.params[0], message.tags);
const targetChannel = this.getChannel(message.params[1], message.tags);
if (!this.user || !targetUser || !targetChannel) return;
if (!this.checkIfInChannel(targetChannel, message.tags)) return;
if (targetChannel.matrixUsers.has(targetUser.nick)) {
this.sendMessage(this.server.name, "443", [this.user.nick, targetUser.nick, "is already on channel"], message.tags);
return;
}
const reason = (message.params.length === 3) ? message.params[2] : "";
if (this.user && targetChannel && targetChannel.ircUsers.get(this.user.nick))
this.user.inviteMatrixUser(this, targetChannel, targetUser, reason, message.tags);
this.user.inviteMatrixUser(this, targetChannel, targetUser, reason, message.tags);
break;
}
case 'KICK': {
const targetChannel = this.server.ircChannels.get(message.params[0]);
const targetMxid = this.server.nickToMxid.get(message.params[1]);
if (!targetMxid)
if (!this.checkIfRegistered(message.tags) || !this.checkMinParams(message, 2))
return;
console.log(targetMxid);
const targetChannel = this.getChannel(message.params[0], message.tags);
const targetUser = this.getMatrixUserFromNick(message.params[1], message.tags);
if (!this.user || !targetUser || !targetChannel) return;
if (!this.checkIfInChannel(targetChannel, message.tags)) return;
if (!targetChannel.matrixUsers.has(targetUser.nick)) {
this.sendMessage(this.server.name, "441", [this.user.nick, targetUser.nick, targetChannel.name, "They aren't on that channel"], message.tags);
return;
}
const reason = (message.params.length === 3) ? message.params[2] : "";
if (this.user && targetChannel && targetChannel.ircUsers.get(this.user.nick))
this.user.kickMatrixUser(this, targetChannel, targetMxid, reason, message.tags);
this.user.kickMatrixUser(this, targetChannel, targetUser.mxid, reason, message.tags);
break;
}
case 'MODE': {
if (!this.checkIfRegistered(message.tags) || !this.checkMinParams(message, 1) || !this.user)
return;
const targetChannel = this.server.ircChannels.get(message.params[0]);
if (this.user && targetChannel && targetChannel.ircUsers.get(this.user.nick))
if (!targetChannel) {
if (message.params[0] !== this.user.nick) {
this.sendMessage(this.server.name, "502", [this.user.nick, "Can't view mode for other users"], message.tags);
return;
}
this.sendMessage(this.server.name, "221", [this.user.nick, "+i"], message.tags);
return;
}
if (!this.checkIfInChannel(targetChannel, message.tags)) return;
if (message.params.length === 1)
targetChannel.sendMode(this, message.tags);
else
targetChannel.handleModeChange(this, message);
break;
}
case 'NAMES': {
const targetChannel = this.server.ircChannels.get(message.params[0]);
if (this.user && targetChannel && targetChannel.ircUsers.get(this.user.nick))
targetChannel.sendNames(this, message.tags);
if (!this.checkIfRegistered(message.tags) || !this.checkMinParams(message, 1))
return;
const targetChannel = this.getChannel(message.params[0], message.tags);
if (!this.user || !targetChannel) return;
if (!this.checkIfInChannel(targetChannel, message.tags)) return;
targetChannel.sendNames(this, message.tags);
break;
}
case 'NOTICE': {
if (this.user) {
this.user.sendMessageToMatrix(message, this);
}
if (!this.checkIfRegistered(message.tags) || !this.checkMinParams(message, 2))
return;
const targetChannel = this.getChannel(message.params[0], message.tags);
if (!this.user || !targetChannel) return;
if (!this.checkIfInChannel(targetChannel, message.tags)) return;
this.user.sendMessageToMatrix(message, this);
break;
}
case 'PART': {
const targetChannel = this.server.ircChannels.get(message.params[0]);
if (!this.checkIfRegistered(message.tags) || !this.checkMinParams(message, 1))
return;
const targetChannel = this.getChannel(message.params[0], message.tags);
if (!this.user || !targetChannel) return;
if (!this.checkIfInChannel(targetChannel, message.tags)) return;
const reason = (message.params.length === 2) ? message.params[1] : "";
if (this.user && targetChannel && targetChannel.ircUsers.get(this.user.nick))
this.user.partMatrixRoom(this, targetChannel, reason, message.tags);
this.user.partMatrixRoom(this, targetChannel, reason, message.tags);
break;
}
case 'PING': {
@ -109,21 +192,29 @@ export class Client {
break;
}
case 'PRIVMSG': {
if (this.user) {
this.user.sendMessageToMatrix(message, this);
}
if (!this.checkIfRegistered(message.tags) || !this.checkMinParams(message, 2))
return;
const targetChannel = this.getChannel(message.params[0], message.tags);
if (!this.user || !targetChannel) return;
if (!this.checkIfInChannel(targetChannel, message.tags)) return;
this.user.sendMessageToMatrix(message, this);
break;
}
case 'TAGMSG': {
if (this.user) {
this.user.sendTagToMatrix(message, this);
}
if (!this.checkIfRegistered(message.tags) || !this.checkMinParams(message, 1))
return;
const targetChannel = this.getChannel(message.params[0], message.tags);
if (!this.user || !targetChannel) return;
if (!this.checkIfInChannel(targetChannel, message.tags)) return;
this.user.sendTagToMatrix(message, this);
break;
}
case 'TOPIC': {
const targetChannel = this.server.ircChannels.get(message.params[0]);
if (!this.user || !targetChannel || !targetChannel.ircUsers.get(this.user.nick))
break;
if (!this.checkIfRegistered(message.tags) || !this.checkMinParams(message, 1))
return;
const targetChannel = this.getChannel(message.params[0], message.tags);
if (!this.user || !targetChannel) return;
if (!this.checkIfInChannel(targetChannel, message.tags)) return;
if (message.params.length === 1) {
targetChannel.sendTopic(this, message.tags);
break;
@ -133,9 +224,12 @@ export class Client {
break;
}
case 'WHO': {
const targetChannel = this.server.ircChannels.get(message.params[0]);
if (this.user && targetChannel && targetChannel.ircUsers.get(this.user.nick))
targetChannel.sendWho(this, message.tags);
if (!this.checkIfRegistered(message.tags) || !this.checkMinParams(message, 1))
return;
const targetChannel = this.getChannel(message.params[0], message.tags);
if (!this.user || !targetChannel) return;
if (!this.checkIfInChannel(targetChannel, message.tags)) return;
targetChannel.sendWho(this, message.tags);
break;
}
}

View file

@ -36,7 +36,7 @@ const numerics = {
return [nick, "End of MOTD"]
},
"433": (nick: string, otherNick: string) => {
return [nick, otherNick, "You can't change nicks on IRC yet"]
return [nick, otherNick, "Nickname is already in use"]
},
"900": (mask: string, nick: string) => {
return [nick, mask, `You are now logged in as ${nick}`]