Skip to content

Commit

Permalink
v1.4.2 Simplify code, Some logic changes, Extra Log (#21)
Browse files Browse the repository at this point in the history
* v1.4.0 Add caching feature, improve documents, detail changes and optimizations

* 紧急修复

* Update README.md

* v1.4.1 md file update, improve code quality

* v1.4.2 Simplify code, Some logic changes, Extra Log

* Update README.md

* Update README.md

---------

Co-authored-by: lingbopro <ilovemc@zohomail.cn>
  • Loading branch information
Minemetero and lingbopro authored Jun 28, 2024
1 parent 33cfab1 commit 10e6914
Show file tree
Hide file tree
Showing 7 changed files with 150 additions and 112 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ git clone https://github.com/lingbopro/easy-github-hosts.git

2. **完成**:程序将在原始`hosts`文件恢复完成后通知您。

## 选项
<!--## 选项

可以在运行时在命令中增加可选的选项(见下)

Expand Down Expand Up @@ -106,7 +106,7 @@ node main.js --noedit --diff

```shell
node main.js --nocache
```
```-->

## TODO

Expand Down
74 changes: 44 additions & 30 deletions ipFetcher.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,31 +38,32 @@ const sites = [
* @returns {Promise<string>} - 返回网站的 IP 地址
*/
async function getIP(host) {
const url = `http://ip-api.com/json/${host}?fields=status,message,query`;
let url = `http://ip-api.com/json/${host}?fields=status,message,query`;
console.log(`${appName}: Getting IP for '${host}' ( ${url} )`);
try {
const response = await fetch(url, { method: 'GET' });
if (response.ok) {
const data = await response.json();
if (data.status === 'success') {
if (data.status == 'success') {
const ip = data.query;
console.log(`${appName}: Got IP for '${host}' : ${ip}`);
return ip;
} else {
console.error(`${appName}: ERROR - API returned an error message:\n${data.message}`);
console.log(`${appName}: ERROR - API returned an error message:\n${data.message}`);
return "";
}
} else {
if (response.headers['X-R1'] <= 0) {
console.error(`${appName}: ERROR - The API call limit is reached`);
console.error(`${appName}: ERROR - Try again in at least ${response.headers['X-Ttl']} seconds`);
console.log(`${appName}: ERROR - The API call limit is reached`);
console.log(`${appName}: ERROR - Try again in at least ${response.headers['X-Ttl']} seconds`);
throw new Error('API call limit reached');
}
console.error(`${appName}: ERROR - returned an HTTP error code:\n${response.status} (${response.statusText})`);
console.log(`${appName}: ERROR - returned an HTTP error code:\n${response.status} (${response.statusText})`);
return "";
}
} catch (error) {
console.error(`${appName}: ERROR - An error occurred while getting IP for '${host}' :`, error);
console.log(`${appName}: ERROR - An error occurred while getting IP for '${host}' :`);
console.error(error);
return "";
}
}
Expand All @@ -74,19 +75,19 @@ async function getIP(host) {
* @returns {Promise<Array>} - 返回包含所有网站 IP 地址的数组
*/
async function getIPs(cache = true) {
const promises = sites.map(async (site) => {
let promises = sites.map(async (site) => {
try {
const ip = await getIP(site);
let ip = await getIP(site);
return { host: site, ip: ip };
} catch (err) {
if (err.message === 'API call limit reached') {
if (err.message == 'API call limit reached') {
process.exit(1);
} else {
throw err;
}
}
});
const IPs = await Promise.all(promises);
let IPs = await Promise.all(promises);

if (cache) {
cacheIPs(IPs);
Expand All @@ -103,19 +104,18 @@ async function getIPs(cache = true) {
*/
function cacheIPs(IPs) {
console.log(`${appName}: Caching IPs...`);
const now = Date.now();
const cache = { time: now, IPs: IPs };
const json = JSON.stringify(cache);

let now = Date.now();
let cache = { time: now, IPs: IPs };
let json = JSON.stringify(cache);
try {
const cacheDir = path.join(__dirname, "files/cache");
if (!fs.existsSync(cacheDir)) {
fs.mkdirSync(cacheDir, { recursive: true });
if (!fs.existsSync(path.join(__dirname, "files/cache"))) {
fs.mkdirSync(path.join(__dirname, "files/cache"), { recursive: true });
}
fs.writeFileSync(path.join(cacheDir, "cache.json"), json);
fs.writeFileSync(path.join(__dirname, "files/cache/cache.json"), json);
console.info(`${appName}: Successfully cached IPs`);
} catch (error) {
console.error(`${appName}: ERROR - An error occurred while caching IPs :`, error);
console.error(`${appName}: ERROR - An error occurred while caching IPs :`);
console.error(error);
}
}

Expand All @@ -126,28 +126,42 @@ function cacheIPs(IPs) {
*/
function readCache() {
try {
const cachePath = path.join(__dirname, "files/cache/cache.json");
if (fs.existsSync(cachePath)) {
const data = fs.readFileSync(cachePath);
const cache = JSON.parse(data);
const now = Date.now();
if (now - cache.time < 60 * 60 * 3) { // 保留3小时内的缓存
const isValidCache = cache.IPs.every(record => typeof record.host === "string" && typeof record.ip === "string");
if (isValidCache) {
if (fs.existsSync(path.join(__dirname, "files/cache/cache.json"))) {
let data = fs.readFileSync(path.join(__dirname, "files/cache/cache.json"));
let cache = JSON.parse(data);
let now = Date.now();
if (now - cache.time < 60 * 60 * 3) {
let flag = true;
for (let record of cache.IPs) {
if (!(typeof record.host === "string" && typeof record.ip === "string")) {
flag = false;
break;
}
}
if (flag) {
return cache.IPs;
} else {
console.info(`${appName}: cache file corrupted, ignore it`);
return null;
}
} else {
console.info(`${appName}: cache file expired, ignore it`);
return null;
}
} else {
console.info(`${appName}: cache file not exist, ignore it`);
return null;
}
} catch (error) {
console.error(`${appName}: ERROR - An error occurred while reading cache:`, error);
console.error(`${appName}: ERROR - An error occurred while reading cache:`);
console.error(error);
return null;
}
return null;
}

function checkIPv4(IP) {
const parts = IP.split(".");
return parts.length === 4 && parts.every(part => !isNaN(part) && Number(part) >= 0 && Number(part) <= 255);
}

module.exports = { getIPs, readCache };
42 changes: 32 additions & 10 deletions main.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,40 @@ const { restoreHosts } = require("./restoreHosts.js");

const appName = "Easy GitHub Hosts";

const cmd = process.argv[2];
function main() {
let argv = process.argv.slice(2);

(async () => {
switch (cmd) {
case "--restore":
console.log(`${appName}: Command --restore detected`);
// Filter out Node.js specific flags
argv = argv.filter(arg => !arg.startsWith('--inspect') && !arg.startsWith('--inspect-brk'));

if (argv.length === 0) {
console.error(`${appName}: ERROR - No arguments provided.`);
console.info(`${appName}: Usage: node main.js <command>`);
console.info(`${appName}: Commands:`);
console.info(`${appName}: - update: Update the HOSTS file with GitHub IPs`);
console.info(`${appName}: - restore: Restore the HOSTS file from backup`);
process.exit(1);
}

const command = argv[0];

switch (command) {
case "update":
updateHosts();
break;
case "restore":
restoreHosts();
break;
case "--update":
default:
console.log(`${appName}: Command --update detected or no command provided`);
await updateHosts();
break;
console.error(`${appName}: ERROR - Unknown command: ${command}`);
console.info(`${appName}: Usage: node main.js <command>`);
console.info(`${appName}: Commands:`);
console.info(`${appName}: - update: Update the HOSTS file with GitHub IPs`);
console.info(`${appName}: - restore: Restore the HOSTS file from backup`);
process.exit(1);
}
})();
}

if (require.main === module) {
main();
}
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 1 addition & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
{
"name": "easy-github-hosts",
"version": "1.4.1",
"version": "1.4.2",
"description": "Easy to add IP of GitHub into your HOSTS file.",
"author": "lingbopro,Minemetero",
"license": "MIT",
"main": "main.js",
"scripts": {
"test": "node main.js --debug --noedit",
"start": "node main.js --update",
"restore": "node main.js --restore"
},
Expand Down
2 changes: 1 addition & 1 deletion restoreHosts.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ function restoreHosts() {
console.log(`${appName}: Starting restoration`);
// 之前为什么要用hosts路径作为文件名呢... 嗨嗨嗨,你问我?
const hostsPath = os.type().includes("Windows") ? "C:\\Windows\\System32\\drivers\\etc\\hosts" : "/etc/hosts";
const backupPath = path.join(__dirname, 'files/backup', 'hostsfile.backup');
const backupPath = path.join(__dirname, 'files/backup', `hostsfile.backup`);

if (!fs.existsSync(backupPath)) {
console.error(`${appName}: ERROR - Backup file not found: ${backupPath}`);
Expand Down
Loading

0 comments on commit 10e6914

Please sign in to comment.