Socket
Socket
Sign inDemoInstall

tmi.js

Package Overview
Dependencies
38
Maintainers
1
Versions
61
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 0.0.1 to 0.0.2

TODO.md

268

lib/client.js

@@ -8,2 +8,3 @@ var bunyan = require("bunyan");

var utils = require("./utils");
var vow = require("vow");
var webSocket = require("ws");

@@ -34,3 +35,5 @@

// Client instance..
function client(opts) {
var client = function client(opts) {
this.setMaxListeners(0);
this.opts = (typeof opts !== "undefined") ? opts : {};

@@ -72,2 +75,23 @@ this.opts.channels = opts.channels || [];

// Parse emotes..
if (typeof message.tags['emotes'] === 'string') {
var emoticons = message.tags['emotes'].split('/');
var emotes = {};
for (var i = 0; i < emoticons.length; i++) {
var parts = emoticons[i].split(':');
emotes[parts[0]] = parts[1].split(',');
}
message.tags['emotes'] = emotes;
} else { message.tags['emotes'] = null; }
// Transform the IRCv3 tags..
if (message.tags) {
for(var key in message.tags) {
if (typeof message.tags[key] === "boolean") { message.tags[key] = null; }
else if (message.tags[key] === "1") { message.tags[key] = true; }
else if (message.tags[key] === "0") { message.tags[key] = false; }
}
}
// Messages with no prefix..

@@ -139,2 +163,3 @@ if (message.prefix === null) {

self.log.info("[" + message.params[0] + "] This room is now in subscribers-only mode.");
self.emit("subscriber", message.params[0], true);
self.emit("subscribers", message.params[0], true);

@@ -146,2 +171,3 @@ break;

self.log.info("[" + message.params[0] + "] This room is no longer in subscribers-only mode.");
self.emit("subscriber", message.params[0], false);
self.emit("subscribers", message.params[0], false);

@@ -155,2 +181,3 @@ break;

self.emit("slow", message.params[0], true);
self.emit("slowmode", message.params[0], true);
break;

@@ -162,2 +189,3 @@

self.emit("slow", message.params[0], false);
self.emit("slowmode", message.params[0], false);
break;

@@ -175,2 +203,3 @@

self.emit("r9kmode", message.params[0], false);
self.emit("r9kbeta", message.params[0], false);
break;

@@ -242,2 +271,6 @@

break;
case "ROOMSTATE":
self.emit("roomstate", message.params[0], message.tags);
break;

@@ -255,2 +288,8 @@ default:

case "MODE":
if (message.params[1] === "+o") {
self.emit("mod", message.params[0], message.params[2]);
}
else if (message.params[1] === "-o") {
self.emit("unmod", message.params[0], message.params[2]);
}
break;

@@ -303,2 +342,41 @@

}
if (message.tags.username === "twitchnotify") {
// Someone subscribed to a hosted channel. Who cares.
if (message.params[1].indexOf("subscribed to") >= 0) {
//
}
// New subscriber..
else if (message.params[1].indexOf("just subscribed") >= 0) {
self.emit('subscription', message.params[0], message.params[1].split(' ')[0]);
}
// Subanniversary..
else if (message.params[1].indexOf("subscribed") >= 0 && message.params[1].indexOf("in a row") >= 0) {
var splitted = message.params[1].split(' ');
var length = splitted[splitted.length - 5];
self.emit('subanniversary', message.params[0], splitted[0], length);
}
}
else if (message.tags.username === "jtv") {
// Client sent /mods command to channel..
if (message.params[1].indexOf("moderators of this room are") >= 0) {
var splitted = message.params[1].split(':');
var mods = splitted[1].replace(/,/g, '').split(':').toString().toLowerCase().split(' ');
for(var i = mods.length - 1; i >= 0; i--) {
if(mods[i] === '') {
mods.splice(i, 1);
}
}
self.emit('mods', message.params[0], mods);
self.emit('modspromises', message.params[0], mods);
}
// Someone is hosting my channel..
else if (message.params[1].indexOf("is now hosting you") >= 0) {
self.emit('hosted', message.params[0], utils.normalizeUsername(message.params[1].split(' ')[0]));
}
}
break;

@@ -317,3 +395,4 @@

var self = this;
var deferred = vow.defer();
this.reconnect = typeof this.opts.connection.reconnect !== "undefined" ? this.opts.connection.reconnect : false;

@@ -333,2 +412,3 @@ this.server = typeof this.opts.connection.server !== "undefined" ? this.opts.connection.server : "RANDOM";

self._openConnection();
deferred.resolve();
});

@@ -339,3 +419,6 @@ }

this._openConnection();
deferred.resolve();
}
return deferred.promise();
};

@@ -362,2 +445,3 @@

self.log.error("Server is not accepting WebSocket connections. Reconnecting in 10 seconds..");
self.emit("reconnect");
setTimeout(function() { self.connect(self.server + ":" + self.port); }, 10000);

@@ -415,2 +499,3 @@ } else {

var self = this;
// User called .disconnect();

@@ -426,4 +511,5 @@ if (this.wasCloseCalled) {

if (self.reconnect) {
if (this.reconnect) {
this.log.error("Sorry, we were unable to connect to chat. Reconnecting in 10 seconds..");
this.emit("reconnect");
setTimeout(function() { self.connect(self.server + ":" + self.port); }, 10000);

@@ -436,4 +522,72 @@ } else {

// Send a command to the server..
client.prototype._sendCommand = function _sendCommand(channel, command) {
var self = this;
// Promise a result..
return new vow.Promise(function(resolve, reject, notify) {
if (self.usingWebSocket && self.ws !== null && self.ws.readyState !== 2 && self.ws.readyState !== 3 && self.getUsername().indexOf("justinfan") < 0) {
switch (command.toLowerCase()) {
case "/mods":
case ".mods":
self.log.info("Executing command: " + command);
self.once("modspromises", function (channel, mods) {
resolve(mods);
});
self.ws.send("PRIVMSG " + utils.normalizeChannel(channel) + " :" + command);
break;
default:
if (channel !== null) {
self.log.info("[" + utils.normalizeChannel(channel) + "] Executing command: " + command);
self.ws.send("PRIVMSG " + utils.normalizeChannel(channel) + " :" + command);
} else {
self.log.info("Executing command: " + command);
self.ws.send(command);
}
resolve();
break;
}
} else {
reject();
}
});
}
// Send a message to the server..
client.prototype._sendMessage = function _sendMessage(channel, message) {
var self = this;
// Promise a result..
return new vow.Promise(function(resolve, reject, notify) {
if (self.usingWebSocket && self.ws !== null && self.ws.readyState !== 2 && self.ws.readyState !== 3 && self.getUsername().indexOf("justinfan") < 0) {
self.ws.send("PRIVMSG " + utils.normalizeChannel(channel) + " :" + message);
if (message.match(/^\u0001ACTION ([^\u0001]+)\u0001$/)) {
self.log.info("[" + utils.normalizeChannel(channel) + "] *<" + self.getUsername() + ">: " + message.match(/^\u0001ACTION ([^\u0001]+)\u0001$/)[1]);
self.emit("action", utils.normalizeChannel(channel), self.userstate[utils.normalizeChannel(channel)], message.match(/^\u0001ACTION ([^\u0001]+)\u0001$/)[1]);
} else {
self.log.info("[" + utils.normalizeChannel(channel) + "] <" + self.getUsername() + ">: " + message);
self.emit("chat", utils.normalizeChannel(channel), self.userstate[utils.normalizeChannel(channel)], message);
}
resolve();
} else {
reject();
}
});
}
// Get current username..
client.prototype.getUsername = function getUsername() {
return this.username;
};
// Get current options..
client.prototype.getOptions = function getOptions() {
return this.opts;
};
// Disconnect from server..
client.prototype.disconnect = function disconnect() {
var deferred = vow.defer();
if (this.usingWebSocket && this.ws !== null && this.ws.readyState !== 3) {

@@ -443,10 +597,116 @@ this.wasCloseCalled = true;

this.ws.close();
deferred.resolve();
} else {
this.log.error("Cannot disconnect from server. Socket is not opened or connection is already closing.");
deferred.reject();
}
return deferred.promise();
};
client.prototype.action = function action(channel, message) {
message = "\u0001ACTION " + message + "\u0001";
return this._sendMessage(channel, message);
};
client.prototype.ban = function ban(channel, username) {
return this._sendCommand(channel, "/ban " + utils.normalizeUsername(username));
};
client.prototype.clear = function clear(channel) {
return this._sendCommand(channel, "/clear");
};
client.prototype.color = function color(channel, color) {
return this._sendCommand(channel, "/color " + color);
};
client.prototype.commercial = function commercial(channel, seconds) {
seconds = typeof seconds !== 'undefined' ? seconds : 30;
return this._sendCommand(channel, "/commercial " + seconds);
};
client.prototype.host = function host(channel, target) {
return this._sendCommand(channel, "/host " + utils.normalizeUsername(target));
};
client.prototype.join = function join(channel) {
return this._sendCommand(null, "JOIN " + utils.normalizeChannel(channel));
};
client.prototype.mod = function mod(channel, username) {
return this._sendCommand(channel, "/mod " + utils.normalizeUsername(username));
};
client.prototype.mods = function mods(channel) {
return this._sendCommand(channel, "/mods");
};
client.prototype.part = client.prototype.leave = function part(channel) {
return this._sendCommand(null, "PART " + utils.normalizeChannel(channel));
};
client.prototype.ping = function ping() {
return this._sendCommand(null, "PING");
};
client.prototype.r9kbeta = client.prototype.r9kmode = function r9kbeta(channel) {
return this._sendCommand(channel, "/r9kbeta");
};
client.prototype.r9kbetaoff = client.prototype.r9kmodeoff = function r9kbetaoff(channel) {
return this._sendCommand(channel, "/r9kbetaoff");
};
client.prototype.raw = function raw(message) {
return this._sendCommand(null, message);
};
client.prototype.say = function say(channel, message) {
return this._sendMessage(channel, message);
};
client.prototype.slow = client.prototype.slowmode = function slow(channel, seconds) {
seconds = typeof seconds !== 'undefined' ? seconds : 300;
return this._sendCommand(channel, "/seconds " + seconds);
};
client.prototype.slowoff = client.prototype.slowmodeoff = function slowoff(channel) {
return this._sendCommand(channel, "/slowoff");
};
client.prototype.subscribers = function subscribers(channel) {
return this._sendCommand(channel, "/subscribers");
};
client.prototype.subscribersoff = function subscribersoff(channel) {
return this._sendCommand(channel, "/subscribersoff");
};
client.prototype.timeout = function timeout(channel, username, seconds) {
seconds = typeof seconds !== 'undefined' ? seconds : 300;
username = typeof username !== 'undefined' ? username : "Kappa";
return this._sendCommand(channel, "/timeout " + username + " " + seconds);
};
client.prototype.unban = function unban(channel, username) {
return this._sendCommand(channel, "/unban " + utils.normalizeUsername(username));
};
client.prototype.unhost = function unhost(channel) {
return this._sendCommand(channel, "/unhost");
};
client.prototype.unmod = function unmod(channel, username) {
return this._sendCommand(channel, "/unmod " + utils.normalizeUsername(username));
};
// Expose everything, for browser and Node.js / io.js
if (typeof window !== "undefined") {
window.client = client;
window.irc = {};
window.irc.client = client;
} else {
module.exports = client;
}

@@ -7,3 +7,8 @@ var webSocket = require("ws");

if (type === "event" || type === "events") {
var servers = [
"192.16.64.143:80"
];
if (servers.indexOf(ignore) >= 0) { servers.splice(servers.indexOf(ignore), 1); }
return callback(servers[Math.floor(Math.random()*servers.length)]);
}

@@ -18,3 +23,3 @@ else if (type === "group" || type === "groups") {

];
if (servers.indexOf(ignore) >=0) { servers.splice(servers.indexOf(ignore), 1); }
if (servers.indexOf(ignore) >= 0) { servers.splice(servers.indexOf(ignore), 1); }

@@ -21,0 +26,0 @@ return callback(servers[Math.floor(Math.random()*servers.length)]);

10

lib/utils.js

@@ -12,3 +12,3 @@ // Generate a random justinfan username..

// Normalize channel name for Twitch..
// Normalize channel name..
function normalizeChannel(name) {

@@ -19,4 +19,10 @@ if (name.indexOf("#") !== 0) { name = "#" + name; }

// Normalize username..
function normalizeUsername(username) {
return username.replace("#", "").toLowerCase();
}
exports.generateJustinfan = generateJustinfan;
exports.isInteger = isInteger;
exports.normalizeChannel = normalizeChannel;
exports.normalizeChannel = normalizeChannel;
exports.normalizeUsername = normalizeUsername;
{
"name": "tmi.js",
"version": "0.0.1",
"version": "0.0.2",
"description": "Javascript library for the Twitch Messaging Interface.",

@@ -14,2 +14,3 @@ "main": "index.js",

"irc-message": "^3.0.1",
"vow": "^0.4.10",
"ws": "^0.7.2"

@@ -16,0 +17,0 @@ },

# tmi.js - WORK IN PROGRESS
[![Build Status](https://secure.travis-ci.org/Schmoopiie/tmi.js.png?branch=master)](https://travis-ci.org/Schmoopiie/tmi.js) [![Downloads](http://img.shields.io/npm/dm/tmi.js.svg?style=flat)](https://www.npmjs.org/package/tmi.js) [![Npm Version](http://img.shields.io/npm/v/tmi.js.svg?style=flat)](https://www.npmjs.org/package/tmi.js) [![Node Version](https://img.shields.io/node/v/tmi.js.svg?style=flat)](https://www.npmjs.org/package/tmi.js) [![Issues](http://img.shields.io/github/issues/Schmoopiie/tmi.js.svg?style=flat)](https://github.com/Schmoopiie/tmi.js/tmi)
![](http://i.imgur.com/Fb1mUDJ.png)
![](http://i.imgur.com/vsdO7N5.png)
Twitch is a trademark or registered trademark of Twitch Interactive, Inc. in the U.S. and/or other countries. "tmi.js" is not operated by, sponsored by, or affiliated with Twitch Interactive, Inc. in any way.

@@ -6,0 +7,0 @@

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc