const EventEmitter = require("events").EventEmitter;
const OutgoingBanchoMessage = require("./OutgoingBanchoMessage.js");
/**
* Represents a discussion channel (not including PMs)
*
* @prop {string} name Channel name as it is referred to on IRC (including #)
* @prop {string} topic
* @prop {boolean} joined Whether we've joined the channel or not
* @prop {Map<string,BanchoChannelMember>} channelMembers Members of the channel, referenced by their name
* @extends EventEmitter
*/
class BanchoChannel extends EventEmitter {
/**
* Creates an instance of BanchoChannel.
* @param {BanchoClient} banchojs bancho.js client
* @param {string} name Channel name as it is referred to on IRC (including #)
*/
constructor(banchojs, name) {
super();
this.banchojs = banchojs;
this.name = name;
this.topic = "";
this.joined = false;
this.joinCallback = null;
this.joinPromise = null;
this.partCallback = null;
this.partPromise = null;
this.channelMembers = new Map();
this.listenersInitialized = false;
}
on() {
if(!this.listenersInitialized) {
this.banchojs.on("CM", (msg) => {
if(msg.channel == this)
/**
* Emitted when a message is received in a BanchoChannel
* @event BanchoChannel#message
* @type {ChannelMessage}
*/
this.emit("message", msg);
});
this.banchojs.on("JOIN", (member) => {
if(member.channel == this)
/**
* Emitted when someone joins this channel
* @event BanchoChannel#JOIN
* @type {BanchoChannelMember}
*/
this.emit("JOIN", member);
});
this.banchojs.on("PART", (member) => {
if(member.channel == this)
/**
* Emitted when someone leaves this channel
* @event BanchoChannel#PART
* @type {BanchoChannelMember}
*/
this.emit("PART", member);
});
this.listenersInitialized = true;
}
super.on.apply(this, arguments);
}
/**
* Sends a message to this channel
*
* Elevated Bancho users are advised to heavily sanitize their inputs.
*
* @async
* @throws {Error} If we're offline
* @param {string} message
* @returns {Promise<null>} Resolves when message is sent (rate-limiting)
*/
sendMessage(message) {
return (new OutgoingBanchoMessage(this.banchojs, this, message)).send();
}
/**
* Sends an ACTION message to this channel
*
* @async
* @throws {Error} If we're offline
* @param {string} message
* @returns {Promise<null>} Resolves when message is sent (rate-limiting)
*/
sendAction(message) {
return (new OutgoingBanchoMessage(this.banchojs, this, `\x01ACTION ${message}\x01`)).send();
}
/**
* Join the channel
*
* @async
* @returns {Promise<null>}
*/
join() {
if (this.joined)
return Promise.resolve();
return this._joinOrPart("JOIN", "joinCallback", "joinPromise");
}
/**
* Leave the channel
*
* @async
* @returns {Promise<null>}
*/
leave() {
if (!this.joined)
return Promise.resolve();
return this._joinOrPart("PART", "partCallback", "partPromise");
}
/**
* Sub-function for join/leave calls
*
* @private
* @param {string} action
* @param {*} callbackProp
* @param {*} promiseProp
*/
_joinOrPart(action, callbackProp, promiseProp) {
if(action != "JOIN" && action != "PART")
throw new Error("wrong action dumbass");
if(this[promiseProp] == null)
this[promiseProp] = new Promise((resolve, reject) => {
this.banchojs.send(action+" "+this.name);
this[callbackProp] = (err) => {
if(!err)
resolve();
else
reject(err);
this[callbackProp] = null;
this[promiseProp] = null;
};
});
return this[promiseProp];
}
}
module.exports = BanchoChannel;