Skip to content
This repository has been archived by the owner on Jul 17, 2020. It is now read-only.

Run headlessly with webdriver #274

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 9 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,15 @@ The bot is currently a big dangle-on script running in your browser. **Run `book

If you wish, you can also run it headlessly on top of phantomjs and node:

* Install [phantomjs 2](http://phantomjs.org/) (yes, it has to be 2 and above). Differs from platform to platform.
* Install nightmare: `npm install nightmare`
* Edit your credentials into `run-headless.js`
* Hit the road: `env DEBUG=nightmare node run-headless.js`
1. Install [phantomjs 2](http://phantomjs.org/) (yes, it has to be 2 and above). Differs from platform to platform.
2. Install webdriverio: `npm install [email protected]` (4.x is broken)
3. Copy `run-headless.config.json.SAMPLE` into `run-headless.config.json` (update if necessary), and edit your credentials into it.
4. Hit the road:

```sh
screen -mdS pjs-server phantomjs --webdriver=4444
screen -mdS bot node run-headless-webdriver.js
```

###Building###

Expand Down
5 changes: 2 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,9 @@
"name": "so-chatbot",
"version": "0.2.0",
"description": "A chatbot for StackOverflow.",
"main": "run-headless.js",
"main": "run-headless-webdriver.js",
"dependencies": {
"nightmare": "^1.8.1"
},
"webdriverio": "3.4.0"
"devDependencies": {
"browserify": "^13.0.0",
"uglify-js": "^2.4.15"
Expand Down
146 changes: 146 additions & 0 deletions run-headless-webdriver.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
var cleanupAndExit = function(exitCode) {
var exit = function() {
console.log('Exiting.');
process.exit(exitCode);
};

console.log('Cleaning up...');
setTimeout(function() {
console.warn('Failed to clean up in 5000ms. Some browser instances may remain.');
exit();
}, 5000);
if (client) {
if (dumpBrowserConsoleLoop) {
clearInterval(dumpBrowserConsoleLoop);
}
client.end().then(function() {
console.log('Cleaned up.');
exit();
}).catch(function(err) {
console.error(err.name, err.message);
console.warn('Cleanup failed. Some browser instances may remain.');
exit();
});
} else {
exit();
}
};

var signals = {
'SIGHUP': 1,
'SIGINT': 2,
'SIGTERM': 15,
'SIGBREAK': 21
};
for (var signal in signals) {
process.on(signal, function() {
console.log(signal + ' caught');
cleanupAndExit(128 + signals[signal]); // posix signal 128 + signal number
});
}
process.on('uncaughtException', function(err) {
console.error(err);
cleanupAndExit(1);
});

var config = require('./run-headless.config.json');

var webdriverio = require('webdriverio');

var client = webdriverio.remote(config.driverOptions);

var logLevels = {
'SEVERE': console.error,
'WARNING': console.warn,
'INFO': console.info,
'DEBUG': console.debug
};
var dumpBrowserConsole = function(limit) {
client.log('browser').then(function(logs) {
(limit ? logs.value.slice(-limit) : logs.value).forEach(function(log) {
(logLevels[log.value] || console.log).call(console, log.message);
});
});
};
var dumpBrowserConsoleLoop = null;
// phantomjs does not clear browser logs correctly
// dumping in a loop floods console cause they repeat
//var dumpBrowserConsoleLoop = setInterval(dumpBrowserConsole, 5000);

client
.init()
.url(config.loginUrl)
.getUrl()
.then(function(url) {
console.log('Loaded ' + url);
})
.getText('=log in')
.then(function() {
console.log('Logging in...');
return client
.execute(function() {
openid.signin('stack_exchange');
})
.waitForExist('#affiliate-signin-iframe', 10000)
.frame('affiliate-signin-iframe')
.waitForExist('#email', 10000)
.setValue('#email', config.email)
.setValue('#password', config.password)
.submitForm('.login-form form')
.frame()
.getUrl()
.then(function(url) {
console.log('Login submitted; loaded ' + url);
});
}, function(err) {
console.log('Already logged in; skipping login');
})
.url(config.roomUrl)
.getUrl()
.then(function(url) {
console.log('Loaded chatroom ' + url);
})
.execute(function(scriptUrl) {
var script = document.createElement('script');
script.src = scriptUrl;
script.onload = function() {
//bot.activateDevMode();
console.log('Loaded bot');
bot.adapter.out.add('I have just been restarted! This happens daily automatically, or when my owner restarts me. Ready for commands.');
};
document.head.appendChild(script);
}, config.scriptUrl)
.then(function() {
console.log('Chatbot injected');
})
.then(function() {
var readline = require('readline');
var repl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
repl.on('SIGINT', function() {
process.emit('SIGINT');
});
repl.setPrompt('> ');

console.log('You are now in a REPL with the remote page. Have fun!');

repl.on('line', function(data) {
console.log('Attempting to run "' + data + '"');
client.executeAsync(function(code) {
return eval(code);
}, data).then(function(ret) {
console.log('$', ret.value);
}).catch(function(err) {
console.log('!', err.name, err.message);
}).finally(function() {
// because phantomjs does not clear browser logs correctly
// we only display the last 5 to avoid flooding
dumpBrowserConsole(5);
repl.prompt();
});
});

repl.prompt();
});
17 changes: 13 additions & 4 deletions run-headless.config.json.SAMPLE
Original file line number Diff line number Diff line change
@@ -1,7 +1,16 @@
{
"email": "you can guess",
"password": "what these are",
"email": "you can guess",
"password": "what these are",

"siteUrl": "https://stackoverflow.com",
"roomUrl": "https://chat.stackoverflow.com/rooms/1"
"siteUrl": "https://stackoverflow.com",
"roomUrl": "https://chat.stackoverflow.com/rooms/1",
"loginUrl": "https://stackexchange.com/users/login",

"scriptUrl": "http://localhost/master.js",

"driverOptions": {
"desiredCapabilities": {
"browserName": "phantomjs"
}
}
}