omegle-node
Version:
Node.js API for Omegle
311 lines (310 loc) • 9.85 kB
JavaScript
//jshint node:true
//jshint esversion:6
var request = require('request');
var ee = require('events').EventEmitter;
var util = require('util');
var qs = require('querystring');
var Omegle = function () {
ee.call(this);
this.useragent = 'Mozilla/5.0 (Windows NT 10.0; WOW64; rv:47.0) Gecko/20100101 Firefox/47.0';
this.language = 'en';
var url = 'front1.omegle.com';
var workingServers=[];
var gotID = false;
var isConnected = false;
var _this = this;
var lastEvent = ''; //stopLookingForCommonLikes only works when this is set to 'waiting'.
var id = '';
var typing = false;
var challenge = ''; // to store recaptcha challenge.
var challengeLink = '';
//to check if the client is connected to the server
this.connected = function () {
return isConnected;
};
var randID = function () {
var charset = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890';
var str = '';
for (var i = 0; i < 8; ++i) str += charset.charAt(Math.floor((Math.random() * (charset.length + 1))));
return str;
};
var getResponse = function (path, data, callback, method = 'POST') {
var qsArr = ['/status', '/start']; //these paths use qs, others take urlencoded data.
var options = {
url: 'https://' + url + path,
headers: {
'User-Agent': this.useragent,
'Connection': 'keep-alive',
'Referer': 'http://www.omegle.com',
'Origin': 'http://www.omegle.com',
'Host': url,
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': 0
},
method: method
};
if (qsArr.indexOf(path) > -1) {
options['qs'] = data;
}
else {
options.headers['Content-Length'] = qs.stringify(data).length;
options['form'] = qs.stringify(data);
}
request(options, function (error, response, body) {
if (!error && response.statusCode == 200) {
if(workingServers.indexOf(url) < 0){
workingServers.push(url);
}
return callback(body, null);
}
else {
var index = workingServers.indexOf(url);
if (index > -1) {
workingServers.splice(index, 1); //so that we don't use it again
}
return callback(false, error);
}
});
};
this.connect = function (topics = false) {
this.updateServer();
var data = {
rcs: 1,
firstevents: 1,
lang: this.language,
randid: randID(),
spid: ''
};
if (topics) data['topics'] = formatTopics(topics);
getResponse('/start', data, function (body, error) {
if (body) {
id = JSON.parse(body).clientID;
gotID = true;
_this.emit('gotID', id);
emitEvents(JSON.parse(body).events);
_this.getEvents();
}
else _this.emit('omerror', 'connect(): ' + error);
});
};
var formatTopics = function (topicsArr) {
var top = '[';
for (var i = 0; i < topicsArr.length; ++i) top += '"' + topicsArr[i] + '",';
top = top.slice(0, -1);
top += ']';
return top;
};
this.getEvents = function () {
var data = {
id: id
};
if (!gotID && !isConnected) return;
getResponse('/events', data, function (events, error) {
if (events) {
var ev = JSON.parse(events);
emitEvents(ev);
if (gotID) _this.getEvents();
}
else {
_this.emit('omerror', 'getEvents(): ' + error);
if (gotID) _this.getEvents();
}
});
};
var emitEvents = function (ev) {
if (!ev) return;
var eventsArr = ['waiting', 'connected', 'error', 'connectionDied', 'antinudeBanned', 'typing',
'stoppedTyping', 'gotMessage', 'strangerDisconnected', 'recaptchaRequired',
'recaptchaRejected', 'commonLikes'];
for (var i = 0; i < ev.length; ++i) {
var currentEvent = ev[i][0];
if (eventsArr.indexOf(currentEvent) < 0) continue;
lastEvent = currentEvent;
if (currentEvent == 'waiting') _this.emit('waiting');
else if (currentEvent == 'connected') {
challengeLink = '';
challenge = '';
isConnected = true;
_this.emit('connected');
}
else if (currentEvent == 'error') {
reset();
_this.emit('omegleError', +ev[i][1]);
}
else if (currentEvent == 'connectionDied') {
reset();
_this.emit('connectionDied');
}
else if (currentEvent == 'antinudeBanned') {
reset();
_this.emit('antinudeBanned');
}
else if (currentEvent == 'typing') {
typing = true;
_this.emit('typing');
}
else if (currentEvent == 'stoppedTyping') _this.emit('stoppedTyping');
else if (currentEvent == 'gotMessage') {
if (typing) _this.emit('stoppedTyping');
for (var j = 1; j < ev[i].length; ++j) _this.emit('gotMessage', ev[i][j]);
}
else if (currentEvent == 'strangerDisconnected') {
reset();
_this.emit('strangerDisconnected');
}
else if (currentEvent == 'recaptchaRequired') evalCaptcha(ev[i][1]);
else if (currentEvent == 'recaptchaRejected') evalCaptcha(ev[i][1]);
else if (currentEvent == 'commonLikes') _this.emit('commonLikes', ev[i][1]);
}
};
var evalCaptcha = function (pchallengeLink) {
challengeLink = pchallengeLink;
var url = 'http://www.google.com/recaptcha/api/challenge?k=' + pchallengeLink;
request.get(url, function (error, response, body) {
if (!error && response.statusCode == 200) {
var close = body.indexOf('}');
//I give up. JSON.parse, you have failed me, or maybe I'm just dumb.
eval(body.substring(0, close + 1)); // jshint ignore:line
challenge = RecaptchaState.challenge; // jshint ignore:line
_this.emit('recaptchaRequired', 'http://www.google.com/recaptcha/api/image?c=' + challenge);
}
});
};
this.reloadReCAPTCHA = function () {
if (challengeLink) evalCaptcha(challengeLink);
};
this.updateServer = function (server) {
if (server) {
url=server;
return false;
}
getResponse('/status', {
nocache: Math.random(),
randid: randID()
}, function (statusBody, error) {
if (statusBody) {
var response;
try {
response = JSON.parse(statusBody);
}
catch(err) {
_this.emit('omerror', 'updateServer(): ' + err);
return;
}
url = response.servers[0] + '.omegle.com';
_this.emit('serverUpdated', url);
}
else {
_this.emit('omerror', 'updateServer(): ' + error);
//this url didn't work, if updateServer() is called again, it's going to throw this error again
if(workingServers.length > 0){
url = workingServers[workingServers.length - 1];
}
}
}, 'GET');
};
this.send = function (msg) {
if (gotID && isConnected) {
var data = {
msg: msg,
id: id
};
getResponse('/send', data, function (body, error) {
if (body) {
if (body != 'win') _this.emit('omerror', 'send(): ' + body);
}
else _this.emit('omerror', 'send(): ' + error);
});
}
else {
_this.emit('omerror', 'send(): Not connected to ' + (gotID ? 'a stranger yet.' : 'the server.'));
}
};
this.startTyping = function () {
if (gotID && isConnected) {
var data = {
id: id
};
getResponse('/typing', data, function (body, error) {
if (body) {
if (body != 'win') _this.emit('omerror', 'startTyping(): Couldn\'t send the typing event. Response from server: ' + body);
}
else _this.emit('omerror', 'startTyping(): ' + error);
});
}
else _this.emit('omerror', 'startTyping(): Couldn\'t send the typing event. Not connected to ' + (gotID ? 'a stranger yet.' : 'the server.'));
};
this.stopTyping = function () {
if (gotID && isConnected) {
var data = {
id: id
};
getResponse('/stoppedtyping', data, function (body, error) {
if (body) {
if (body != 'win') _this.emit('omerror', 'stopTyping(): Couldn\'t send the stoppedtyping event. Response from server: ' + body);
}
else _this.emit('omerror', error);
});
}
else _this.emit('omerror', 'stopTyping(): Couldn\'t send the stoppedtyping event. Not connected to ' + (gotID ? 'a stranger yet.' : 'the server.'));
};
this.stopLookingForCommonLikes = function (callback) {
if (lastEvent == 'waiting' && !challengeLink) {
var data = {
id: id
};
getResponse('/stoplookingforcommonlikes', data, function (body, error) {
if (body) {
if (body != 'win') _this.emit('omerror', 'stopLookingForCommonLikes(): Something went wrong. Response from server: ' + body);
}
else _this.emit('omerror', error);
if (callback) callback(body);
});
}
//else
// _this.emit('omerror','stopLookingForCommonLikes: ' + (isConnected?'Already connected to a stranger':'Current event is not \'waiting\'. Current event: '+lastEvent));
};
this.slfcl = this.stopLookingForCommonLikes;
this.disconnect = function () {
if (gotID && isConnected) {
var data = {
id: id
};
getResponse('/disconnect', data, function (body, error) {
if (body) {
if (body != 'win') _this.emit('omerror', 'disconnect(): Couldn\'t send the disconnect event. Response from server: ' + body);
reset();
}
else _this.emit('omerror', 'disconnect(): ' + error);
});
}
else _this.emit('omerror', 'disconnect(): Couldn\'t send the disconnect event. Not connected to ' + (gotID ? 'a stranger yet.' : 'the server.'));
};
// I haven't tested this, because I'd first have to get banned to be able to test this, but it should work.
// Nevermind, I got banned today, turns out I implemented recaptcha handling totally wrong. Now it's working.
this.solveReCAPTCHA = function (answer) {
if (gotID && challenge) {
var data = {
id: id,
challenge: challenge,
response: answer
};
getResponse('/recaptcha', data, function (body, error) {
if (error) _this.emit('omerror', 'solveReCAPTCHA(): ' + error);
});
}
else _this.emit('omerror', 'solveReCAPTCHA(): Not connected to the server or there\'s no ReCAPTCHA.');
};
var reset = function () {
isConnected = false;
gotID = false;
lastEvent = '';
id = '';
typing = false;
challenge = '';
_this.emit('disconnected');
};
//TODO: Chat log support
};
util.inherits(Omegle, ee);
module.exports = Omegle;