UNPKG

fair-twitch

Version:

Fair's Twitch API and Chat bot library

322 lines (321 loc) 14.5 kB
"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 __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; var ExpandedEventEmitter_1 = __importDefault(require("./ExpandedEventEmitter")); var v4_1 = __importDefault(require("uuid/v4")); // Wait to notify gift subs in case they are a part of mass gift subs var mysteryGiftTimeout = 5000; // If count is reached, it will call it var giftTimeout = 1000; var SmartTimeout = /** @class */ (function () { function SmartTimeout(callback, time) { this.time = time; this.callback = callback; this.timeout = null; this.start = this.start.bind(this); this.refresh = this.refresh.bind(this); this.clear = this.clear.bind(this); } SmartTimeout.prototype.start = function () { this.timeout = setTimeout(this.callback, this.time); }; SmartTimeout.prototype.clear = function () { if (this.timeout !== null) { clearTimeout(this.timeout); } }; SmartTimeout.prototype.refresh = function (newTime) { if (newTime !== undefined) this.time = newTime; this.clear(); this.start(); }; SmartTimeout.prototype.call = function () { this.clear(); this.callback(); }; return SmartTimeout; }()); var NotificationsEmitter = /** @class */ (function (_super) { __extends(NotificationsEmitter, _super); /** * @param twitchIRC The Twitch IRC client */ function NotificationsEmitter(twitchIRC) { var _this = _super.call(this) || this; _this.twitchIRC = twitchIRC; _this.eventID = v4_1.default(); // We want to collect all the recepients of a mass gift sub under 1 notice // Since all mass gift subs are also displayed as a gift sub and there's no way // to guarantee that 'submysterygift' event triggers before the giftsub events, // we have to wait a short while before displaying the notice, in case a // 'submysterygift' event happens _this.giftSubs = []; _this.massGifters = []; _this.twitchIRC.addListener('usernotice#' + _this.eventID, function (channel, login, message, tags) { var data = { login: login, displayName: tags['display-name'], id: tags.id, timestamp: Number(tags['tmi-sent-ts']), systemMsg: tags['system-msg'].replace(/\\s/g, ' ') }; switch (tags['msg-id']) { case 'sub': { data.tier = tags['msg-param-sub-plan']; _this._emitNotification('sub', channel, data, tags); break; } case 'resub': { data.msg = message; data.months = Number(tags['msg-param-cumulative-months']); data.tier = tags['msg-param-sub-plan']; _this._emitNotification('resub', channel, data, tags); break; } case 'subgift': { data.recepient = { login: tags['msg-param-recipient-user-name'], displayName: tags['msg-param-recipient-display-name'] }; data.msg = message; data.months = Number(tags['msg-param-months']); data.senderCount = Number(tags['msg-param-sender-count']); data.tier = tags['msg-param-sub-plan']; var key = data.login + '#' + channel + '!' + data.tier; var absorbed = false; // First check if there's any mass gifts going on for (var i = 0; i < _this.massGifters.length; i++) { var massGift = _this.massGifters[i]; if (massGift.key === key) { if (massGift.data.recepients.length < massGift.data.massCount) { massGift.data.recepients.push(data.recepient); if (massGift.data.recepients.length >= massGift.data.massCount) { massGift.timeout.call(); } else { // Refresh timeout massGift.timeout.refresh(giftTimeout); } absorbed = true; break; } } } if (!absorbed) { var obj_1 = { key: key, channel: channel, data: data, timeout: new SmartTimeout(function () { _this._emitNotification('giftsub', channel, data, tags); // Remove from list for (var i = 0; i < _this.giftSubs.length; i++) { if (_this.giftSubs[i] === obj_1) { _this.giftSubs.splice(i, 1); break; } } }, giftTimeout) }; obj_1.timeout.start(); _this.giftSubs.push(obj_1); } break; } case 'submysterygift': { data.massCount = Number(tags['msg-param-mass-gift-count']); data.senderCount = Number(tags['msg-param-sender-count']); data.tier = tags['msg-param-sub-plan']; data.recepients = []; var key = data.login + '#' + channel + '!' + data.tier; // Check all sub gifts going on, and add them to this part for (var i = 0; i < _this.giftSubs.length; i++) { var giftSub = _this.giftSubs[i]; if (giftSub.key === key && data.recepient.length < data.massCount) { data.recepients.push(giftSub.data.recepient); giftSub.timeout.clear(); _this.giftSubs.splice(i, 1); i--; } } var obj_2 = { key: key, channel: channel, data: data, timeout: new SmartTimeout(function () { _this._emitNotification('massgiftsub', channel, data, tags); for (var i = 0; i < _this.massGifters.length; i++) { if (_this.massGifters[i] === obj_2) { _this.massGifters.splice(i, 1); break; } } }, mysteryGiftTimeout) }; if (data.recepients.length >= data.massCount) { obj_2.timeout.call(); } else { obj_2.timeout.start(); _this.massGifters.push(obj_2); } break; } } }); _this.twitchIRC.addListener('msg#' + _this.eventID, function (channel, login, message, tags) { if (tags.bits) { var data = { login: login, displayName: tags['display-name'], id: tags.id, timestamp: Number(tags['tmi-sent-ts']), msg: message, bits: Number(tags.bits) }; _this._emitNotification('bits', channel, data, tags); } }); return _this; } /** * Removes all event listeners added from this tracker */ NotificationsEmitter.prototype.dispose = function () { this.twitchIRC.removeIDListeners(this.eventID); }; /** * Emit an 'any' event but also a normal event * @param eventName The name of the event * @param args The args/parameters of the event */ NotificationsEmitter.prototype._emitNotification = function (eventName) { var args = []; for (var _i = 1; _i < arguments.length; _i++) { args[_i - 1] = arguments[_i]; } this.emit.apply(this, ['any', eventName].concat(args)); this.emit.apply(this, [eventName].concat(args)); }; /** * Get a dummy notification object * @param eventName The event name (sub, resub, giftsub, massgiftsub, bits, any) * @param channel The optional target channel (default DummyChannel) * @param overwriteData Will overwrite the final object these keys and values */ NotificationsEmitter.prototype.getDummyNotification = function (eventName, channel, overwriteData) { if (channel === void 0) { channel = 'DummyChannel'; } if (overwriteData === void 0) { overwriteData = {}; } // First generate basic object var nameAffix = getRandomAffix(); var login = 'dummyfan' + nameAffix; var displayName = 'DummyFan' + nameAffix; var obj = { login: login, displayName: displayName, id: v4_1.default(), timestamp: Date.now() }; switch (eventName) { case 'sub': { obj.tier = randomOneOf('Prime', '1000', '2000', '3000'); var tierMsg = obj.tier === 'Prime' ? 'Twitch Prime' : 'Tier ' + obj.tier.charAt(0); obj.systemMsg = obj.displayName + " subscribed with " + tierMsg + "."; break; } case 'resub': { obj.tier = randomOneOf('Prime', '1000', '2000', '3000'); obj.months = 1 + Math.floor(Math.random() * 23); var tierMsg = obj.tier === 'Prime' ? 'Twitch Prime' : 'Tier ' + obj.tier.charAt(0); obj.systemMsg = obj.displayName + " subscribed with " + tierMsg + ". They've subscribed for " + obj.months + " months!"; if (Math.floor(Math.random() * 3) !== 1) { obj.msg = "Dummy message " + getRandomAffix(); } break; } case 'giftsub': { obj.tier = randomOneOf('1000', '2000', '3000'); obj.recepient = getDummyRecepient(); obj.senderCount = Math.max(0, Math.floor(Math.random() * 500) - 200); var systemMsgAffix = obj.senderCount > 1 ? " They have given " + obj.senderCount + " Gift Subs in the channel!" : ''; obj.systemMsg = obj.displayName + " gifted a Tier " + obj.tier.charAt(0) + " sub to " + obj.recepient.displayName + "!" + systemMsgAffix; obj.months = Math.floor(Math.random() * 12); break; } case 'massgiftsub': { obj.tier = randomOneOf('1000', '2000', '3000'); obj.massCount = randomOneOf(5, 5, 5, 10, 10, 100); obj.senderCount = Math.max(0, Math.floor(Math.random() * 500) - 200) + obj.massCount; var community = channel ? channel : 'Unknown'; obj.systemMsg = obj.displayName + " is gifting " + obj.massCount + " Tier " + obj.tier.charAt(0) + " to " + community + "'s community! They've gifted a total of " + obj.senderCount + " in the channel!"; obj.recepients = []; for (var i = 0; i < obj.massCount; i++) { obj.recepients.push(getDummyRecepient()); } break; } case 'bits': { obj.bits = randomOneOf(1, 100, 1000, 10000); obj.msg = "Dummy message " + getRandomAffix() + " cheer" + obj.bits; break; } default: { return this.getDummyNotification(randomOneOf('sub', 'resub', 'giftsub', 'massgiftsub', 'bits')); } } for (var key in overwriteData) { obj[key] = overwriteData[key]; } return obj; }; /** * Emit a dummy notification event (tags will not be included) * @param eventName The event name (sub, resub, giftsub, massgiftsub, bits, any) * @param channel The channel name (optional) * @param overwriteData Will overwrite the final object these keys and values (optional) */ NotificationsEmitter.prototype.sendDummyNotification = function (eventName, channel, overwriteData) { if (eventName === 'any') eventName = randomOneOf('sub', 'resub', 'giftsub', 'massgiftsub', 'bits'); var obj = this.getDummyNotification(eventName, channel, overwriteData); this._emitNotification(eventName, channel, obj); }; return NotificationsEmitter; }(ExpandedEventEmitter_1.default)); function randomOneOf() { var items = []; for (var _i = 0; _i < arguments.length; _i++) { items[_i] = arguments[_i]; } return items[Math.floor(Math.random() * items.length)]; } function getDummyRecepient() { var recipientAffix = getRandomAffix(); return { login: 'dummytarget' + recipientAffix, displayName: 'DummyTarget' + recipientAffix }; } function getRandomAffix() { var affix = ''; for (var i = 0; i < 5; i++) { var num = Math.floor(Math.random() * 10); affix += num; } return affix; } module.exports = NotificationsEmitter;