-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 1a78f37
Showing
11 changed files
with
338 additions
and
0 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
node_modules/ |
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,2 @@ | ||
#!/usr/bin/env node | ||
require('../src/cli'); |
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,20 @@ | ||
const QScan = require('../src/index'); | ||
const scan = new QScan({ | ||
modelOpts: { | ||
'wx-default': { | ||
udid: 'xxx', | ||
port: '4723', | ||
opts: { | ||
user: 'xxx', | ||
pass: 'xxx' | ||
} | ||
} | ||
} | ||
}); | ||
|
||
scan.run({ | ||
modelName: 'wx-default', | ||
type: 'ide-login-scan' | ||
}, (err) => { | ||
|
||
}); |
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,20 @@ | ||
{ | ||
"name": "qscan", | ||
"version": "1.0.0", | ||
"description": "", | ||
"main": "src/index.js", | ||
"bin": { | ||
"qscan": "./bin/qscan" | ||
}, | ||
"scripts": { | ||
"test": "echo \"Error: no test specified\" && exit 1" | ||
}, | ||
"author": "", | ||
"license": "Apache 2.0", | ||
"dependencies": { | ||
"async": "^2.6.1", | ||
"commander": "^2.18.0", | ||
"queue": "^4.5.0", | ||
"wd": "^1.10.3" | ||
} | ||
} |
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,26 @@ | ||
const fs = require('fs'); | ||
const path = require('path'); | ||
const prog = require('commander'); | ||
|
||
const pkgJSON = require('../package.json'); | ||
|
||
prog.version(pkgJSON.version, '-v, --version') | ||
.usage('<command> [options]'); | ||
|
||
fs.readdirSync(path.join(__dirname, './commands')).forEach(file => { | ||
if (/\.js$/.test(file)) { | ||
const cmd = require(`./commands/${file}`); | ||
const name = path.basename(file, '.js'); | ||
const program = prog.command(name) | ||
.usage(cmd.usage) | ||
.description(cmd.description) | ||
.action(cmd.action); | ||
|
||
} | ||
}); | ||
|
||
prog.parse(process.argv); | ||
|
||
if (!program.args.length) { | ||
program.help(); | ||
} |
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 @@ | ||
module.exports = { | ||
usage: '[options]', | ||
description: '检查运行环境', | ||
options: { | ||
'-l, --login': '对登录逻辑进行检查' | ||
}, | ||
action: (rc, options) => { | ||
|
||
} | ||
}; |
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,14 @@ | ||
module.exports = { | ||
usage: '[options]', | ||
description: '扫描二维码', | ||
options: { | ||
'-u, --uri': '二维码地址', | ||
'-f, --file': '二维码本地图片文件地址', | ||
'-m, --model': '使用的扫码模式', | ||
'-t, --type': '使用的扫码类型', | ||
'-d, --device': '指定设备的 UDID' | ||
}, | ||
action: (rc, options) => { | ||
|
||
} | ||
}; |
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 @@ | ||
module.exports = { | ||
usage: '[options]', | ||
description: '启动自助二维码扫描服务', | ||
options: { | ||
'-p, --port': '服务端口' | ||
}, | ||
action: (rc, options) => { | ||
|
||
} | ||
}; |
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,176 @@ | ||
const fs = require('fs'); | ||
const path = require('path'); | ||
const wd = require('wd'); | ||
const async = require('async'); | ||
|
||
const Queue = require('queue'); | ||
const EventEmitter = require('events').EventEmitter; | ||
|
||
// 本地 Host | ||
const LOCAL_HOST = '127.0.0.1'; | ||
// 默认的等待时间 | ||
const WAIT_TIMEOUT = 3000; | ||
// 队列配置 | ||
const QUEUE_OPTS = { | ||
concurrency: 1, // 并发任务数1,等于串行 | ||
timeout: 10 * 60 * 1000, // 单个任务超时,10分钟 | ||
autostart: true // 有任务自动执行 | ||
}; | ||
// 默认的 Model | ||
const DEFAULT_MODEL_PATH = path.join(__dirname, '../models'); | ||
// 默认的配置文件路径 | ||
const DEFAULT_MODEL_OPTS_PATH = path.join(process.env['HOME'], '.qscanrc'); | ||
|
||
class QScan extends EventEmitter { | ||
constructor({customModel, modelOpts}) { | ||
// Models | ||
this.models = {}; | ||
// 队列 | ||
this.queues = {}; | ||
// 读取配置 | ||
if (modelOpts) { | ||
if (typeof modelOpts === 'string' && fs.existsSync(modelOpts)) { | ||
modelOpts = JSON.parse(fs.readFileSync(modelOpts, 'UTF-8')); | ||
} | ||
} else if (fs.existsSync(DEFAULT_MODEL_OPTS_PATH)) { | ||
modelOpts = JSON.parse(fs.readFileSync(DEFAULT_MODEL_OPTS_PATH, 'UTF-8')); | ||
} else { | ||
modelOpts = {}; | ||
} | ||
// 读取默认的 Model | ||
fs.readdirSync(DEFAULT_MODEL_PATH, (file) => this.loadModelFile({ | ||
modelFilePath: path.join(DEFAULT_MODEL_PATH, file), | ||
modelOpts | ||
})); | ||
// 读取自定义 model | ||
if (customModel) { | ||
if (typeof customModel === 'string' && fs.existsSync(customModel)) { | ||
fs.readdirSync(customModel, (file) => this.__loadModelFile({ | ||
modelFilePath: path.join(customModel, file), | ||
modelOpts | ||
})); | ||
} else { | ||
Object.keys(customModel).forEach((key) => { | ||
const model = customModel[key]; | ||
const opts = modelOpts[model.name || 'default'] || {}; | ||
this.loadModel({ | ||
model, | ||
...opts | ||
}); | ||
}); | ||
} | ||
} | ||
} | ||
doctor(modelName, cb) { | ||
const tasks = []; | ||
tasks.push((cb) => { | ||
// TODO Check Appium | ||
}); | ||
if (modelName && this.models[modelName]) { | ||
const model = this.models[modelName]; | ||
if (model.udid) { | ||
tasks.push((cb) => { | ||
// TODO Check Devices | ||
// model.udid | ||
}); | ||
} | ||
if (model.port) { | ||
tasks.push((cb) => { | ||
// TODO Check Appium Process | ||
}); | ||
} | ||
if (model.checkApp) { | ||
tasks.push((cb) => model.checkApp(cb)); | ||
} | ||
} | ||
async.series(tasks, cb); | ||
} | ||
loadModel({model, udid, port, opts}) { | ||
if (udid) { | ||
model.udid = model.connectOpt.udid = udid; | ||
} | ||
if (port) { | ||
model.port = port; | ||
} | ||
if (opts) { | ||
model.opts = opts; | ||
} | ||
this.models[model.name] = model; | ||
} | ||
run({modelName, type}, cb) { | ||
if (!this.queues[modelName]) { | ||
this.queues[modelName] = new Queue(QUEUE_OPTS); | ||
} | ||
this.queues[modelName].push((callback) => { | ||
__handleDevice({modelName, type, reset: false}, (err) => { | ||
cb(err); | ||
callback(); | ||
}); | ||
}); | ||
} | ||
__loadModelFile({modelFilePath, modelOpts}) { | ||
const model = require(modelFilePath); | ||
const opts = modelOpts[model.name || 'default'] || {}; | ||
this.loadModel({ | ||
model, | ||
...opts | ||
}); | ||
} | ||
__connectAppium(model, cb) { | ||
//TODO Connect for Start Appium | ||
setTimeout(() => { | ||
cb(null); | ||
}, 100); | ||
} | ||
__initConnect(model, reset) { | ||
return wd.promiseChainRemote({ | ||
host: LOCAL_HOST, | ||
port: model.port, | ||
}).init(Object.assign({}, model.connectOpt, { | ||
noReset: !reset | ||
})).setImplicitWaitTimeout(model.waitTimeout || WAIT_TIMEOUT); | ||
} | ||
__initModel(model, reset) { | ||
return model.init(this.__initConnect(model, reset)); | ||
} | ||
__checkStatus(model, cb) { | ||
model.checkStatus(this.__initConnect(model), model.opts, cb); | ||
} | ||
__handleDevice({modelName, type, reset}, cb) { | ||
const model = this.models[modelName]; | ||
if (model) { | ||
if (model.types && model.types[type]) { | ||
this.__connectAppium(model, (err) => { | ||
if (err) { | ||
cb(err); | ||
} else if (reset) { | ||
model.types[type](this.__initModel(model, true), model.opts).catch((e) => { | ||
cb(e); | ||
}).finnally(() => { | ||
cb(null); | ||
}); | ||
} else { | ||
this.__checkStatus(model, (err, flag) => { | ||
if (!err && flag) { | ||
model.types[type](this.__initModel(model, false), model.opts).catch((e) => { | ||
cb(e); | ||
}).finnally(() => { | ||
cb(null); | ||
}); | ||
} else { | ||
this.__handleDevice({modelName, type, reset: true}, cb); | ||
} | ||
}); | ||
} | ||
}); | ||
} else { | ||
cb(new Error(`Not Found This Type <${type}>.`)); | ||
} | ||
} else { | ||
cb(new Error(`Not Found This Model <${modelName}>.`)); | ||
} | ||
} | ||
} | ||
|
||
module.exports = QScan; | ||
|
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,16 @@ | ||
const QScan = require('./core/qcan'); | ||
|
||
// 中间件 | ||
QScan.middleWare = ({customModel, modelOpts}) => { | ||
const scan = new QScan({customModel, modelOpts}); | ||
return (req, res) => { | ||
// TODO | ||
}; | ||
}; | ||
|
||
// 服务 | ||
QScan.serve = ({customModel, modelOpts, port, forever}) => { | ||
// TODO | ||
}; | ||
|
||
module.exports = QScan; |
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,43 @@ | ||
module.exports = { | ||
// Model Name | ||
name: 'wx-default', | ||
// 参数,包括用户名,密码等 | ||
opts: {}, | ||
// Appium 连接参数 | ||
connectOpt: { | ||
platformName: 'Android', | ||
deviceName: 'Android', | ||
appPackage: 'com.tencent.mm', | ||
}, | ||
// 等待超时时间 | ||
waitTimeout: 3000, | ||
// 检查 App 是否是相应的版本等 | ||
checkApp: (cb) => { | ||
const version = '6.7.0'; | ||
setTimeout(() => { | ||
cb(null, true); | ||
}, 100); | ||
}, | ||
// 初始化 App,从打开、登录到主界面 | ||
init: (app) => { | ||
return app; | ||
}, | ||
// 检查状态是否正确,包括登录的用户是指定用户等 | ||
checkStatus: (app, opts, cb) => { | ||
setTimeout(() => { | ||
cb(null, true); | ||
}, 100); | ||
}, | ||
// 不同类型的扫码 | ||
types: { | ||
// 开发者工具登录 | ||
"ide-login-scan": (app, opts) => { | ||
return app; | ||
}, | ||
// 微信后台登录 | ||
"backstage-login-scan": (app, opts) => { | ||
return app; | ||
} | ||
} | ||
}; | ||
|