const EventEmitter = require('events')
const User = require("./User")
/**
* @class
*/
class Channel extends EventEmitter{
constructor(connection, channelName){
super()
this._connection = connection
this._channelName = channelName
this._users = new Map()
this._mode = ""
this._modeParams = {}
}
/**
* The name of the channel
* @type {String}
*/
get name(){
return this._channelName
}
/**
* The mode of the channel
* @type {String}
*/
get mode(){
return this._mode
}
/**
* The channels mode params
* @type {Object}
*/
get modeParams(){
return this._modeParams
}
/**
* The topic of the channel
* @type {String}
*/
get topic(){
return this._topic
}
/**
* The users in the channel
* @type {Map}
*/
get users(){
return this._users
}
/**
* Adds a mode
* @function
* @param {String} mode - The mode to add
*/
addMode(mode){
this._mode += mode
}
/**
* Sets the mode of the channel
* @param {String} mode - The mode to set
*/
setMode(mode){
this._mode = mode
}
/**
* Sets a mode param
* @function
* @param {String} name - The name to set
* @param {String} value - The value to set
*/
setModeParam(name, value){
this._modeParams[name] = value
}
handleTopic(message){
this._topic = {by: message.nick, text: message.args[1]}
this.emit('topic', this._topic)
}
/**
* Emits when a user joins the channel
* @event Channel#join
* @type {Object}
* @property {User} user - The user that joined
*/
handleJoin(message){
const user = new User(message.nick, this._connection)
user.set("prefix", message.prefix)
.set("user", message.user)
.set("host", message.host)
this._users.set(message.nick, user)
this.emit("join", user)
}
/**
* Emits when the channel revieves a message
* @event Channel#message
* @type {Object}
* @property {User} user - The user that sent the message
* @property {String} message - The message that was sent
*/
handleMessage(message){
const user = new User(message.nick, this._connection)
user.set("prefix", message.prefix)
.set("user", message.user)
.set("host", message.host)
if(Object.keys(this._users.get(message.nick).info).length === 1){
this._users.set(message.nick, user)
}
this.emit("message", user, message.args[1])
}
handleNames(message){
let users = message.args[3].trim().split(/ +/)
users.map(user => {
let username = user.replace("@", "").replace("+", "")
this._users.set(username, new User(username, this._connection))
})
}
handleRaw(message){
switch(message.command){
case "JOIN":
this.handleJoin(message)
break
case "PART":
this.handlePart(message)
break
case "PRIVMSG":
this.handleMessage(message)
break
case "TOPIC":
this.handleTopic(message)
break
case "KICK":
this.handleKick(message)
break
case "RPL_NAMREPLY":
this.handleNames(message)
break
case "NICK":
this.handleNick(message)
break
case "MODE":
this.handleMode(message)
break
}
}
/**
* Emits when the a user in the channel gets their modes updated
* @event Channel#+mode
* @type {Object}
* @property {Object} data - The data of the event
* @property {User} data.user - The user that was updated
* @property {String} data.from - The nick of the user that updated the mode
* @property {Array.<String>} data.modes - The modes that was added
*/
/**
* Emits when the a user in the channel gets their modes updated
* @event Channel#-mode
* @type {Object}
* @property {Object} data - The data of the event
* @property {User} data.user - The user that was updated
* @property {String} data.from - The nick of the user that updated the mode
* @property {Array.<String>} data.modes - The modes that was removed
*/
handleMode(message){
console.log(message)
let split = message.args[1].split("")
let action = split[0]
split.shift()
if(args[2] !== undefined){
let user = this._users.get(args[2])
if(action === "+"){
split.map(mode => {
user.addMode(mode)
})
}else if(action === "-"){
split.map(mode => {
user.removeMode(mode)
})
}
this.emit(`${action}mode`, {
user: user,
from: message.nick,
modes: split
})
}
}
/**
* Emits when a user changes their nick
* @event Channel#nick
* @type {Object}
* @property {String} oldNick - The old nickname of the user
* @property {String} newNick - The new nickname of the user
* @property {User} user - The user object
*/
handleNick(message){
this._users.delete(message.nick)
const user = new User(message.args[0], this._connection)
user.set("prefix", message.prefix)
.set("user", message.user)
.set("host", message.host)
this._users.set(message.args[0], user)
this.emit("nick", message.nick, message.args[0], user)
}
/**
* Emits when a user parts the channel
* @event Channel#part
* @type {Object}
* @property {User} user - The user that parted
* @property {String} message - The message they left with
*/
handlePart(message){
message.args.shift()
const user = new User(message.nick, this._connection)
user.set("prefix", message.prefix)
.set("user", message.user)
.set("host", message.host)
this._users.delete(message.nick)
this.emit("part", user, message.args[0])
}
/**
* Emits when a user is kicked from the channel
* @event Channel#kick
* @type {Object}
* @property {User} user - The user that was kicked
* @property {User} by - The user who kicked
* @property {String} reason - The reason for the kick
*/
handleKick(message){
let user = this._users.get(message.args[1])
this._users.delete(message.nick)
this.emit("kick", user, message.nick, message.args[2])
}
/**
* Sends a message to the channel
* @function
* @param {String} message - The message to send
* @author Mackan
*/
sendMessage(message){
this._connection.write(`PRIVMSG ${this._channelName} :${message}\n`)
}
/**
* Sends an action message to the channel
* @function
* @param {String} message - The message to send
* @author Mackan
*/
sendAction(message){
this._connection.write(`PRIVMSG ${this._channelName} :\u0001ACTION ${message}\u0001\n`)
}
/**
* Updates the modes of a user in the channel
* @function
* @param {String} nick - The nickname of the user to update the modes for
* @param {String} mode - What modes to add
*/
mode(nick, mode){
this.sendCommand(`MODE ${this._channelName} ${this._clientData.nick} ${mode}\n`)
}
}
module.exports = Channel