2026-01-18 23:35:56 +08:00
|
|
|
const fs = require('fs');
|
2026-01-30 23:07:58 +08:00
|
|
|
const yaml = require('js-yaml');
|
|
|
|
|
const axios = require('axios');
|
2026-01-18 23:35:56 +08:00
|
|
|
const path = require('path');
|
|
|
|
|
|
2026-01-30 23:07:58 +08:00
|
|
|
const linksPath = path.join(__dirname, '../themes/Ying/data/links.yaml');
|
|
|
|
|
const outputPath = path.join(__dirname, '../static/link_status.json');
|
2026-01-18 23:35:56 +08:00
|
|
|
|
2026-01-30 23:07:58 +08:00
|
|
|
// Ensure static dir exists
|
|
|
|
|
if (!fs.existsSync(path.dirname(outputPath))) {
|
|
|
|
|
fs.mkdirSync(path.dirname(outputPath), { recursive: true });
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function checkLinks() {
|
|
|
|
|
console.log('Starting link check...');
|
2026-01-18 23:35:56 +08:00
|
|
|
try {
|
2026-01-30 23:07:58 +08:00
|
|
|
const fileContents = fs.readFileSync(linksPath, 'utf8');
|
|
|
|
|
const data = yaml.load(fileContents);
|
2026-01-18 23:35:56 +08:00
|
|
|
|
2026-01-30 23:07:58 +08:00
|
|
|
if (!data || !data.blogs) {
|
|
|
|
|
console.log('No blogs found in links.yaml');
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const results = {};
|
|
|
|
|
// Process in chunks to avoid too many concurrent connections
|
|
|
|
|
const batchSize = 10;
|
|
|
|
|
const blogs = data.blogs;
|
2026-01-18 23:35:56 +08:00
|
|
|
|
2026-01-30 23:07:58 +08:00
|
|
|
for (let i = 0; i < blogs.length; i += batchSize) {
|
|
|
|
|
const batch = blogs.slice(i, i + batchSize);
|
|
|
|
|
await Promise.all(batch.map(async (blog) => {
|
|
|
|
|
if (!blog.url) return;
|
|
|
|
|
try {
|
|
|
|
|
const response = await axios.head(blog.url, {
|
|
|
|
|
timeout: 10000,
|
|
|
|
|
maxRedirects: 5,
|
|
|
|
|
headers: {
|
|
|
|
|
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
|
|
|
|
|
},
|
|
|
|
|
validateStatus: (status) => status >= 200 && status < 400
|
|
|
|
|
});
|
|
|
|
|
results[blog.url] = true;
|
|
|
|
|
console.log(`[OK] ${blog.name}`);
|
|
|
|
|
} catch (error) {
|
|
|
|
|
// Retry with GET if HEAD fails (some servers block HEAD)
|
|
|
|
|
try {
|
|
|
|
|
console.log(`[RETRY] ${blog.name} (HEAD failed, trying GET)...`);
|
|
|
|
|
await axios.get(blog.url, {
|
|
|
|
|
timeout: 10000,
|
|
|
|
|
maxRedirects: 5,
|
|
|
|
|
headers: {
|
|
|
|
|
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
|
|
|
|
|
},
|
|
|
|
|
validateStatus: (status) => status >= 200 && status < 400
|
|
|
|
|
});
|
|
|
|
|
results[blog.url] = true;
|
|
|
|
|
console.log(`[OK] ${blog.name} (GET success)`);
|
|
|
|
|
} catch (err2) {
|
|
|
|
|
results[blog.url] = false;
|
|
|
|
|
console.log(`[FAIL] ${blog.name} - ${error.message}`);
|
2026-01-18 23:35:56 +08:00
|
|
|
}
|
|
|
|
|
}
|
2026-01-30 23:07:58 +08:00
|
|
|
}));
|
2026-01-18 23:35:56 +08:00
|
|
|
}
|
|
|
|
|
|
2026-01-30 23:07:58 +08:00
|
|
|
fs.writeFileSync(outputPath, JSON.stringify(results, null, 2));
|
|
|
|
|
console.log(`Link status saved to ${outputPath}`);
|
2026-01-18 23:35:56 +08:00
|
|
|
|
|
|
|
|
} catch (e) {
|
2026-01-30 23:07:58 +08:00
|
|
|
console.error(e);
|
2026-01-18 23:35:56 +08:00
|
|
|
process.exit(1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-30 23:07:58 +08:00
|
|
|
checkLinks();
|