Skip to content

Commit b960b00

Browse files
committed
Another attempt at rescan, can't test locally without more substantial effort. Testing directly on deployment since this is in alpha/noone but me :D
1 parent 85dadfa commit b960b00

File tree

4 files changed

+91
-15
lines changed

4 files changed

+91
-15
lines changed

frontend/src/pages/SystemInfoPage.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ const SystemInfoPage: React.FC = () => {
8383

8484
toast({
8585
title: 'Library Rescanned',
86-
description: `Successfully rescanned library. Found ${data.new_videos_count} new videos.`,
86+
description: `Successfully rescanned library. Found ${data.new_videos_count} new videos and updated ${data.updated_videos_count} existing videos.`,
8787
status: 'success',
8888
duration: 5000,
8989
isClosable: true,

src/routes/scan.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ pub fn router(app_state: AppState) -> Router {
1515
struct ScanResponse {
1616
new_videos_count: usize,
1717
new_videos: Vec<crate::models::Video>,
18+
updated_videos_count: usize,
19+
updated_videos: Vec<crate::models::Video>,
1820
}
1921

2022
async fn scan_directories(State(state): State<AppState>) -> Result<Json<ScanResponse>> {
@@ -31,7 +33,7 @@ async fn scan_directories(State(state): State<AppState>) -> Result<Json<ScanResp
3133
let source_paths = state.config.media.source_paths.clone();
3234

3335
// Scan directories
34-
let new_videos = ScannerService::scan_directories(
36+
let (new_videos, updated_videos) = ScannerService::scan_directories(
3537
&source_paths,
3638
&video_service,
3739
&thumbnail_service,
@@ -40,6 +42,8 @@ async fn scan_directories(State(state): State<AppState>) -> Result<Json<ScanResp
4042
let response = ScanResponse {
4143
new_videos_count: new_videos.len(),
4244
new_videos,
45+
updated_videos_count: updated_videos.len(),
46+
updated_videos,
4347
};
4448

4549
Ok(Json(response))

src/services/scanner.rs

Lines changed: 35 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -137,8 +137,9 @@ impl ScannerService {
137137
path_configs: &[crate::config::MediaPathConfig],
138138
video_service: &VideoService,
139139
thumbnail_service: &ThumbnailService,
140-
) -> Result<Vec<Video>, AppError> {
140+
) -> Result<(Vec<Video>, Vec<Video>), AppError> {
141141
let mut new_videos = Vec::new();
142+
let mut updated_videos = Vec::new();
142143

143144
for path_config in path_configs {
144145
info!("Scanning directory: {}", path_config.path);
@@ -161,13 +162,6 @@ impl ScannerService {
161162
let file_path = entry.path().to_string_lossy().to_string();
162163
let file_name = entry.file_name().to_string_lossy().to_string();
163164

164-
// Check if video already exists in database
165-
if video_service.find_by_path(&file_path).await.is_ok() {
166-
continue;
167-
}
168-
169-
info!("Found new video: {}", file_path);
170-
171165
// Get file metadata
172166
let metadata = match fs::metadata(&file_path).await {
173167
Ok(m) => m,
@@ -195,9 +189,6 @@ impl ScannerService {
195189
}
196190
};
197191

198-
// Create video record
199-
let file_name_clone = file_name.clone();
200-
201192
// Extract duration for video files
202193
let duration = if let Some(ext) = std::path::Path::new(&file_path).extension() {
203194
let ext = ext.to_string_lossy().to_lowercase();
@@ -240,6 +231,37 @@ impl ScannerService {
240231
None
241232
};
242233

234+
// Check if video already exists in database
235+
match video_service.find_by_path(&file_path).await {
236+
Ok(existing_video) => {
237+
// Update existing video with new metadata
238+
info!("Updating existing video: {}", file_path);
239+
match video_service.update_technical_metadata(
240+
&existing_video.id,
241+
Some(metadata.len() as i64),
242+
duration,
243+
thumbnail_path,
244+
original_file_path
245+
).await {
246+
Ok(updated_video) => {
247+
updated_videos.push(updated_video);
248+
},
249+
Err(e) => {
250+
error!("Error updating video metadata: {}", e);
251+
}
252+
}
253+
continue;
254+
},
255+
Err(_) => {
256+
// Video doesn't exist, continue with creation
257+
}
258+
};
259+
260+
info!("Found new video: {}", file_path);
261+
262+
// Create video record
263+
let file_name_clone = file_name.clone();
264+
243265
let create_dto = CreateVideoDto {
244266
file_path,
245267
file_name,
@@ -266,8 +288,8 @@ impl ScannerService {
266288
}
267289
}
268290

269-
info!("Scan complete. Found {} new videos", new_videos.len());
270-
Ok(new_videos)
291+
info!("Scan complete. Found {} new videos and updated {} existing videos", new_videos.len(), updated_videos.len());
292+
Ok((new_videos, updated_videos))
271293
}
272294

273295
fn get_video_files(dir: &Path) -> Result<Vec<walkdir::DirEntry>> {

src/services/video.rs

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,56 @@ impl VideoService {
278278
self.find_by_id(id).await
279279
}
280280

281+
pub async fn update_technical_metadata(&self, id: &str, file_size: Option<i64>, duration: Option<i64>, thumbnail_path: Option<String>, original_file_path: Option<String>) -> Result<Video> {
282+
let mut tx = self.db.begin().await.map_err(AppError::Database)?;
283+
284+
// Check if video exists
285+
let video = self.find_by_id(id).await?;
286+
let now = chrono::Utc::now().to_rfc3339();
287+
288+
// Update video fields
289+
let mut query = "UPDATE videos SET updated_at = ?".to_string();
290+
let mut params: Vec<String> = vec![now.clone()];
291+
292+
if let Some(size) = file_size {
293+
query.push_str(", file_size = ?");
294+
params.push(size.to_string());
295+
}
296+
297+
if let Some(dur) = duration {
298+
query.push_str(", duration = ?");
299+
params.push(dur.to_string());
300+
}
301+
302+
if let Some(thumb) = &thumbnail_path {
303+
query.push_str(", thumbnail_path = ?");
304+
params.push(thumb.clone());
305+
}
306+
307+
if let Some(orig) = &original_file_path {
308+
query.push_str(", original_file_path = ?");
309+
params.push(orig.clone());
310+
}
311+
312+
query.push_str(" WHERE id = ?");
313+
params.push(id.to_string());
314+
315+
let mut query_builder = sqlx::query(&query);
316+
for param in params {
317+
query_builder = query_builder.bind(param);
318+
}
319+
320+
query_builder
321+
.execute(&mut *tx)
322+
.await
323+
.map_err(AppError::Database)?;
324+
325+
tx.commit().await.map_err(AppError::Database)?;
326+
327+
// Return the updated video (find_by_id already transforms the thumbnail path)
328+
self.find_by_id(id).await
329+
}
330+
281331
pub async fn delete(&self, id: &str) -> Result<()> {
282332
let video = self.find_by_id(id).await?;
283333

0 commit comments

Comments
 (0)