fixed 部署友圈bug
This commit is contained in:
1 parent
9c669badba
commit
d65d6d94c7
2 files changed
+29
-58
No files matched your search
@@ -9,7 +9,7 @@ const MAX_POSTS_PER_FRIEND = 5;
|
|||||||
const MAX_TOTAL_POSTS = 100; // Limit total output size
|
const MAX_TOTAL_POSTS = 100; // Limit total output size
|
||||||
|
|
||||||
const parser = new Parser({
|
const parser = new Parser({
|
||||||
timeout: 5000,
|
timeout: 10000, // 10s timeout
|
||||||
headers: {
|
headers: {
|
||||||
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36'
|
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36'
|
||||||
}
|
}
|
||||||
@@ -20,44 +20,10 @@ async function fetchFeed(url) {
|
|||||||
const feed = await parser.parseURL(url);
|
const feed = await parser.parseURL(url);
|
||||||
return feed;
|
return feed;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// console.error(`Failed to fetch ${url}: ${error.message}`);
|
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getRssUrl(friend) {
|
|
||||||
// If RSS is explicitly provided (4th element in array)
|
|
||||||
if (friend.length >= 4 && friend[3]) {
|
|
||||||
return friend[3];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Otherwise, try to guess
|
|
||||||
const baseUrl = friend[1].replace(/\/$/, '');
|
|
||||||
const guesses = [
|
|
||||||
`${baseUrl}/atom.xml`,
|
|
||||||
`${baseUrl}/rss.xml`,
|
|
||||||
`${baseUrl}/feed`,
|
|
||||||
`${baseUrl}/feed/`,
|
|
||||||
`${baseUrl}/index.xml`
|
|
||||||
];
|
|
||||||
|
|
||||||
for (const url of guesses) {
|
|
||||||
try {
|
|
||||||
// Simple HEAD request or just try to parse
|
|
||||||
// Since we use rss-parser, just trying to parse is easiest check
|
|
||||||
// But doing this for every friend is slow.
|
|
||||||
// For now, we only use explicit RSS if provided, or simple guess if not.
|
|
||||||
// To speed up, we'll just try the first guess or return null if strict.
|
|
||||||
// But to be helpful, let's try the most common one: atom.xml
|
|
||||||
// ideally we should check HEAD, but let's just return the first guess for now
|
|
||||||
// and let the parser fail if it's wrong.
|
|
||||||
// BETTER STRATEGY: Return a list of candidates and try them.
|
|
||||||
} catch (e) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
return `${baseUrl}/atom.xml`; // Default guess
|
|
||||||
}
|
|
||||||
|
|
||||||
async function main() {
|
async function main() {
|
||||||
console.log('Starting Friend Circle generation...');
|
console.log('Starting Friend Circle generation...');
|
||||||
|
|
||||||
@@ -71,12 +37,17 @@ async function main() {
|
|||||||
|
|
||||||
let allPosts = [];
|
let allPosts = [];
|
||||||
|
|
||||||
// Process friends in batches to avoid overwhelming network
|
// Revert to processing one by one or small batches with sequential candidate checks
|
||||||
const BATCH_SIZE = 10;
|
// to ensure reliability over speed.
|
||||||
const friends = data.friends;
|
const friends = data.friends;
|
||||||
|
|
||||||
for (let i = 0; i < friends.length; i += BATCH_SIZE) {
|
// Using a simple loop to process friends to ensure stability
|
||||||
const batch = friends.slice(i, i + BATCH_SIZE);
|
// We can run a few in parallel, but let's keep candidate checking sequential
|
||||||
|
|
||||||
|
const CONCURRENCY = 5; // Conservative concurrency
|
||||||
|
|
||||||
|
for (let i = 0; i < friends.length; i += CONCURRENCY) {
|
||||||
|
const batch = friends.slice(i, i + CONCURRENCY);
|
||||||
const promises = batch.map(async (friend) => {
|
const promises = batch.map(async (friend) => {
|
||||||
const name = friend[0];
|
const name = friend[0];
|
||||||
const blogUrl = friend[1];
|
const blogUrl = friend[1];
|
||||||
@@ -93,32 +64,35 @@ async function main() {
|
|||||||
candidates.push(`${cleanUrl}/rss.xml`);
|
candidates.push(`${cleanUrl}/rss.xml`);
|
||||||
candidates.push(`${cleanUrl}/feed`);
|
candidates.push(`${cleanUrl}/feed`);
|
||||||
candidates.push(`${cleanUrl}/feed/`);
|
candidates.push(`${cleanUrl}/feed/`);
|
||||||
candidates.push(`${cleanUrl}/feed.xml`);
|
|
||||||
candidates.push(`${cleanUrl}/index.xml`);
|
candidates.push(`${cleanUrl}/index.xml`);
|
||||||
candidates.push(`${cleanUrl}/rss`);
|
|
||||||
candidates.push(`${cleanUrl}/atom`);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let feed = null;
|
let feed = null;
|
||||||
try {
|
|
||||||
// Try all candidates in parallel and take the first success
|
// Sequential candidate check (Reliable)
|
||||||
feed = await Promise.any(candidates.map(url => fetchFeed(url)));
|
for (const url of candidates) {
|
||||||
// console.log(`[${name}] Fetched RSS successfully.`);
|
try {
|
||||||
} catch (err) {
|
feed = await fetchFeed(url);
|
||||||
// All candidates failed
|
// console.log(`[${name}] Fetched RSS successfully: ${url}`);
|
||||||
// console.error(`[${name}] All RSS candidates failed:`, err.errors);
|
break; // Found one, stop checking
|
||||||
console.log(`[${name}] No valid RSS found. Candidates: ${candidates.join(', ')}`);
|
} catch (e) {
|
||||||
|
// Continue to next candidate
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!feed) {
|
||||||
|
console.log(`[${name}] No valid RSS found.`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Extract posts
|
// Extract posts
|
||||||
|
if (!feed.items) return;
|
||||||
|
|
||||||
const posts = feed.items.slice(0, MAX_POSTS_PER_FRIEND).map(item => {
|
const posts = feed.items.slice(0, MAX_POSTS_PER_FRIEND).map(item => {
|
||||||
let img = null;
|
let img = null;
|
||||||
// Try to find an image in content
|
// Try to find an image in content
|
||||||
// Priority: content:encoded > content > description
|
|
||||||
const content = item['content:encoded'] || item.content || item.description || '';
|
const content = item['content:encoded'] || item.content || item.description || '';
|
||||||
|
|
||||||
// Better regex to capture src with single or double quotes
|
|
||||||
const imgMatch = content.match(/<img[^>]+src=['"]([^'"]+)['"]/i);
|
const imgMatch = content.match(/<img[^>]+src=['"]([^'"]+)['"]/i);
|
||||||
|
|
||||||
if (imgMatch) {
|
if (imgMatch) {
|
||||||
@@ -130,11 +104,8 @@ async function main() {
|
|||||||
// Get a short snippet
|
// Get a short snippet
|
||||||
let snippet = '';
|
let snippet = '';
|
||||||
if (content) {
|
if (content) {
|
||||||
// Remove HTML tags
|
|
||||||
snippet = content.replace(/<[^>]+>/g, '');
|
snippet = content.replace(/<[^>]+>/g, '');
|
||||||
// Remove excessive whitespace
|
|
||||||
snippet = snippet.replace(/\s+/g, ' ').trim();
|
snippet = snippet.replace(/\s+/g, ' ').trim();
|
||||||
// Truncate
|
|
||||||
if (snippet.length > 120) {
|
if (snippet.length > 120) {
|
||||||
snippet = snippet.substring(0, 120) + '...';
|
snippet = snippet.substring(0, 120) + '...';
|
||||||
}
|
}
|
||||||
@@ -143,7 +114,7 @@ async function main() {
|
|||||||
return {
|
return {
|
||||||
title: item.title,
|
title: item.title,
|
||||||
link: item.link,
|
link: item.link,
|
||||||
date: item.isoDate || item.pubDate, // RSS parser standardizes this
|
date: item.isoDate || item.pubDate,
|
||||||
author: name,
|
author: name,
|
||||||
avatar: avatar,
|
avatar: avatar,
|
||||||
blogUrl: blogUrl,
|
blogUrl: blogUrl,
|
||||||
@@ -156,7 +127,7 @@ async function main() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
await Promise.all(promises);
|
await Promise.all(promises);
|
||||||
process.stdout.write(`Processed ${Math.min(i + BATCH_SIZE, friends.length)}/${friends.length} friends...\r`);
|
process.stdout.write(`Processed ${Math.min(i + CONCURRENCY, friends.length)}/${friends.length} friends...\r`);
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('\nSorting and saving...');
|
console.log('\nSorting and saving...');
|
||||||
|
|||||||
@@ -648,7 +648,7 @@ ul {
|
|||||||
display: inline-block;
|
display: inline-block;
|
||||||
list-style: none;
|
list-style: none;
|
||||||
margin-left: 0;
|
margin-left: 0;
|
||||||
margin-right: 15px;
|
margin-right: 16px;
|
||||||
margin-top: 20px;
|
margin-top: 20px;
|
||||||
text-transform: capitalize;
|
text-transform: capitalize;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in new issue
Block a user