2016-01-18 15:07:22 +01:00
|
|
|
import os from 'os';
|
|
|
|
import path from 'path';
|
2016-01-19 14:32:55 +01:00
|
|
|
import url from 'url';
|
2016-01-18 15:07:22 +01:00
|
|
|
|
2016-01-18 17:40:24 +01:00
|
|
|
import request from 'request';
|
|
|
|
import cheerio from 'cheerio';
|
2016-01-18 16:56:59 +01:00
|
|
|
import validator from 'validator';
|
2016-01-26 02:51:39 +01:00
|
|
|
import sanitize from 'sanitize-filename';
|
2016-01-26 07:44:19 +01:00
|
|
|
import _ from 'lodash';
|
2016-01-28 14:13:57 +01:00
|
|
|
import async from 'async';
|
|
|
|
import inferIcon from './inferIcon';
|
2016-01-18 16:56:59 +01:00
|
|
|
|
2016-01-18 15:07:22 +01:00
|
|
|
const TEMPLATE_APP_DIR = path.join(__dirname, '../', 'app');
|
|
|
|
const ELECTRON_VERSION = '0.36.4';
|
2016-01-28 14:13:57 +01:00
|
|
|
const DEFAULT_APP_NAME = 'APP';
|
2016-01-18 15:07:22 +01:00
|
|
|
|
2016-01-18 17:40:24 +01:00
|
|
|
function optionsFactory(name,
|
2016-01-18 17:44:15 +01:00
|
|
|
targetUrl,
|
2016-01-18 15:07:22 +01:00
|
|
|
platform = detectPlatform(),
|
2016-01-18 16:38:52 +01:00
|
|
|
arch = detectArch(),
|
2016-01-18 15:07:22 +01:00
|
|
|
version = ELECTRON_VERSION,
|
2016-01-18 16:38:52 +01:00
|
|
|
outDir = process.cwd(),
|
2016-01-18 18:17:12 +01:00
|
|
|
overwrite = false,
|
2016-01-18 16:38:52 +01:00
|
|
|
conceal = false,
|
|
|
|
icon,
|
2016-01-22 04:35:05 +01:00
|
|
|
counter = false,
|
2016-01-18 15:07:22 +01:00
|
|
|
width = 1280,
|
2016-01-19 04:30:42 +01:00
|
|
|
height = 800,
|
2016-01-22 15:42:56 +01:00
|
|
|
showMenuBar = false,
|
2016-01-19 04:30:42 +01:00
|
|
|
userAgent,
|
2016-01-22 04:59:57 +01:00
|
|
|
honest = false,
|
2016-01-25 16:42:28 +01:00
|
|
|
insecure = false,
|
2016-01-19 04:30:42 +01:00
|
|
|
callback) {
|
2016-01-19 14:32:55 +01:00
|
|
|
targetUrl = normalizeUrl(targetUrl);
|
2016-01-18 18:17:12 +01:00
|
|
|
|
|
|
|
if (!width) {
|
|
|
|
width = 1280;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!height) {
|
|
|
|
height = 800;
|
2016-01-18 16:56:59 +01:00
|
|
|
}
|
|
|
|
|
2016-01-22 04:59:57 +01:00
|
|
|
if (!userAgent && !honest) {
|
2016-01-21 05:53:12 +01:00
|
|
|
userAgent = getFakeUserAgent();
|
|
|
|
}
|
|
|
|
|
2016-01-18 17:40:24 +01:00
|
|
|
const options = {
|
2016-01-18 15:07:22 +01:00
|
|
|
dir: TEMPLATE_APP_DIR,
|
|
|
|
|
|
|
|
name: name,
|
|
|
|
targetUrl: targetUrl,
|
|
|
|
|
|
|
|
platform: platform,
|
2016-01-18 16:38:52 +01:00
|
|
|
arch: arch,
|
2016-01-18 15:07:22 +01:00
|
|
|
version: version,
|
|
|
|
|
|
|
|
out: outDir,
|
|
|
|
|
|
|
|
// optionals
|
|
|
|
overwrite: overwrite,
|
|
|
|
asar: conceal,
|
2016-01-18 16:38:52 +01:00
|
|
|
icon: icon,
|
2016-01-18 15:07:22 +01:00
|
|
|
|
|
|
|
// app configuration
|
2016-01-22 04:35:05 +01:00
|
|
|
counter: counter,
|
2016-01-18 15:07:22 +01:00
|
|
|
width: width,
|
2016-01-19 04:30:42 +01:00
|
|
|
height: height,
|
2016-01-22 15:42:56 +01:00
|
|
|
showMenuBar: showMenuBar,
|
2016-01-25 16:42:28 +01:00
|
|
|
userAgent: userAgent,
|
|
|
|
insecure: insecure
|
2016-01-18 17:44:15 +01:00
|
|
|
};
|
2016-01-18 17:40:24 +01:00
|
|
|
|
2016-01-28 14:13:57 +01:00
|
|
|
async.waterfall([
|
|
|
|
callback => {
|
|
|
|
if (options.icon) {
|
|
|
|
callback(null, options);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
inferIcon(options.targetUrl, (error, pngPath) => {
|
|
|
|
if (error) {
|
|
|
|
console.warn('Cannot automatically retrieve the app icon:', error);
|
|
|
|
} else {
|
|
|
|
options.icon = pngPath;
|
|
|
|
}
|
|
|
|
callback(null, options);
|
|
|
|
});
|
|
|
|
},
|
|
|
|
(options, callback) => {
|
|
|
|
if (name && name.length > 0) {
|
|
|
|
options.name = name;
|
|
|
|
callback(null, options);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
getTitle(options.targetUrl, function(error, pageTitle) {
|
|
|
|
if (error) {
|
|
|
|
console.warn(`Unable to automatically determine app name, falling back to '${DEFAULT_APP_NAME}'`);
|
|
|
|
options.name = DEFAULT_APP_NAME;
|
|
|
|
} else {
|
|
|
|
options.name = pageTitle;
|
|
|
|
}
|
|
|
|
|
|
|
|
callback(null, options);
|
|
|
|
});
|
2016-01-18 17:40:24 +01:00
|
|
|
}
|
2016-01-28 14:13:57 +01:00
|
|
|
], (error, options) => {
|
|
|
|
callback(error, sanitizeOptions(options));
|
2016-01-18 17:40:24 +01:00
|
|
|
});
|
2016-01-18 15:07:22 +01:00
|
|
|
}
|
|
|
|
|
2016-01-26 02:51:39 +01:00
|
|
|
function sanitizeOptions(options) {
|
|
|
|
options.name = sanitize(options.name);
|
2016-01-26 07:44:19 +01:00
|
|
|
|
|
|
|
if (options.platform === 'linux') {
|
2016-01-28 17:20:32 +01:00
|
|
|
options.name = _.kebabCase(options.name);
|
2016-01-26 07:44:19 +01:00
|
|
|
}
|
2016-01-26 02:51:39 +01:00
|
|
|
return options;
|
|
|
|
}
|
|
|
|
|
2016-01-18 15:07:22 +01:00
|
|
|
function detectPlatform() {
|
|
|
|
const platform = os.platform();
|
|
|
|
if (platform === 'darwin' || platform === 'win32' || platform === 'linux') {
|
|
|
|
return platform;
|
|
|
|
}
|
|
|
|
|
|
|
|
console.warn(`Warning: Untested platform ${platform} detected, assuming linux`);
|
|
|
|
return 'linux';
|
|
|
|
}
|
|
|
|
|
|
|
|
function detectArch() {
|
|
|
|
const arch = os.arch();
|
|
|
|
if (arch !== 'ia32' && arch !== 'x64') {
|
|
|
|
throw `Incompatible architecture ${arch} detected`;
|
|
|
|
}
|
|
|
|
return os.arch();
|
|
|
|
}
|
|
|
|
|
2016-01-18 17:40:24 +01:00
|
|
|
function getTitle(url, callback) {
|
2016-01-22 03:47:53 +01:00
|
|
|
const options = {
|
|
|
|
url: url,
|
|
|
|
headers: {
|
|
|
|
// fake a user agent because pages like http://messenger.com will throw 404 error
|
|
|
|
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2227.1 Safari/537.36'
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
request(options, (error, response, body) => {
|
2016-01-18 17:40:24 +01:00
|
|
|
if (error || response.statusCode !== 200) {
|
2016-01-21 05:27:20 +01:00
|
|
|
callback(`Request Error: ${error}, Status Code ${response ? response.statusCode : 'No Response'}`);
|
2016-01-18 17:40:24 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
const $ = cheerio.load(body);
|
2016-01-23 19:02:23 +01:00
|
|
|
const pageTitle = $('title').text().replace(/\//g, '');
|
2016-01-18 17:40:24 +01:00
|
|
|
callback(null, pageTitle);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2016-01-19 14:32:55 +01:00
|
|
|
function normalizeUrl(testUrl) {
|
|
|
|
// add protocol if protocol not found
|
|
|
|
let normalized = testUrl;
|
|
|
|
const parsed = url.parse(normalized);
|
|
|
|
if (!parsed.protocol) {
|
|
|
|
normalized = 'http://' + normalized;
|
|
|
|
}
|
2016-01-20 17:57:51 +01:00
|
|
|
if (!validator.isURL(normalized, {require_protocol: true, require_tld: false})) {
|
2016-01-19 14:32:55 +01:00
|
|
|
throw `Your Url: "${normalized}" is invalid!`;
|
|
|
|
}
|
|
|
|
return normalized;
|
|
|
|
}
|
|
|
|
|
2016-01-21 05:53:12 +01:00
|
|
|
function getFakeUserAgent() {
|
|
|
|
let userAgent;
|
|
|
|
switch (os.platform()) {
|
|
|
|
case 'darwin':
|
|
|
|
userAgent = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2227.1 Safari/537.36';
|
|
|
|
break;
|
|
|
|
case 'win32':
|
|
|
|
userAgent = 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36';
|
|
|
|
break;
|
|
|
|
case 'linux':
|
|
|
|
userAgent = 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2227.0 Safari/537.36';
|
|
|
|
break;
|
2016-01-23 19:02:23 +01:00
|
|
|
default:
|
|
|
|
break;
|
2016-01-21 05:53:12 +01:00
|
|
|
}
|
|
|
|
return userAgent;
|
|
|
|
}
|
|
|
|
|
2016-01-18 15:07:22 +01:00
|
|
|
export default optionsFactory;
|