Nagesh Muralidhar commited on
Commit
b4dc0bf
·
1 Parent(s): d7391ba

midterm-submission

Browse files
Files changed (2) hide show
  1. podcraft/src/pages/Podcasts.tsx +60 -44
  2. server/main.py +31 -30
podcraft/src/pages/Podcasts.tsx CHANGED
@@ -41,7 +41,8 @@ const Podcasts: React.FC = () => {
41
  );
42
  }
43
 
44
- setPodcasts(prev => prev.filter(p => p.filename !== podcast.filename));
 
45
 
46
  } catch (err) {
47
  console.error('Delete error:', err);
@@ -60,16 +61,33 @@ const Podcasts: React.FC = () => {
60
 
61
  const files = await response.json();
62
 
 
 
 
 
 
 
63
  const podcastList: Podcast[] = files.map((file: any, index: number) => {
64
  const filename = file.filename;
65
- const [queryPart, descriptionPart, categoryWithExt] = filename.split('-');
 
 
 
 
 
 
 
 
 
 
 
66
  const category = categoryWithExt.replace('.mp3', '');
67
 
68
  return {
69
  id: index + 1,
70
  title: `${descriptionPart.replace(/_/g, ' ').replace(/^\w/, c => c.toUpperCase())}`,
71
  description: `A debate exploring ${queryPart.replace(/_/g, ' ')}`,
72
- audio_file: file.path, // Use relative path returned from server
73
  filename: filename,
74
  category: category.replace(/_/g, ' ')
75
  };
@@ -77,6 +95,7 @@ const Podcasts: React.FC = () => {
77
 
78
  setPodcasts(podcastList);
79
  } catch (err) {
 
80
  setError(err instanceof Error ? err.message : 'An error occurred');
81
  } finally {
82
  setLoading(false);
@@ -91,14 +110,6 @@ const Podcasts: React.FC = () => {
91
  );
92
  }
93
 
94
- if (error !== "") {
95
- return (
96
- <div className="podcasts-container">
97
- <div className="error-message">Error: {error}</div>
98
- </div>
99
- );
100
- }
101
-
102
  return (
103
  <div className="podcasts-container">
104
  <header className="podcasts-header">
@@ -106,42 +117,47 @@ const Podcasts: React.FC = () => {
106
  <p>Listen to AI-generated debate podcasts on various topics</p>
107
  </header>
108
 
 
 
 
 
109
  <div className="podcasts-grid">
110
- {podcasts.map(podcast => (
111
- <div
112
- key={podcast.id}
113
- className="podcast-card"
114
- onClick={() => navigate(`/podcast/${podcast.id}`)}
115
- style={{ cursor: 'pointer' }}
116
- >
117
- <div className="podcast-content">
118
- <div className="podcast-header">
119
- <h2 className="podcast-title">{podcast.title}</h2>
120
- <button
121
- className="delete-button"
122
- onClick={(e) => {
123
- e.stopPropagation();
124
- handleDelete(podcast);
125
- }}
126
- aria-label="Delete podcast"
127
- >
128
- ×
129
- </button>
130
- </div>
131
- <div className="category-pill">{podcast.category}</div>
132
- <p className="description">{podcast.description}</p>
133
- <div className="audio-player" onClick={e => e.stopPropagation()}>
134
- <audio
135
- controls
136
- src={podcast.audio_file}
137
- >
138
- Your browser does not support the audio element.
139
- </audio>
 
 
140
  </div>
141
  </div>
142
- </div>
143
- ))}
144
- {podcasts.length === 0 && (
145
  <div className="no-podcasts-message">
146
  No podcasts found. Generate your first podcast from the home page!
147
  </div>
 
41
  );
42
  }
43
 
44
+ // Refresh the podcast list after successful deletion
45
+ await fetchPodcasts();
46
 
47
  } catch (err) {
48
  console.error('Delete error:', err);
 
61
 
62
  const files = await response.json();
63
 
64
+ if (!Array.isArray(files) || files.length === 0) {
65
+ setPodcasts([]);
66
+ setLoading(false);
67
+ return;
68
+ }
69
+
70
  const podcastList: Podcast[] = files.map((file: any, index: number) => {
71
  const filename = file.filename;
72
+ const parts = filename.split('-');
73
+ let queryPart = '', descriptionPart = '', categoryWithExt = '';
74
+
75
+ // Handle filenames that might not have all parts
76
+ if (parts.length >= 3) {
77
+ [queryPart, descriptionPart, categoryWithExt] = parts;
78
+ } else {
79
+ queryPart = parts[0] || '';
80
+ descriptionPart = parts[1] || queryPart;
81
+ categoryWithExt = parts[2] || 'general.mp3';
82
+ }
83
+
84
  const category = categoryWithExt.replace('.mp3', '');
85
 
86
  return {
87
  id: index + 1,
88
  title: `${descriptionPart.replace(/_/g, ' ').replace(/^\w/, c => c.toUpperCase())}`,
89
  description: `A debate exploring ${queryPart.replace(/_/g, ' ')}`,
90
+ audio_file: `${API_URL}${file.path}`, // Add API_URL for audio files
91
  filename: filename,
92
  category: category.replace(/_/g, ' ')
93
  };
 
95
 
96
  setPodcasts(podcastList);
97
  } catch (err) {
98
+ console.error('Fetch error:', err);
99
  setError(err instanceof Error ? err.message : 'An error occurred');
100
  } finally {
101
  setLoading(false);
 
110
  );
111
  }
112
 
 
 
 
 
 
 
 
 
113
  return (
114
  <div className="podcasts-container">
115
  <header className="podcasts-header">
 
117
  <p>Listen to AI-generated debate podcasts on various topics</p>
118
  </header>
119
 
120
+ {error && (
121
+ <div className="error-message">Error: {error}</div>
122
+ )}
123
+
124
  <div className="podcasts-grid">
125
+ {podcasts.length > 0 ? (
126
+ podcasts.map(podcast => (
127
+ <div
128
+ key={podcast.id}
129
+ className="podcast-card"
130
+ onClick={() => navigate(`/podcast/${podcast.id}`)}
131
+ style={{ cursor: 'pointer' }}
132
+ >
133
+ <div className="podcast-content">
134
+ <div className="podcast-header">
135
+ <h2 className="podcast-title">{podcast.title}</h2>
136
+ <button
137
+ className="delete-button"
138
+ onClick={(e) => {
139
+ e.stopPropagation();
140
+ handleDelete(podcast);
141
+ }}
142
+ aria-label="Delete podcast"
143
+ >
144
+ ×
145
+ </button>
146
+ </div>
147
+ <div className="category-pill">{podcast.category}</div>
148
+ <p className="description">{podcast.description}</p>
149
+ <div className="audio-player" onClick={e => e.stopPropagation()}>
150
+ <audio
151
+ controls
152
+ src={podcast.audio_file}
153
+ >
154
+ Your browser does not support the audio element.
155
+ </audio>
156
+ </div>
157
  </div>
158
  </div>
159
+ ))
160
+ ) : (
 
161
  <div className="no-podcasts-message">
162
  No podcasts found. Generate your first podcast from the home page!
163
  </div>
server/main.py CHANGED
@@ -133,9 +133,10 @@ async def list_audio_files():
133
  "path": f"/audio-files/{file}",
134
  "size": os.path.getsize(file_path)
135
  })
136
- return audio_files
137
  except Exception as e:
138
- raise HTTPException(status_code=500, detail=str(e))
 
139
 
140
  @api_router.get("/audio/{filename}")
141
  async def get_audio_file(filename: str):
@@ -143,56 +144,56 @@ async def get_audio_file(filename: str):
143
  try:
144
  file_path = os.path.join(audio_dir, filename)
145
  if not os.path.exists(file_path):
 
146
  raise HTTPException(status_code=404, detail="File not found")
147
- return FileResponse(file_path)
148
  except Exception as e:
 
149
  raise HTTPException(status_code=500, detail=str(e))
150
 
151
  @api_router.delete("/audio/{filename}")
152
  async def delete_audio_file(filename: str):
153
  """Delete an audio file and its corresponding transcript."""
154
  try:
155
- # Delete audio file
156
  file_path = os.path.join(audio_dir, filename)
157
  if not os.path.exists(file_path):
 
158
  raise HTTPException(status_code=404, detail="File not found")
159
 
160
- # Get all audio files to determine the podcast ID
161
- audio_files = [f for f in os.listdir(audio_dir) if f.endswith(('.mp3', '.wav'))]
162
  try:
163
- # Find the index (0-based) of the file being deleted
164
- podcast_id = audio_files.index(filename) + 1 # Convert to 1-based ID
165
- logger.info(f"Deleting podcast with ID: {podcast_id}")
166
 
167
- # Path to transcripts file
168
- transcripts_file = os.path.join(os.path.dirname(__file__), "transcripts", "podcasts.json")
169
 
170
- # Update transcripts if file exists
 
171
  if os.path.exists(transcripts_file):
172
  with open(transcripts_file, 'r') as f:
173
  transcripts = json.load(f)
174
 
175
- # Remove the transcript at the corresponding index
176
- if len(transcripts) >= podcast_id:
177
- transcripts.pop(podcast_id - 1) # Convert back to 0-based index
178
-
179
- # Save updated transcripts
180
- with open(transcripts_file, 'w') as f:
181
- json.dump(transcripts, f, indent=2)
182
- logger.info(f"Removed transcript for podcast ID {podcast_id}")
 
 
183
 
184
- # Delete the audio file
185
- os.remove(file_path)
186
- logger.info(f"Deleted audio file: {filename}")
187
-
188
- return {"message": "File and transcript deleted successfully"}
189
 
190
- except ValueError:
191
- logger.error(f"Could not determine podcast ID for file: {filename}")
192
- # Still delete the audio file even if transcript removal fails
193
- os.remove(file_path)
194
- return {"message": "Audio file deleted, but transcript could not be removed"}
195
 
 
 
196
  except Exception as e:
197
  logger.error(f"Error in delete_audio_file: {str(e)}")
198
  raise HTTPException(status_code=500, detail=str(e))
 
133
  "path": f"/audio-files/{file}",
134
  "size": os.path.getsize(file_path)
135
  })
136
+ return audio_files if audio_files else []
137
  except Exception as e:
138
+ logger.error(f"Error listing audio files: {str(e)}")
139
+ return []
140
 
141
  @api_router.get("/audio/{filename}")
142
  async def get_audio_file(filename: str):
 
144
  try:
145
  file_path = os.path.join(audio_dir, filename)
146
  if not os.path.exists(file_path):
147
+ logger.error(f"Audio file not found: {filename}")
148
  raise HTTPException(status_code=404, detail="File not found")
149
+ return FileResponse(file_path, media_type="audio/mpeg")
150
  except Exception as e:
151
+ logger.error(f"Error serving audio file: {str(e)}")
152
  raise HTTPException(status_code=500, detail=str(e))
153
 
154
  @api_router.delete("/audio/{filename}")
155
  async def delete_audio_file(filename: str):
156
  """Delete an audio file and its corresponding transcript."""
157
  try:
158
+ # Check if file exists before attempting deletion
159
  file_path = os.path.join(audio_dir, filename)
160
  if not os.path.exists(file_path):
161
+ logger.error(f"File not found for deletion: {filename}")
162
  raise HTTPException(status_code=404, detail="File not found")
163
 
 
 
164
  try:
165
+ # Delete the audio file first
166
+ os.remove(file_path)
167
+ logger.info(f"Deleted audio file: {filename}")
168
 
169
+ # Get all remaining audio files
170
+ audio_files = [f for f in os.listdir(audio_dir) if f.endswith(('.mp3', '.wav'))]
171
 
172
+ # Try to update transcripts if they exist
173
+ transcripts_file = os.path.join(os.path.dirname(__file__), "transcripts", "podcasts.json")
174
  if os.path.exists(transcripts_file):
175
  with open(transcripts_file, 'r') as f:
176
  transcripts = json.load(f)
177
 
178
+ # Find the index of the deleted file in the original list
179
+ try:
180
+ podcast_id = audio_files.index(filename) + 1
181
+ if len(transcripts) >= podcast_id:
182
+ transcripts.pop(podcast_id - 1)
183
+ with open(transcripts_file, 'w') as f:
184
+ json.dump(transcripts, f, indent=2)
185
+ logger.info(f"Updated transcripts after deletion")
186
+ except ValueError:
187
+ logger.warning(f"Could not find podcast ID for {filename} in transcripts")
188
 
189
+ return {"message": "File deleted successfully"}
 
 
 
 
190
 
191
+ except Exception as e:
192
+ logger.error(f"Error during file deletion process: {str(e)}")
193
+ raise HTTPException(status_code=500, detail=str(e))
 
 
194
 
195
+ except HTTPException as he:
196
+ raise he
197
  except Exception as e:
198
  logger.error(f"Error in delete_audio_file: {str(e)}")
199
  raise HTTPException(status_code=500, detail=str(e))