-
-
Notifications
You must be signed in to change notification settings - Fork 42
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
chore: import last existing code from sandbox
- Loading branch information
Showing
20 changed files
with
1,114 additions
and
281 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
/* | ||
* Copyright (c) 2017, Hugo Freire <hugo@exec.sh>. | ||
* | ||
* This source code is licensed under the license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
*/ | ||
|
||
const _ = require('lodash') | ||
const Promise = require('bluebird') | ||
const retry = require('bluebird-retry') | ||
const Brakes = require('brakes') | ||
|
||
const Nightmare = require('nightmare') | ||
Nightmare.Promise = Promise | ||
|
||
const Logger = require('modern-logger') | ||
|
||
const Health = require('health-checkup') | ||
|
||
const RandomUserAgent = require('random-http-useragent') | ||
|
||
const { join } = require('path') | ||
|
||
const authorizeApp = function (email, password, url, userAgent) { | ||
let facebookUserId | ||
let accessToken | ||
|
||
const nightmare = Nightmare(this._options.nightmare) | ||
|
||
return nightmare | ||
.useragent(userAgent) | ||
.on('page', function (type, url, method, response) { | ||
if (type !== 'xhr-complete') { | ||
return | ||
} | ||
|
||
if (url.path === '/ajax/presence/reconnect.php') { | ||
const match = response.match(/"user_channel":"p_(.*?)"/) | ||
facebookUserId = match.length === 2 ? match[ 1 ] : undefined | ||
|
||
return | ||
} | ||
|
||
if (_.includes(url, 'oauth/confirm?dpr')) { | ||
const match = response.match(/access_token=(.*)&/) | ||
accessToken = match.length === 2 ? match[ 1 ] : undefined | ||
} | ||
}) | ||
.goto('https://facebook.com') | ||
.type('input#email', email) | ||
.type('input#pass', password) | ||
.click('#loginbutton input') | ||
.wait(3000) | ||
.goto(url) | ||
.wait('button._42ft._4jy0.layerConfirm._1flv._51_n.autofocus.uiOverlayButton._4jy5._4jy1.selected._51sy') | ||
.click('button._42ft._4jy0.layerConfirm._1flv._51_n.autofocus.uiOverlayButton._4jy5._4jy1.selected._51sy') | ||
.wait(10000) | ||
.end() | ||
.then(() => { | ||
if (!accessToken || !facebookUserId) { | ||
throw new Error('unable to authorize app') | ||
} | ||
|
||
return { accessToken, facebookUserId } | ||
}) | ||
} | ||
|
||
const defaultOptions = { | ||
nightmare: { | ||
show: false, | ||
partition: 'nopersist', | ||
webPreferences: { | ||
preload: join(__dirname, '/preload.js'), | ||
webSecurity: false | ||
} | ||
}, | ||
retry: { max_tries: 2, interval: 5000, timeout: 40000, throw_original: true }, | ||
breaker: { timeout: 60000, threshold: 80, circuitDuration: 3 * 60 * 60 * 1000 } | ||
} | ||
|
||
class Facebook { | ||
constructor (options = {}) { | ||
this._options = _.defaults(options, defaultOptions) | ||
|
||
this._breaker = new Brakes(this._options.breaker) | ||
|
||
this._authorizeAppCircuitBreaker = this._breaker.slaveCircuit((...params) => retry(() => authorizeApp.bind(this)(...params), this._options.retry)) | ||
|
||
Health.addCheck('facebook', () => new Promise((resolve, reject) => { | ||
if (this._breaker.isOpen()) { | ||
return reject(new Error(`circuit breaker is open`)) | ||
} else { | ||
return resolve() | ||
} | ||
})) | ||
} | ||
|
||
authorizeApp (email, password, url) { | ||
Logger.debug('Started authorizing app in Facebook') | ||
|
||
return RandomUserAgent.get() | ||
.then((userAgent) => this._authorizeAppCircuitBreaker.exec(email, password, url, userAgent)) | ||
.finally(() => Logger.debug('Finished authorizing app in Facebook')) | ||
} | ||
} | ||
|
||
module.exports = Facebook |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
/* | ||
* Copyright (c) 2017, Hugo Freire <hugo@exec.sh>. | ||
* | ||
* This source code is licensed under the license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
*/ | ||
|
||
module.exports = { | ||
Facebook: require('./facebook') | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
/* | ||
* Copyright (c) 2017, Hugo Freire <hugo@exec.sh>. | ||
* | ||
* This source code is licensed under the license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
*/ | ||
|
||
/* eslint-disable no-undef */ | ||
|
||
window.__nightmare = {} | ||
__nightmare.ipc = require('electron').ipcRenderer | ||
__nightmare.sliced = require('sliced') | ||
|
||
// Listen for error events | ||
window.addEventListener('error', function (e) { | ||
__nightmare.ipc.send('page', 'error', e.message, e.error.stack) | ||
}) | ||
|
||
var open = window.XMLHttpRequest.prototype.open | ||
window.XMLHttpRequest.prototype.open = function (method, url, async, user, pass) { | ||
this.addEventListener('readystatechange', function () { | ||
if (this.readyState === 4) { | ||
__nightmare.ipc.send('page', 'xhr-complete', url, method, this.responseText) | ||
} | ||
}, false) | ||
open.apply(this, arguments) | ||
}; | ||
|
||
(function () { | ||
// prevent 'unload' and 'beforeunload' from being bound | ||
var defaultAddEventListener = window.addEventListener | ||
window.addEventListener = function (type) { | ||
if (type === 'unload' || type === 'beforeunload') { | ||
return | ||
} | ||
defaultAddEventListener.apply(window, arguments) | ||
} | ||
|
||
// prevent 'onunload' and 'onbeforeunload' from being set | ||
Object.defineProperties(window, { | ||
onunload: { | ||
enumerable: true, | ||
writable: false, | ||
value: null | ||
}, | ||
onbeforeunload: { | ||
enumerable: true, | ||
writable: false, | ||
value: null | ||
} | ||
}) | ||
|
||
// listen for console.log | ||
var defaultLog = console.log | ||
console.log = function () { | ||
__nightmare.ipc.send('console', 'log', __nightmare.sliced(arguments)) | ||
return defaultLog.apply(this, arguments) | ||
} | ||
|
||
// listen for console.warn | ||
var defaultWarn = console.warn | ||
console.warn = function () { | ||
__nightmare.ipc.send('console', 'warn', __nightmare.sliced(arguments)) | ||
return defaultWarn.apply(this, arguments) | ||
} | ||
|
||
// listen for console.error | ||
var defaultError = console.error | ||
console.error = function () { | ||
__nightmare.ipc.send('console', 'error', __nightmare.sliced(arguments)) | ||
return defaultError.apply(this, arguments) | ||
} | ||
|
||
// overwrite the default alert | ||
window.alert = function (message) { | ||
__nightmare.ipc.send('page', 'alert', message) | ||
} | ||
|
||
// overwrite the default prompt | ||
window.prompt = function (message, defaultResponse) { | ||
__nightmare.ipc.send('page', 'prompt', message, defaultResponse) | ||
} | ||
|
||
// overwrite the default confirm | ||
window.confirm = function (message, defaultResponse) { | ||
__nightmare.ipc.send('page', 'confirm', message, defaultResponse) | ||
} | ||
})() |
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.