fix
This commit is contained in:
@ -107,7 +107,7 @@ function extractDomain(url: string): string | null {
|
||||
}
|
||||
|
||||
// Initialize database with proper error handling
|
||||
function initializeDatabase(): Database {
|
||||
async function initializeDatabase(): Promise<Database> {
|
||||
// Ensure data directory exists
|
||||
if (!fs.existsSync(config.paths.dataDir)) {
|
||||
fs.mkdirSync(config.paths.dataDir, { recursive: true });
|
||||
@ -205,10 +205,12 @@ function initializeDatabase(): Database {
|
||||
// Perform database integrity checks and fixes
|
||||
performDatabaseIntegrityFixes(db);
|
||||
|
||||
await migrateFeedsWithCategories();
|
||||
|
||||
return db;
|
||||
}
|
||||
|
||||
const db = initializeDatabase();
|
||||
const db = await initializeDatabase();
|
||||
|
||||
export interface Feed {
|
||||
id: string;
|
||||
@ -581,11 +583,15 @@ export async function getFeedsByCategory(category?: string): Promise<Feed[]> {
|
||||
let rows;
|
||||
|
||||
if (category) {
|
||||
stmt = db.prepare("SELECT * FROM feeds WHERE category = ? AND active = 1 ORDER BY created_at DESC");
|
||||
stmt = db.prepare(
|
||||
"SELECT * FROM feeds WHERE category = ? AND active = 1 ORDER BY created_at DESC",
|
||||
);
|
||||
rows = stmt.all(category) as any[];
|
||||
} else {
|
||||
// If no category specified, return all active feeds
|
||||
stmt = db.prepare("SELECT * FROM feeds WHERE active = 1 ORDER BY created_at DESC");
|
||||
stmt = db.prepare(
|
||||
"SELECT * FROM feeds WHERE active = 1 ORDER BY created_at DESC",
|
||||
);
|
||||
rows = stmt.all() as any[];
|
||||
}
|
||||
|
||||
@ -607,7 +613,9 @@ export async function getFeedsByCategory(category?: string): Promise<Feed[]> {
|
||||
|
||||
export async function getAllCategories(): Promise<string[]> {
|
||||
try {
|
||||
const stmt = db.prepare("SELECT DISTINCT category FROM feeds WHERE category IS NOT NULL AND active = 1 ORDER BY category");
|
||||
const stmt = db.prepare(
|
||||
"SELECT DISTINCT category FROM feeds WHERE category IS NOT NULL AND active = 1 ORDER BY category",
|
||||
);
|
||||
const rows = stmt.all() as any[];
|
||||
|
||||
return rows.map((row) => row.category).filter(Boolean);
|
||||
@ -617,13 +625,15 @@ export async function getAllCategories(): Promise<string[]> {
|
||||
}
|
||||
}
|
||||
|
||||
export async function getFeedsGroupedByCategory(): Promise<{ [category: string]: Feed[] }> {
|
||||
export async function getFeedsGroupedByCategory(): Promise<{
|
||||
[category: string]: Feed[];
|
||||
}> {
|
||||
try {
|
||||
const feeds = await getAllFeeds();
|
||||
const grouped: { [category: string]: Feed[] } = {};
|
||||
|
||||
for (const feed of feeds) {
|
||||
const category = feed.category || 'Uncategorized';
|
||||
const category = feed.category || "Uncategorized";
|
||||
if (!grouped[category]) {
|
||||
grouped[category] = [];
|
||||
}
|
||||
@ -1121,7 +1131,9 @@ export async function migrateFeedsWithCategories(): Promise<void> {
|
||||
console.log("🔄 Starting feed category migration...");
|
||||
|
||||
// Get all feeds without categories
|
||||
const stmt = db.prepare("SELECT * FROM feeds WHERE category IS NULL OR category = ''");
|
||||
const stmt = db.prepare(
|
||||
"SELECT * FROM feeds WHERE category IS NULL OR category = ''",
|
||||
);
|
||||
const feedsWithoutCategories = stmt.all() as any[];
|
||||
|
||||
if (feedsWithoutCategories.length === 0) {
|
||||
@ -1129,7 +1141,9 @@ export async function migrateFeedsWithCategories(): Promise<void> {
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(`📋 Found ${feedsWithoutCategories.length} feeds without categories`);
|
||||
console.log(
|
||||
`📋 Found ${feedsWithoutCategories.length} feeds without categories`,
|
||||
);
|
||||
|
||||
// Import LLM service
|
||||
const { openAI_ClassifyFeed } = await import("./llm.js");
|
||||
@ -1148,30 +1162,41 @@ export async function migrateFeedsWithCategories(): Promise<void> {
|
||||
const category = await openAI_ClassifyFeed(titleForClassification);
|
||||
|
||||
// Update the feed with the category
|
||||
const updateStmt = db.prepare("UPDATE feeds SET category = ? WHERE id = ?");
|
||||
const updateStmt = db.prepare(
|
||||
"UPDATE feeds SET category = ? WHERE id = ?",
|
||||
);
|
||||
updateStmt.run(category, feed.id);
|
||||
|
||||
console.log(`✅ Assigned category "${category}" to feed: ${titleForClassification}`);
|
||||
console.log(
|
||||
`✅ Assigned category "${category}" to feed: ${titleForClassification}`,
|
||||
);
|
||||
processedCount++;
|
||||
|
||||
// Add a small delay to avoid rate limiting
|
||||
await new Promise(resolve => setTimeout(resolve, 1000));
|
||||
|
||||
await new Promise((resolve) => setTimeout(resolve, 1000));
|
||||
} catch (error) {
|
||||
console.error(`❌ Failed to classify feed ${feed.title || feed.url}:`, error);
|
||||
console.error(
|
||||
`❌ Failed to classify feed ${feed.title || feed.url}:`,
|
||||
error,
|
||||
);
|
||||
errorCount++;
|
||||
|
||||
// Set a default category for failed classifications
|
||||
const defaultCategory = "その他";
|
||||
const updateStmt = db.prepare("UPDATE feeds SET category = ? WHERE id = ?");
|
||||
const updateStmt = db.prepare(
|
||||
"UPDATE feeds SET category = ? WHERE id = ?",
|
||||
);
|
||||
updateStmt.run(defaultCategory, feed.id);
|
||||
console.log(`⚠️ Assigned default category "${defaultCategory}" to feed: ${feed.title || feed.url}`);
|
||||
console.log(
|
||||
`! Assigned default category "${defaultCategory}" to feed: ${feed.title || feed.url}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`✅ Feed category migration completed`);
|
||||
console.log(`📊 Processed: ${processedCount}, Errors: ${errorCount}, Total: ${feedsWithoutCategories.length}`);
|
||||
|
||||
console.log(
|
||||
`📊 Processed: ${processedCount}, Errors: ${errorCount}, Total: ${feedsWithoutCategories.length}`,
|
||||
);
|
||||
} catch (error) {
|
||||
console.error("❌ Error during feed category migration:", error);
|
||||
throw error;
|
||||
@ -1186,11 +1211,15 @@ export async function getFeedCategoryMigrationStatus(): Promise<{
|
||||
migrationComplete: boolean;
|
||||
}> {
|
||||
try {
|
||||
const totalStmt = db.prepare("SELECT COUNT(*) as count FROM feeds WHERE active = 1");
|
||||
const totalStmt = db.prepare(
|
||||
"SELECT COUNT(*) as count FROM feeds WHERE active = 1",
|
||||
);
|
||||
const totalResult = totalStmt.get() as any;
|
||||
const totalFeeds = totalResult.count;
|
||||
|
||||
const withCategoriesStmt = db.prepare("SELECT COUNT(*) as count FROM feeds WHERE active = 1 AND category IS NOT NULL AND category != ''");
|
||||
const withCategoriesStmt = db.prepare(
|
||||
"SELECT COUNT(*) as count FROM feeds WHERE active = 1 AND category IS NOT NULL AND category != ''",
|
||||
);
|
||||
const withCategoriesResult = withCategoriesStmt.get() as any;
|
||||
const feedsWithCategories = withCategoriesResult.count;
|
||||
|
||||
@ -1212,7 +1241,9 @@ export async function getFeedCategoryMigrationStatus(): Promise<{
|
||||
export async function deleteEpisode(episodeId: string): Promise<boolean> {
|
||||
try {
|
||||
// Get episode info first to find the audio file path
|
||||
const episodeStmt = db.prepare("SELECT audio_path FROM episodes WHERE id = ?");
|
||||
const episodeStmt = db.prepare(
|
||||
"SELECT audio_path FROM episodes WHERE id = ?",
|
||||
);
|
||||
const episode = episodeStmt.get(episodeId) as any;
|
||||
|
||||
if (!episode) {
|
||||
@ -1226,13 +1257,19 @@ export async function deleteEpisode(episodeId: string): Promise<boolean> {
|
||||
// If database deletion successful, try to delete the audio file
|
||||
if (result.changes > 0 && episode.audio_path) {
|
||||
try {
|
||||
const fullAudioPath = path.join(config.paths.projectRoot, episode.audio_path);
|
||||
const fullAudioPath = path.join(
|
||||
config.paths.projectRoot,
|
||||
episode.audio_path,
|
||||
);
|
||||
if (fs.existsSync(fullAudioPath)) {
|
||||
fs.unlinkSync(fullAudioPath);
|
||||
console.log(`🗑️ Deleted audio file: ${fullAudioPath}`);
|
||||
console.log(`🗑 Deleted audio file: ${fullAudioPath}`);
|
||||
}
|
||||
} catch (fileError) {
|
||||
console.warn(`⚠️ Failed to delete audio file ${episode.audio_path}:`, fileError);
|
||||
console.warn(
|
||||
`! Failed to delete audio file ${episode.audio_path}:`,
|
||||
fileError,
|
||||
);
|
||||
// Don't fail the operation if file deletion fails
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user