<commit_before>var _ = require('underscore');
var ClearwingNamespace = require('./clearwingnamespace');

/**
 * @constructor
 * @augments ClearwingNamespace
 */
function Channel(network, name) {
	'use strict';

	/** {@link Clearwing} instance */
	this.client = network.client;

	/** {@link Network} instance */
	this.network = network;

	/** {@link User} list */
	this.users = [];

	name = Channel.sanitize(name);

	/**
	 * Lowercase channel name
	 * @private
	 */
	this._name = name.toLowerCase();

	/**
	 * Namespace
	 * @private
	 * @static
	 */
	this._namespace = this.network._namespace.concat({ channel: this._name });

	/* set up data */
	this
		.set('name', name)
		.set('topic', '')
		.set('mode', '')
		.set('joined', false);
}


/**
 * Sanitize channel name
 * @todo Implement RFC-2812 enforcement
 * @param {string} name Channel name
 * @return {string}
 */
Channel.sanitize = function(name) {
	'use strict';

	return name.replace(/^([^#+!&])/, '#$1');
};


Channel.prototype = new ClearwingNamespace();
Channel.prototype.constructor = Channel;


/**
 * Lookup a user by name
 * Note: This function will also create a new {@link User} if one is not found
 * @param {string} user User name
 * @param {function} [ctx] User context
 * @return {User}
 */
Channel.prototype.user = function(user, ctx) {
	'use strict';

	user = this.users.filter(function(n) { return n._name == user.toLowerCase(); }).pop() ||
	       this.users[this.users.push(this.network.user(user)) - 1];

	if (_.isFunction(ctx))
		ctx.call(user, user);

	return user;
};


/**
 * See if a user exists
 * @param {string} user User name
 * @return {bool} True if user exists, false if it does not
 */
Channel.prototype.hasUser = function(user) {
	'use strict';

	return !!this.users.filter(function(n) { return n._name == user.toLowerCase(); }).length;
};


/**
 * Join channel if we aren't already joined
 * @return {this}
 */
Channel.prototype.join = function() {
	'use strict';

	if (!this.get('joined'))
		this.network.send('join', this.get('name'));

	return this;
};


/**
 * Part channel if we're joined
 * @return {this}
 */
Channel.prototype.part = function(message) {
	'use strict';

	if (this.get('joined'))
		this.network.send('part', this.get('name'));

	return this;
};


/**
 * Send a message to the channel
 * @param {string} message Message to send
 * @return {this}
 */
Channel.prototype.message = function(message) {
	'use strict';

	this.network.send('privmsg', this.get('name'), message);
	return this;
};


/**
 * Send a CTCP message to the channel<commit_msg>Add optional channel part message<commit_after>var _ = require('underscore');
var ClearwingNamespace = require('./clearwingnamespace');

/**
 * @constructor
 * @augments ClearwingNamespace
 */
function Channel(network, name) {
	'use strict';

	/** {@link Clearwing} instance */
	this.client = network.client;

	/** {@link Network} instance */
	this.network = network;

	/** {@link User} list */
	this.users = [];

	name = Channel.sanitize(name);

	/**
	 * Lowercase channel name
	 * @private
	 */
	this._name = name.toLowerCase();

	/**
	 * Namespace
	 * @private
	 * @static
	 */
	this._namespace = this.network._namespace.concat({ channel: this._name });

	/* set up data */
	this
		.set('name', name)
		.set('topic', '')
		.set('mode', '')
		.set('joined', false);
}


/**
 * Sanitize channel name
 * @todo Implement RFC-2812 enforcement
 * @param {string} name Channel name
 * @return {string}
 */
Channel.sanitize = function(name) {
	'use strict';

	return name.replace(/^([^#+!&])/, '#$1');
};


Channel.prototype = new ClearwingNamespace();
Channel.prototype.constructor = Channel;


/**
 * Lookup a user by name
 * Note: This function will also create a new {@link User} if one is not found
 * @param {string} user User name
 * @param {function} [ctx] User context
 * @return {User}
 */
Channel.prototype.user = function(user, ctx) {
	'use strict';

	user = this.users.filter(function(n) { return n._name == user.toLowerCase(); }).pop() ||
	       this.users[this.users.push(this.network.user(user)) - 1];

	if (_.isFunction(ctx))
		ctx.call(user, user);

	return user;
};


/**
 * See if a user exists
 * @param {string} user User name
 * @return {bool} True if user exists, false if it does not
 */
Channel.prototype.hasUser = function(user) {
	'use strict';

	return !!this.users.filter(function(n) { return n._name == user.toLowerCase(); }).length;
};


/**
 * Join channel if we aren't already joined
 * @return {this}
 */
Channel.prototype.join = function() {
	'use strict';

	if (!this.get('joined'))
		this.network.send('join', this.get('name'));

	return this;
};


/**
 * Part channel if we're joined
 * @param {string} [message] Part message
 * @return {this}
 */
Channel.prototype.part = function(message) {
	'use strict';

	if (this.get('joined'))
		this.network.send('part', this.get('name'), message);

	return this;
};


/**
 * Send a message to the channel
 * @param {string} message Message to send
 * @return {this}
 */
Channel.prototype.message = function(message) {
	'use strict';

	this.network.send('privmsg', this.get('name'), message);
	return this;
};


/**
 * Send a CTCP message to the channel
{'fraction_non_alphanumeric': 0.17833044148833624, 'fraction_numerical': 0.002313475997686524, 'mean_word_length': 3.7206551410373065, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4773436', 'n_tokens_mistral': 1733, 'n_tokens_neox': 1658, 'n_words': 461}