twitch-js
Version:
Javascript library for the Twitch Messaging Interface.
1,139 lines • 65.3 kB
JavaScript
"use strict";
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
var __read = (this && this.__read) || function (o, n) {
var m = typeof Symbol === "function" && o[Symbol.iterator];
if (!m) return o;
var i = m.call(o), r, ar = [], e;
try {
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
}
catch (error) { e = { error: error }; }
finally {
try {
if (r && !r.done && (m = i["return"])) m.call(i);
}
finally { if (e) throw e.error; }
}
return ar;
};
var __spread = (this && this.__spread) || function () {
for (var ar = [], i = 0; i < arguments.length; i++) ar = ar.concat(__read(arguments[i]));
return ar;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
var _a;
Object.defineProperty(exports, "__esModule", { value: true });
var eventemitter3_1 = __importDefault(require("eventemitter3"));
var p_event_1 = __importDefault(require("p-event"));
var uniq_1 = __importDefault(require("lodash/uniq"));
var twitch_1 = require("../twitch");
var logger_1 = __importDefault(require("../utils/logger"));
var Client_1 = __importDefault(require("../Client"));
var client_types_1 = require("../Client/client-types");
var parsers = __importStar(require("./utils/parsers"));
var sanitizers = __importStar(require("./utils/chat-sanitizers"));
var validators = __importStar(require("./utils/chat-validators"));
var constants = __importStar(require("./chat-constants"));
var Errors = __importStar(require("./chat-errors"));
var chat_types_1 = require("./chat-types");
/**
* Interact with Twitch chat.
*
* ## Connecting
*
* ```js
* const token = 'cfabdegwdoklmawdzdo98xt2fo512y'
* const username = 'ronni'
* const { chat } = new TwitchJs({ token, username })
*
* chat.connect().then(globalUserState => {
* // Do stuff ...
* })
* ```
*
* **Note:** Connecting with a `token` and a `username` is optional.
*
* Once connected, `chat.userState` will contain
* [[GlobalUserStateTags|global user state information]].
*
* ## Joining a channel
*
* ```js
* const channel = '#dallas'
*
* chat.join(channel).then(channelState => {
* // Do stuff with channelState...
* })
* ```
*
* After joining a channel, `chat.channels[channel]` will contain
* [[ChannelState|channel state information]].
*
* ## Listening for events
*
* ```js
* // Listen to all events
* chat.on('*', message => {
* // Do stuff with message ...
* })
*
* // Listen to private messages
* chat.on('PRIVMSG', privateMessage => {
* // Do stuff with privateMessage ...
* })
* ```
*
* Events are nested; for example:
*
* ```js
* // Listen to subscriptions only
* chat.on('USERNOTICE/SUBSCRIPTION', userStateMessage => {
* // Do stuff with userStateMessage ...
* })
*
* // Listen to all user notices
* chat.on('USERNOTICE', userStateMessage => {
* // Do stuff with userStateMessage ...
* })
* ```
*
* For added convenience, TwitchJS also exposes event constants.
*
* ```js
* const { chat } = new TwitchJs({ token, username })
*
* // Listen to all user notices
* chat.on(chat.events.USER_NOTICE, userStateMessage => {
* // Do stuff with userStateMessage ...
* })
* ```
*
* ## Sending messages
*
* To send messages, [Chat] must be initialized with a `username` and a
* [`token`](../#authentication) with `chat_login` scope.
*
* All messages sent to Twitch are automatically rate-limited according to
* [Twitch Developer documentation](https://dev.twitch.tv/docs/irc/guide/#command--message-limits).
*
* ### Speak in channel
*
* ```js
* const channel = '#dallas'
*
* chat
* .say(channel, 'Kappa Keepo Kappa')
* // Optionally ...
* .then(() => {
* // ... do stuff on success ...
* })
* ```
*
* ### Send command to channel
*
* All chat commands are currently supported and exposed as camel-case methods. For
* example:
*
* ```js
* const channel = '#dallas'
*
* // Enable followers-only for 1 week
* chat.followersOnly(channel, '1w')
*
* // Ban ronni
* chat.ban(channel, 'ronni')
* ```
*
* **Note:** `Promise`-resolves for each commands are
* [planned](https://github.com/twitch-devs/twitch-js/issues/87).
*
* ## Joining multiple channels
*
* ```js
* const channels = ['#dallas', '#ronni']
*
* Promise.all(channels.map(channel => chat.join(channel))).then(channelStates => {
* // Listen to all messages from #dallas only
* chat.on('#dallas', message => {
* // Do stuff with message ...
* })
*
* // Listen to private messages from #dallas and #ronni
* chat.on('PRIVMSG', privateMessage => {
* // Do stuff with privateMessage ...
* })
*
* // Listen to private messages from #dallas only
* chat.on('PRIVMSG/#dallas', privateMessage => {
* // Do stuff with privateMessage ...
* })
*
* // Listen to all private messages from #ronni only
* chat.on('PRIVMSG/#ronni', privateMessage => {
* // Do stuff with privateMessage ...
* })
* })
* ```
*
* ### Broadcasting to all channels
*
* ```js
* chat
* .broadcast('Kappa Keepo Kappa')
* // Optionally ...
* .then(userStateMessages => {
* // ... do stuff with userStateMessages on success ...
* })
* ```
*/
var Chat = /** @class */ (function (_super) {
__extends(Chat, _super);
/**
* Chat constructor.
*/
function Chat(options) {
var _this = _super.call(this) || this;
_this._internalEmitter = new eventemitter3_1.default();
_this._readyState = chat_types_1.ChatReadyStates.WAITING;
_this._connectionAttempts = 0;
_this._channelState = {};
_this._isAuthenticated = false;
_this._handleConnect = function () {
var connectProfiler = _this._log.profile('connecting ...');
// Connect ...
_this._readyState = chat_types_1.ChatReadyStates.CONNECTING;
// Increment connection attempts.
_this._connectionAttempts += 1;
if (_this._client) {
// Remove all listeners, just in case.
_this._client.removeAllListeners();
}
// Create client and connect.
_this._client = new Client_1.default(_this._options);
// Handle disconnects.
_this._client.once(client_types_1.ClientEvents.DISCONNECTED, function () {
return _this._internalEmitter.emit(constants.DISCONNECT);
});
// Listen for reconnects.
_this._client.once(client_types_1.ClientEvents.RECONNECT, function () {
return _this._internalEmitter.emit(constants.RECONNECT);
});
// Listen for authentication failure.
_this._client.once(client_types_1.ClientEvents.AUTHENTICATION_FAILED, _this._handleClientAuthenticationFailure);
// Once the client is connected, resolve ...
_this._client.once(client_types_1.ClientEvents.CONNECTED, function (message) {
_this._readyState = chat_types_1.ChatReadyStates.CONNECTED;
if (_this._options.token && _this._options.username) {
var globalUserStateMessage = parsers.globalUserStateMessage(message);
_this._globalUserState = globalUserStateMessage.tags;
_this._isAuthenticated = true;
}
_this._handleJoinsAfterConnect();
_this._internalEmitter.emit(constants.CONNECTED);
connectProfiler.done('connected');
});
// Handle messages.
_this._client.on(client_types_1.ClientEvents.ALL, _this._handleClientMessage, _this);
};
_this._handleDisconnect = function () {
var _a, _b;
_this._log.info('disconnecting ...');
_this._readyState = chat_types_1.ChatReadyStates.DISCONNECTING;
_this._isAuthenticated = false;
_this._clearChannelState();
(_a = _this._client) === null || _a === void 0 ? void 0 : _a.once(client_types_1.ClientEvents.DISCONNECTED, function () {
_this._internalEmitter.emit(constants.DISCONNECTED);
_this._readyState = chat_types_1.ChatReadyStates.DISCONNECTED;
_this._log.info('disconnected');
});
(_b = _this._client) === null || _b === void 0 ? void 0 : _b.disconnect();
};
_this._handleReconnect = function () {
var _a, _b, _c;
_this._log.info('reconnecting ...');
_this._readyState = chat_types_1.ChatReadyStates.RECONNECTING;
(_a = _this._client) === null || _a === void 0 ? void 0 : _a.removeAllListeners();
(_b = _this._client) === null || _b === void 0 ? void 0 : _b.once(client_types_1.ClientEvents.DISCONNECTED, function () {
_this._internalEmitter.emit(constants.CONNECT);
});
(_c = _this._client) === null || _c === void 0 ? void 0 : _c.disconnect();
};
_this._handleClientAuthenticationFailure = function (originError) { return __awaiter(_this, void 0, void 0, function () {
var token, reAuthenticationError_1, error, authenticationError;
var _a, _b;
return __generator(this, function (_c) {
switch (_c.label) {
case 0:
_c.trys.push([0, 2, , 3]);
this._log.info('retrying ...');
return [4 /*yield*/, ((_b = (_a = this._options).onAuthenticationFailure) === null || _b === void 0 ? void 0 : _b.call(_a))];
case 1:
token = _c.sent();
if (token) {
this._log.info('re-authenticating ...');
this._options = __assign(__assign({}, this._options), { token: token });
}
this._internalEmitter.emit(constants.CONNECT);
return [3 /*break*/, 3];
case 2:
reAuthenticationError_1 = _c.sent();
error = reAuthenticationError_1 || originError;
authenticationError = new Errors.AuthenticationError((originError === null || originError === void 0 ? void 0 : originError.message) || 'Login authentication failed', originError);
this._internalEmitter.emit(twitch_1.Events.ERROR_ENCOUNTERED, authenticationError);
this._log.error(error, 'authentication failed');
return [3 /*break*/, 3];
case 3: return [2 /*return*/];
}
});
}); };
_this._options = validators.chatOptions(options);
// Create logger.
_this._log = logger_1.default(__assign({ name: 'Chat' }, _this._options.log));
_this._internalEmitter.on(constants.CONNECT, _this._handleConnect);
_this._internalEmitter.on(constants.DISCONNECT, _this._handleDisconnect);
_this._internalEmitter.on(constants.RECONNECT, _this._handleReconnect);
return _this;
}
/**
* Connect to Twitch.
*/
Chat.prototype.connect = function () {
if (this._connectionInProgress) {
return this._connectionInProgress;
}
this._connectionInProgress = p_event_1.default(this._internalEmitter, constants.CONNECTED, {
rejectionEvents: [twitch_1.Events.ERROR_ENCOUNTERED],
timeout: this._options.connectionTimeout,
});
this._internalEmitter.emit(constants.CONNECT);
return this._connectionInProgress;
};
/**
* Updates the client options after instantiation.
* To update `token` or `username`, use `reconnect()`.
*/
Chat.prototype.updateOptions = function (options) {
var _a = this._options, token = _a.token, username = _a.username;
this._options = validators.chatOptions(__assign(__assign({}, options), { token: token, username: username }));
};
/**
* Send a raw message to Twitch.
*/
Chat.prototype.send = function (message, options) {
if (!this._client) {
throw new Errors.ChatError('Not connected');
}
return this._client.send(message, options);
};
/**
* Disconnected from Twitch.
*/
Chat.prototype.disconnect = function () {
if (this._connectionInProgress) {
this._connectionInProgress.cancel();
this._connectionInProgress = undefined;
}
this._disconnectionInProgress = p_event_1.default(this._internalEmitter, constants.DISCONNECTED, { timeout: this._options.connectionTimeout }).catch();
this._internalEmitter.emit(constants.DISCONNECT);
return this._disconnectionInProgress;
};
/**
* Reconnect to Twitch, providing new options to the client.
*/
Chat.prototype.reconnect = function (options) {
if (this._reconnectionInProgress) {
return this._reconnectionInProgress;
}
if (options) {
this._options = validators.chatOptions(__assign(__assign({}, this._options), options));
}
this._reconnectionInProgress = p_event_1.default(this._internalEmitter, constants.CONNECTED, {
timeout: this._options.connectionTimeout,
});
this._internalEmitter.emit(constants.RECONNECT);
return this._reconnectionInProgress;
};
/**
* Join a channel.
*
* @example <caption>Joining #dallas</caption>
* const channel = '#dallas'
*
* chat.join(channel).then(channelState => {
* // Do stuff with channelState...
* })
*
* @example <caption>Joining multiple channels</caption>
* const channels = ['#dallas', '#ronni']
*
* Promise.all(channels.map(channel => chat.join(channel)))
* .then(channelStates => {
* // Listen to all PRIVMSG
* chat.on('PRIVMSG', privateMessage => {
* // Do stuff with privateMessage ...
* })
*
* // Listen to PRIVMSG from #dallas ONLY
* chat.on('PRIVMSG/#dallas', privateMessage => {
* // Do stuff with privateMessage ...
* })
* // Listen to all PRIVMSG from #ronni ONLY
* chat.on('PRIVMSG/#ronni', privateMessage => {
* // Do stuff with privateMessage ...
* })
* })
*/
Chat.prototype.join = function (channel) {
return __awaiter(this, void 0, void 0, function () {
var joinProfiler, _a, roomState, userState, channelState;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
channel = validators.channel(channel);
joinProfiler = this._log.profile("joining " + channel);
return [4 /*yield*/, Promise.all([
p_event_1.default(
// @ts-expect-error EventTypes breaks this
this, twitch_1.Commands.ROOM_STATE + "/" + channel),
this._isAuthenticated
? p_event_1.default(
// @ts-expect-error EventTypes breaks this
this, twitch_1.Commands.USER_STATE + "/" + channel)
: undefined,
this.send(twitch_1.Commands.JOIN + " " + channel),
])];
case 1:
_a = __read.apply(void 0, [_b.sent(), 2]), roomState = _a[0], userState = _a[1];
channelState = {
roomState: roomState.tags,
userState: userState ? userState.tags : undefined,
};
this._setChannelState(roomState.channel, channelState);
joinProfiler.done("Joined " + channel);
return [2 /*return*/, channelState];
}
});
});
};
/**
* Depart from a channel.
*/
Chat.prototype.part = function (channel) {
channel = validators.channel(channel);
this._log.info("parting " + channel);
this._removeChannelState(channel);
return this.send(twitch_1.Commands.PART + " " + channel);
};
/**
* Send a message to a channel.
*/
Chat.prototype.say = function (channel, message, options) {
var _a, _b;
if (options === void 0) { options = {}; }
return __awaiter(this, void 0, void 0, function () {
var isCommand, isModerator, resolver;
return __generator(this, function (_c) {
switch (_c.label) {
case 0:
if (!this._isAuthenticated) {
throw new Errors.ChatError('To send messages, please connect with a token and username');
}
channel = validators.channel(channel);
isCommand = message.startsWith('/');
isModerator = ((_b = (_a = this._channelState[channel]) === null || _a === void 0 ? void 0 : _a.userState) === null || _b === void 0 ? void 0 : _b.mod) === '1';
if (isCommand) {
this._log.info("CMD/" + channel + " :" + message);
}
else {
this._log.info("PRIVMSG/" + channel + " :" + message);
}
resolver = isCommand
? // Commands do not result in USERSTATE messages
Promise.resolve()
: p_event_1.default(
// @ts-expect-error EventTypes breaks this
this, twitch_1.Commands.USER_STATE + "/" + channel);
return [4 /*yield*/, Promise.all([
resolver,
this.send(twitch_1.Commands.PRIVATE_MESSAGE + " " + channel + " :" + message, __assign({ isModerator: isModerator }, options)),
])];
case 1:
_c.sent();
return [2 /*return*/];
}
});
});
};
/**
* Broadcast message to all connected channels.
*/
Chat.prototype.broadcast = function (message) {
return __awaiter(this, void 0, void 0, function () {
var _this = this;
return __generator(this, function (_a) {
if (!this._isAuthenticated) {
throw new Errors.ChatError('To broadcast, please connect with a token and username');
}
return [2 /*return*/, this._getChannels().map(function (channel) { return _this.say(channel, message); })];
});
});
};
/**
* This command will allow you to permanently ban a user from the chat room.
*/
Chat.prototype.ban = function (channel, username) {
return __awaiter(this, void 0, void 0, function () {
var message, _a, notice;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
channel = validators.channel(channel);
message = "/" + twitch_1.ChatCommands.BAN + " " + username;
return [4 /*yield*/, Promise.all([
p_event_1.default(
// @ts-expect-error EventTypes breaks this
this, [
chat_types_1.NoticeCompounds.BAN_SUCCESS + "/" + channel,
chat_types_1.NoticeCompounds.ALREADY_BANNED + "/" + channel,
]),
this.say(channel, message),
])];
case 1:
_a = __read.apply(void 0, [_b.sent(), 1]), notice = _a[0];
return [2 /*return*/, notice];
}
});
});
};
/**
* This command will allow you to block all messages from a specific user in
* chat and whispers if you do not wish to see their comments.
*/
Chat.prototype.block = function (channel, username) {
return __awaiter(this, void 0, void 0, function () {
var message;
return __generator(this, function (_a) {
channel = validators.channel(channel);
message = "/" + twitch_1.ChatCommands.BLOCK + " " + username;
return [2 /*return*/, this.say(channel, message)];
});
});
};
/**
* Single message removal on a channel.
*/
Chat.prototype.delete = function (channel, targetMessageId) {
return __awaiter(this, void 0, void 0, function () {
var message;
return __generator(this, function (_a) {
channel = validators.channel(channel);
message = "/" + twitch_1.ChatCommands.DELETE + " " + targetMessageId;
return [2 /*return*/, this.say(channel, message)];
});
});
};
/**
* This command will allow the Broadcaster and chat moderators to completely
* wipe the previous chat history.
*/
Chat.prototype.clear = function (channel) {
return __awaiter(this, void 0, void 0, function () {
var message, _a, notice;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
channel = validators.channel(channel);
message = "/" + twitch_1.ChatCommands.CLEAR;
return [4 /*yield*/, Promise.all([
p_event_1.default(
// @ts-expect-error EventTypes breaks this
this, [twitch_1.Commands.CLEAR_CHAT + "/" + channel]),
this.say(channel, message),
])];
case 1:
_a = __read.apply(void 0, [_b.sent(), 1]), notice = _a[0];
return [2 /*return*/, notice];
}
});
});
};
/**
* Allows you to change the color of your username.
*/
Chat.prototype.color = function (channel, color) {
return __awaiter(this, void 0, void 0, function () {
var message, _a, notice;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
channel = validators.channel(channel);
message = "/" + twitch_1.ChatCommands.COLOR + " " + color;
return [4 /*yield*/, Promise.all([
p_event_1.default(
// @ts-expect-error EventTypes breaks this
this, [chat_types_1.NoticeCompounds.COLOR_CHANGED + "/" + channel]),
this.say(channel, message),
])];
case 1:
_a = __read.apply(void 0, [_b.sent(), 1]), notice = _a[0];
return [2 /*return*/, notice];
}
});
});
};
/**
* An Affiliate and Partner command that runs a commercial for all of your
* viewers.
*/
Chat.prototype.commercial = function (channel, length) {
return __awaiter(this, void 0, void 0, function () {
var message, _a, notice;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
channel = validators.channel(channel);
message = "/" + twitch_1.ChatCommands.COMMERCIAL + " " + length;
return [4 /*yield*/, Promise.all([
p_event_1.default(
// @ts-expect-error EventTypes breaks this
this, [chat_types_1.NoticeCompounds.COMMERCIAL_SUCCESS + "/" + channel]),
this.say(channel, message),
])];
case 1:
_a = __read.apply(void 0, [_b.sent(), 1]), notice = _a[0];
return [2 /*return*/, notice];
}
});
});
};
/**
* This command allows you to set your room so only messages that are 100%
* emotes are allowed.
*/
Chat.prototype.emoteOnly = function (channel) {
return __awaiter(this, void 0, void 0, function () {
var message, _a, notice;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
channel = validators.channel(channel);
message = "/" + twitch_1.ChatCommands.EMOTE_ONLY;
return [4 /*yield*/, Promise.all([
p_event_1.default(
// @ts-expect-error EventTypes breaks this
this, [
chat_types_1.NoticeCompounds.EMOTE_ONLY_ON + "/" + channel,
chat_types_1.NoticeCompounds.ALREADY_EMOTE_ONLY_ON + "/" + channel,
]),
this.say(channel, message),
])];
case 1:
_a = __read.apply(void 0, [_b.sent(), 1]), notice = _a[0];
return [2 /*return*/, notice];
}
});
});
};
/**
* This command allows you to disable emote only mode if you previously
* enabled it.
*/
Chat.prototype.emoteOnlyOff = function (channel) {
return __awaiter(this, void 0, void 0, function () {
var message, _a, notice;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
channel = validators.channel(channel);
message = "/" + twitch_1.ChatCommands.EMOTE_ONLY_OFF;
return [4 /*yield*/, Promise.all([
p_event_1.default(
// @ts-expect-error EventTypes breaks this
this, [
chat_types_1.NoticeCompounds.EMOTE_ONLY_OFF + "/" + channel,
chat_types_1.NoticeCompounds.ALREADY_EMOTE_ONLY_OFF + "/" + channel,
]),
this.say(channel, message),
])];
case 1:
_a = __read.apply(void 0, [_b.sent(), 1]), notice = _a[0];
return [2 /*return*/, notice];
}
});
});
};
/**
* This command allows you or your mods to restrict chat to all or some of
* your followers, based on how long they’ve followed.
* @param period - Follow time from 0 minutes (all followers) to 3 months.
*/
Chat.prototype.followersOnly = function (channel, period) {
return __awaiter(this, void 0, void 0, function () {
var message, _a, notice;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
channel = validators.channel(channel);
message = "/" + twitch_1.ChatCommands.FOLLOWERS_ONLY + " " + period;
return [4 /*yield*/, Promise.all([
p_event_1.default(
// @ts-expect-error EventTypes breaks this
this, [
chat_types_1.NoticeCompounds.FOLLOWERS_ONZERO + "/" + channel,
chat_types_1.NoticeCompounds.FOLLOWERS_ON + "/" + channel,
]),
this.say(channel, message),
])];
case 1:
_a = __read.apply(void 0, [_b.sent(), 1]), notice = _a[0];
return [2 /*return*/, notice];
}
});
});
};
/**
* This command will disable followers only mode if it was previously enabled
* on the channel.
*/
Chat.prototype.followersOnlyOff = function (channel) {
return __awaiter(this, void 0, void 0, function () {
var message, _a, notice;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
channel = validators.channel(channel);
message = "/" + twitch_1.ChatCommands.FOLLOWERS_ONLY_OFF;
return [4 /*yield*/, Promise.all([
p_event_1.default(
// @ts-expect-error EventTypes breaks this
this, [chat_types_1.NoticeCompounds.FOLLOWERS_OFF + "/" + channel]),
this.say(channel, message),
])];
case 1:
_a = __read.apply(void 0, [_b.sent(), 1]), notice = _a[0];
return [2 /*return*/, notice];
}
});
});
};
Chat.prototype.help = function (channel) {
return __awaiter(this, void 0, void 0, function () {
var message, _a, notice;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
channel = validators.channel(channel);
message = "/" + twitch_1.ChatCommands.HELP;
return [4 /*yield*/, Promise.all([
p_event_1.default(
// @ts-expect-error EventTypes breaks this
this, [chat_types_1.NoticeCompounds.CMDS_AVAILABLE + "/" + channel]),
this.say(channel, message),
])];
case 1:
_a = __read.apply(void 0, [_b.sent(), 1]), notice = _a[0];
return [2 /*return*/, notice];
}
});
});
};
/**
* This command will allow you to host another channel on yours.
*/
Chat.prototype.host = function (channel, hostChannel) {
return __awaiter(this, void 0, void 0, function () {
var message, _a, notice;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
channel = validators.channel(channel);
message = "/" + twitch_1.ChatCommands.HOST + " " + hostChannel;
return [4 /*yield*/, Promise.all([
p_event_1.default(
// @ts-expect-error EventTypes breaks this
this, [chat_types_1.NoticeCompounds.HOST_ON + "/" + channel]),
this.say(channel, message),
])];
case 1:
_a = __read.apply(void 0, [_b.sent(), 1]), notice = _a[0];
return [2 /*return*/, notice];
}
});
});
};
/**
* Adds a stream marker (with an optional description, max 140 characters) at
* the current timestamp. You can use markers in the Highlighter for easier
* editing.
*/
Chat.prototype.marker = function (channel, description) {
return __awaiter(this, void 0, void 0, function () {
var message;
return __generator(this, function (_a) {
channel = validators.channel(channel);
message = "/" + twitch_1.ChatCommands.MARKER + " " + description.slice(0, 140);
return [2 /*return*/, this.say(channel, message)];
});
});
};
/**
* This command will color your text based on your chat name color.
*/
Chat.prototype.me = function (channel, text) {
return __awaiter(this, void 0, void 0, function () {
var message;
return __generator(this, function (_a) {
channel = validators.channel(channel);
message = "/" + twitch_1.ChatCommands.ME + " " + text;
return [2 /*return*/, this.say(channel, message)];
});
});
};
/**
* This command will allow you to promote a user to a channel moderator.
*/
Chat.prototype.mod = function (channel, username) {
return __awaiter(this, void 0, void 0, function () {
var message, _a, notice;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
channel = validators.channel(channel);
message = "/" + twitch_1.ChatCommands.MOD + " " + username;
return [4 /*yield*/, Promise.all([
p_event_1.default(
// @ts-expect-error EventTypes breaks this
this, [chat_types_1.NoticeCompounds.MOD_SUCCESS + "/" + channel]),
this.say(channel, message),
])];
case 1:
_a = __read.apply(void 0, [_b.sent(), 1]), notice = _a[0];
return [2 /*return*/, notice];
}
});
});
};
/**
* This command will display a list of all chat moderators for that specific
* channel.
*/
Chat.prototype.mods = function (channel) {
return __awaiter(this, void 0, void 0, function () {
var message, _a, notice;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
channel = validators.channel(channel);
message = "/" + twitch_1.ChatCommands.MODS;
return [4 /*yield*/, Promise.all([
p_event_1.default(
// @ts-expect-error EventTypes breaks this
this, [chat_types_1.NoticeCompounds.ROOM_MODS + "/" + channel]),
this.say(channel, message),
])];
case 1:
_a = __read.apply(void 0, [_b.sent(), 1]), notice = _a[0];
return [2 /*return*/, notice];
}
});
});
};
/**
* @deprecated
*/
Chat.prototype.r9K = function (channel) {
return __awaiter(this, void 0, void 0, function () {
var message, _a, notice;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
channel = validators.channel(channel);
message = "/" + twitch_1.ChatCommands.R9K;
return [4 /*yield*/, Promise.all([
p_event_1.default(
// @ts-expect-error EventTypes breaks this
this, [
chat_types_1.NoticeCompounds.R9K_ON + "/" + channel,
chat_types_1.NoticeCompounds.ALREADY_R9K_ON + "/" + channel,
]),
this.say(channel, message),
])];
case 1:
_a = __read.apply(void 0, [_b.sent(), 1]), notice = _a[0];
return [2 /*return*/, notice];
}
});
});
};
/**
* @deprecated
*/
Chat.prototype.r9KOff = function (channel) {
return __awaiter(this, void 0, void 0, function () {
var message, _a, notice;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
channel = validators.channel(channel);
message = "/" + twitch_1.ChatCommands.R9K_OFF;
return [4 /*yield*/, Promise.all([
p_event_1.default(
// @ts-expect-error EventTypes breaks this
this, [
chat_types_1.NoticeCompounds.R9K_OFF + "/" + channel,
chat_types_1.NoticeCompounds.ALREADY_R9K_OFF + "/" + channel,
]),
this.say(channel, message),
])];
case 1:
_a = __read.apply(void 0, [_b.sent(), 1]), notice = _a[0];
return [2 /*return*/, notice];
}
});
});
};
/**
* This command will send the viewer to another live channel.
*/
Chat.prototype.raid = function (channel, raidChannel) {
return __awaiter(this, void 0, void 0, function () {
var message;
return __generator(this, function (_a) {
channel = validators.channel(channel);
message = "/" + twitch_1.ChatCommands.RAID + " " + raidChannel;
return [2 /*return*/, this.say(channel, message)];
});
});
};
/**
* This command allows you to set a limit on how often users in the chat room
* are allowed to send messages (rate limiting).
*/
Chat.prototype.slow = function (channel, seconds) {
return __awaiter(this, void 0, void 0, function () {
var message, _a, notice;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
channel = validators.channel(channel);
message = "/" + twitch_1.ChatCommands.SLOW + " " + seconds;
return [4 /*yield*/, Promise.all([
p_event_1.default(
// @ts-expect-error EventTypes breaks this
this, [chat_types_1.NoticeCompounds.SLOW_ON + "/" + channel]),
this.say(channel, message),
])];
case 1:
_a = __read.apply(void 0, [_b.sent(), 1]), notice = _a[0];
return [2 /*return*/, notice];
}
});
});
};
/**
* This command allows you to disable slow mode if you had previously set it.
*/
Chat.prototype.slowOff = function (channel) {
return __awaiter(this, void 0, void 0, function () {
var message, _a, notice;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
channel = validators.channel(channel);
message = "/" + twitch_1.ChatCommands.SLOW_OFF;
return [4 /*yield*/, Promise.all([
p_event_1.default(
// @ts-expect-error EventTypes breaks this
this, [chat_types_1.NoticeCompounds.SLOW_OFF + "/" + channel]),
this.say(channel, message),
])];
case 1:
_a = __read.apply(void 0, [_b.sent(), 1]), notice = _a[0];
return [2 /*return*/, notice];
}
});
});
};
/**
* This command allows you to set your room so only users subscribed to you
* can talk in the chat room. If you don't have the subscription feature it
* will only allow the Broadcaster and the channel moderators to talk in the
* chat room.
*/
Chat.prototype.subscribers = function (channel) {
return __awaiter(this, void 0, void 0, function () {
var message, _a, notice;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
channel = validators.channel(channel);
message = "/" + twitch_1.ChatCommands.SUBSCRIBERS;
return [4 /*yield*/, Promise.all([
p_event_1.default(
// @ts-expect-error EventTypes breaks this
this, [
chat_types_1.NoticeCompounds.SUBS_ON + "/" + channel,
chat_types_1.NoticeCompounds.ALREADY_SUBS_ON + "/" + channel,
]),
this.say(channel, message),
])];
case 1:
_a = __read.apply(void 0, [_b.sent(), 1]), notice = _a[0];
return [2 /*return*/, notice];
}
});
});
};
/**
* This command allows you to disable subscribers only chat room if you
* previously enabled it.
*/
Chat.prototype.subscribersOff = function (channel) {
return __awaiter(this, void 0, void 0, function () {
var message, _a, notice;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
channel = validators.channel(channel);
message = "/" + twitch_1.ChatCommands.SUBSCRIBERS_OFF;
return [4 /*yield*/, Promise.all([
p_event_1.default(
// @ts-expect-error EventTypes breaks this
this, [
chat_types_1.NoticeCompounds.SUBS_OFF + "/" + channel,
chat_types_1.NoticeCompounds.ALREADY_SUBS_OFF + "/" + channel,
]),
this.say(channel, message),
])];
case 1:
_a = __read.apply(void 0, [_b.sent(), 1]), notice = _a[0];
return [2 /*return*/, notice];
}
});
});
};
/**
* This command allows you to temporarily ban someone from the chat room for
* 10 minutes by default. This will be indicated to yourself and the
* temporarily banned subject in chat on a successful temporary ban. A new
* timeout command will overwrite an old one.
*/
Chat.prototype.timeout = function (channel, username, timeout) {
return __awaiter(this, void 0, void 0, function () {
var timeoutArg, message, _a, notice;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
channel = validators.channel(channel);
timeoutArg = timeout ? " " + timeout : '';
message = "/" + twitch_1.ChatCommands.TIMEOUT + " " + username + timeoutArg;
return [4 /*yield*/, Promise.all([
p_event_1.default(
// @ts-expect-error EventTypes breaks this
this, [chat_types_1.NoticeCompounds.TIMEOUT_SUCCESS + "/" + channel]),
this.say(channel, message),
])];
case 1:
_a = __read.apply(void 0, [_b.sent(), 1]), notice = _a[0];
return [2 /*return*/, notice];
}
});
});
};
/**
* This command will allow you to lift a permanent ban on a user from the
* chat room. You can also use this command to end a ban early; this also
* applies to timeouts.
*/
Chat.prototype.unban = function (channel, username) {
return __awaiter(this, void 0, void 0, function () {
var message, _a, notice;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
channel = validators.channel(channel);
message = "/" + twitch_1.ChatCommands.UNBAN + " " + username;
return [4 /*yield*/, Promise.all([
p_event_1.default(
// @ts-expect-error EventTypes breaks this
this, [chat_types_1.N