├── .gitignore
├── .npmignore
├── README.md
├── bin
└── cli.js
├── index.js
├── package.json
└── promise.js
/.gitignore:
--------------------------------------------------------------------------------
1 | hosts.bak
2 | node_modules/
3 | .diea/
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | hosts.bak
2 | .diea/
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | hostx
2 | ===========
3 |
4 | 一条命令更新hosts,你懂的。
5 |
6 | 安装:
7 |
8 | npm install -g hostx
9 |
10 | 使用:
11 |
12 | hostx
13 |
14 | 指定一个在线的hosts列表更新
15 |
16 | hostx -u http://laod.cn/wp-content/uploads/2014/11/imouto.host_.txt
17 |
18 |
19 | 如果想清除已经更新的 hosts:
20 |
21 | hostx -c
22 |
23 | 查看帮助:
24 |
25 | hostx -h
26 |
27 |
28 |
--------------------------------------------------------------------------------
/bin/cli.js:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 | var argv = require('optimist').argv;
3 | var hostx = require('../index');
4 |
5 | if (argv.c) {
6 | hostx.clear();
7 | }
8 | else if (argv.h) {
9 | console.log(
10 | 'Usage: hostx [-u url] 更新hosts\n' +
11 | ' or: hostx -c 清除更新的hosts \n' +
12 | ' or: hostx -h 查看帮助 \n'
13 | );
14 | }
15 | else {
16 | hostx.run(argv.u);
17 | }
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by an.han on 15/1/20.
3 | */
4 |
5 | var Promise = require('./promise');
6 | var fs = require('fs');
7 | var http = require('http');
8 | var https = require('https');
9 |
10 |
11 | var URLS = [
12 | 'http://www.racalinux.cn/hosts.txt',
13 | 'https://github.com/racaljk/hosts/blob/master/hosts',
14 | //'https://raw.githubusercontent.com/zxdrive/imouto.host/master/imouto.host.txt',
15 | //'http://freedom.txthinking.com/hosts',
16 | //'http://laod.cn/wp-content/uploads/2014/11/imouto.host_.txt'
17 | ]
18 |
19 | var hostsFile = process.platform == 'win32' ? 'C:\\Windows\\System32\\drivers\\etc\\hosts' : '/etc/hosts';
20 | var n = process.platform == 'win32' ? '\r\n' : '\n';
21 | var group = '#==== hostx';
22 | var groupReg = new RegExp(group + '[\n\r\n]([\\S\\s]*?)' + group, 'g');
23 |
24 | var hostx = {
25 |
26 | status: 0,
27 |
28 | errors: 0,
29 |
30 | run: function (url) {
31 | var filter = this.filter.bind(this);
32 | var update = this.update.bind(this);
33 | var urls = url ? [url] : URLS;
34 |
35 | this.backup();
36 |
37 | urls.forEach(function (url) {
38 | this.get(url).then(filter).then(update);
39 | }.bind(this));
40 | },
41 |
42 | update: function (hosts) {
43 | var oldHost = fs.readFileSync(hostsFile).toString();
44 | var newHost = groupReg.test(oldHost) ?
45 | oldHost.replace(groupReg, group + n + hosts + n + group) : oldHost + n + group + n + hosts + n + group;
46 |
47 | fs.writeFile(hostsFile, newHost, this._callback('恭喜,更新 hosts 成功!'));
48 | },
49 |
50 | filter: function (obj) {
51 | var host = '',
52 | url = obj.url,
53 | result = obj.result;
54 |
55 | if (/^https:\/\/github\.com/.test(url)) {
56 | var tds = result.match(/
.+<\/td>/g);
57 | tds.forEach(function (td) {
58 | host += (td.replace(/<.+?>/g, '') + n);
59 | });
60 | }
61 | else {
62 | host = result;
63 | }
64 | host = host.replace(/#.*?(\n|\r\n)/g, '');
65 | return host
66 | },
67 |
68 | get: function (url) {
69 | var self = this;
70 | var pm = new Promise();
71 | var req = /^https/.test(url) ? https : http;
72 | req.get(url, function (res) {
73 | var result = '';
74 | res.on('data', function (r) {
75 | result += r;
76 | });
77 | res.on('end', function () {
78 | if (self.status == 0) {
79 | self.status = 1;
80 | pm.resolve({
81 | url: url,
82 | result: result
83 | });
84 | }
85 | });
86 | }).on('error', function (e) {
87 | if (++self.errors == URLS.length && self.status == 0) {
88 | console.error('更新失败!');
89 | process.exit();
90 | }
91 | pm.reject(e);
92 | });
93 | return pm;
94 | },
95 |
96 | backup: function () {
97 | fs.writeFileSync('./hosts.bak', fs.readFileSync(hostsFile));
98 | },
99 |
100 | clear: function () {
101 | fs.writeFile(hostsFile, fs.readFileSync(hostsFile).toString().replace(groupReg, group + n + group), this._callback('hosts 清除成功!'));
102 | },
103 |
104 | _callback: function (txt) {
105 | return function (err) {
106 | if (err) {
107 | console.error('权限不够!请修改hosts文件为可写入,或使用 sudo 身份运行此命令。');
108 | }
109 | else {
110 | console.log(txt);
111 | }
112 | process.exit();
113 | }
114 | }
115 | }
116 |
117 | module.exports = hostx;
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "hostx",
3 | "version": "0.1.1",
4 | "description": "update hosts",
5 | "main": "index.js",
6 | "bin": "bin/cli.js",
7 | "scripts": {
8 | "test": "echo \"Error: no test specified\" && exit 1"
9 | },
10 | "keywords": [
11 | "hosts"
12 | ],
13 | "author": "韩安",
14 | "license": "ISC",
15 | "repository": {
16 | "type": "git",
17 | "url": "https://github.com/hanan198501/hostx.git"
18 | },
19 | "bugs": {
20 | "url": "https://github.com/hanan198501/hostx/issues"
21 | },
22 | "dependencies": {
23 | "optimist": "^0.6.1"
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/promise.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by an.han on 14/12/23.
3 | * ES6 Promise 类
4 | */
5 |
6 | // status
7 | var PENDING = 0,
8 | FULFILLED = 1,
9 | REJECTED = 2;
10 |
11 | var Promise = function (fun) {
12 | var me = this,
13 | resolve = function (val) {
14 | me.resolve(val);
15 | },
16 | reject = function (val) {
17 | me.reject(val);
18 | }
19 | me._status = PENDING;
20 | me._onFulfilled = null;
21 | me._onRejected = null;
22 | (typeof fun === 'function') && fun(resolve, reject);
23 | }
24 |
25 | var fn = Promise.prototype;
26 |
27 | fn.then = function (resolve, reject) {
28 | var pms = new Promise();
29 | this._onFulfilled = function (val) {
30 | var ret = resolve ? resolve(val) : val;
31 | if (Promise.isPromise(ret)) {
32 | ret.then(function (val) {
33 | pms.resolve(val);
34 | });
35 | }
36 | else {
37 | pms.resolve(ret);
38 | }
39 | };
40 | this._onRejected = function (val) {
41 | var ret = reject ? reject(val) : val;
42 | pms.reject(ret);
43 | };
44 | return pms;
45 | }
46 |
47 | fn.catch = function (reject) {
48 | return this.then(null, reject);
49 | }
50 |
51 | fn.resolve = function (val) {
52 | if (this._status === PENDING) {
53 | this._status = FULFILLED;
54 | this._onFulfilled && this._onFulfilled(val);
55 | }
56 | }
57 |
58 | fn.reject = function (val) {
59 | if (this._status === PENDING) {
60 | this._status = REJECTED;
61 | this._onRejected && this._onRejected(val);
62 | }
63 | }
64 |
65 | Promise.all = function (arr) {
66 | var pms = new Promise();
67 | var len = arr.length,
68 | i = -1,
69 | count = 0,
70 | results = [];
71 | while (++i < len) {
72 | ~function (i) {
73 | arr[i].then(
74 | function (val) {
75 | results[i] = val;
76 | if (++count === len) {
77 | pms.resolve(results);
78 | }
79 | },
80 | function (val) {
81 | pms.reject(val);
82 | }
83 | );
84 | }(i);
85 | }
86 | return pms;
87 | }
88 |
89 | Promise.resolve = function (obj) {
90 | var ret;
91 | if (!Promise.isPromise(obj)) {
92 | ret = obj;
93 | obj = new Promise();
94 | }
95 | setTimeout(function () {
96 | obj.resolve(ret);
97 | });
98 | return obj;
99 | }
100 |
101 | Promise.reject = function (obj) {
102 | var ret;
103 | if (!Promise.isPromise(obj)) {
104 | ret = obj;
105 | obj = new Promise();
106 | }
107 | setTimeout(function () {
108 | obj.reject(ret);
109 | });
110 | return obj;
111 | }
112 |
113 | Promise.isPromise = function (obj) {
114 | return obj instanceof Promise;
115 | }
116 |
117 |
118 | module.exports = Promise;
--------------------------------------------------------------------------------
|