refactor: Improve finding or creating collections in downloadVideo function
This commit is contained in:
@@ -325,20 +325,6 @@ export const downloadVideo = async (
|
||||
title || "Bilibili Video"
|
||||
);
|
||||
|
||||
// Create a collection for the multi-part video if collectionName is provided
|
||||
let collectionId: string | null = null;
|
||||
if (collectionName) {
|
||||
const newCollection = {
|
||||
id: Date.now().toString(),
|
||||
name: collectionName,
|
||||
videos: [],
|
||||
createdAt: new Date().toISOString(),
|
||||
title: collectionName,
|
||||
};
|
||||
storageService.saveCollection(newCollection);
|
||||
collectionId = newCollection.id;
|
||||
}
|
||||
|
||||
// Start downloading the first part
|
||||
const baseUrl = videoUrl.split("?")[0];
|
||||
const firstPartUrl = `${baseUrl}?p=1`;
|
||||
@@ -346,6 +332,46 @@ export const downloadVideo = async (
|
||||
// Check if part 1 already exists
|
||||
const existingPart1 = storageService.getVideoBySourceUrl(firstPartUrl);
|
||||
let firstPartResult: DownloadResult;
|
||||
let collectionId: string | null = null;
|
||||
|
||||
// Find or create collection
|
||||
if (collectionName) {
|
||||
// First, try to find if an existing part belongs to a collection
|
||||
if (existingPart1?.id) {
|
||||
const existingCollection = storageService.getCollectionByVideoId(existingPart1.id);
|
||||
if (existingCollection) {
|
||||
collectionId = existingCollection.id;
|
||||
logger.info(
|
||||
`Found existing collection "${existingCollection.name || existingCollection.title}" for this series`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// If no collection found from existing part, try to find by name
|
||||
if (!collectionId) {
|
||||
const collectionByName = storageService.getCollectionByName(collectionName);
|
||||
if (collectionByName) {
|
||||
collectionId = collectionByName.id;
|
||||
logger.info(
|
||||
`Found existing collection "${collectionName}" by name`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// If still no collection found, create a new one
|
||||
if (!collectionId) {
|
||||
const newCollection = {
|
||||
id: Date.now().toString(),
|
||||
name: collectionName,
|
||||
videos: [],
|
||||
createdAt: new Date().toISOString(),
|
||||
title: collectionName,
|
||||
};
|
||||
storageService.saveCollection(newCollection);
|
||||
collectionId = newCollection.id;
|
||||
logger.info(`Created new collection "${collectionName}"`);
|
||||
}
|
||||
}
|
||||
|
||||
if (existingPart1) {
|
||||
logger.info(
|
||||
@@ -356,7 +382,7 @@ export const downloadVideo = async (
|
||||
videoData: existingPart1,
|
||||
};
|
||||
|
||||
// If we have a collection ID, make sure the existing video is in the collection
|
||||
// Make sure the existing video is in the collection
|
||||
if (collectionId && existingPart1.id) {
|
||||
const collection = storageService.getCollectionById(collectionId);
|
||||
if (collection && !collection.videos.includes(existingPart1.id)) {
|
||||
|
||||
@@ -99,6 +99,56 @@ export function getCollectionById(id: string): Collection | undefined {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a collection that contains a specific video
|
||||
*/
|
||||
export function getCollectionByVideoId(videoId: string): Collection | undefined {
|
||||
try {
|
||||
const rows = db
|
||||
.select({
|
||||
c: collections,
|
||||
cv: collectionVideos,
|
||||
})
|
||||
.from(collections)
|
||||
.innerJoin(
|
||||
collectionVideos,
|
||||
eq(collections.id, collectionVideos.collectionId)
|
||||
)
|
||||
.where(eq(collectionVideos.videoId, videoId))
|
||||
.all();
|
||||
|
||||
if (rows.length === 0) return undefined;
|
||||
|
||||
// Get the first collection that contains this video
|
||||
const collectionId = rows[0].c.id;
|
||||
return getCollectionById(collectionId);
|
||||
} catch (error) {
|
||||
logger.error(
|
||||
"Error getting collection by video id",
|
||||
error instanceof Error ? error : new Error(String(error))
|
||||
);
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a collection by name or title
|
||||
*/
|
||||
export function getCollectionByName(name: string): Collection | undefined {
|
||||
try {
|
||||
const allCollections = getCollections();
|
||||
return allCollections.find(
|
||||
(c) => c.name === name || c.title === name
|
||||
);
|
||||
} catch (error) {
|
||||
logger.error(
|
||||
"Error getting collection by name",
|
||||
error instanceof Error ? error : new Error(String(error))
|
||||
);
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
export function saveCollection(collection: Collection): Collection {
|
||||
try {
|
||||
db.transaction(() => {
|
||||
|
||||
@@ -51,6 +51,8 @@ export {
|
||||
export {
|
||||
getCollections,
|
||||
getCollectionById,
|
||||
getCollectionByVideoId,
|
||||
getCollectionByName,
|
||||
saveCollection,
|
||||
atomicUpdateCollection,
|
||||
deleteCollection,
|
||||
|
||||
@@ -60,16 +60,26 @@ const Collections: React.FC<CollectionsProps> = ({ collections, onItemClick }) =
|
||||
<Folder fontSize="small" sx={{ mr: 1, color: 'secondary.main' }} />
|
||||
<ListItemText
|
||||
primary={collection.name}
|
||||
primaryTypographyProps={{
|
||||
variant: 'body2',
|
||||
noWrap: true
|
||||
slotProps={{
|
||||
primary: {
|
||||
variant: 'body2',
|
||||
noWrap: true
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<Chip
|
||||
label={collection.videos.length}
|
||||
label={`${Math.floor(collection.videos?.length || 0)}`}
|
||||
size="small"
|
||||
variant="outlined"
|
||||
sx={{ height: 20, minWidth: 20, ml: 1 }}
|
||||
sx={{
|
||||
height: 20,
|
||||
minWidth: 20,
|
||||
ml: 1,
|
||||
'& .MuiChip-label': {
|
||||
padding: '0 4px',
|
||||
fontSize: '0.75rem'
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</ListItemButton>
|
||||
))}
|
||||
|
||||
Reference in New Issue
Block a user