@@ -59,23 +59,29 @@ public function import(string $csvPath): void
5959 }
6060
6161 // Read header
62- $ header = fgetcsv ($ handle , 0 , ', ' , '" ' , '' );
62+ $ header = fgetcsv ($ handle , 0 , '; ' , '" ' , '' );
6363 if (!$ header || !in_array ('url ' , $ header )) {
6464 $ this ->climate ->error ("CSV must have at least 'url' column " );
6565 fclose ($ handle );
6666 exit (1 );
6767 }
6868
6969 // Get column indexes
70+ $ nameIndex = array_search ('name ' , $ header );
7071 $ urlIndex = array_search ('url ' , $ header );
7172 $ tagsIndex = array_search ('tags ' , $ header );
7273 $ categoryIndex = array_search ('category ' , $ header );
74+
75+ // Also support 'tag' as alternative to 'tags'
76+ if ($ tagsIndex === false ) {
77+ $ tagsIndex = array_search ('tag ' , $ header );
78+ }
7379
7480 $ results = [];
75- $ lineNumber = 1 ;
81+ $ lineNumber = 0 ;
7682
7783 // Process each line
78- while (($ row = fgetcsv ($ handle , 0 , ', ' , '" ' , '' )) !== false ) {
84+ while (($ row = fgetcsv ($ handle , 0 , '; ' , '" ' , '' )) !== false ) {
7985 $ lineNumber ++;
8086
8187 if (empty ($ row [$ urlIndex ])) {
@@ -90,12 +96,13 @@ public function import(string $csvPath): void
9096 }
9197
9298 $ url = trim ($ row [$ urlIndex ]);
99+ $ name = $ nameIndex !== false && !empty ($ row [$ nameIndex ]) ? trim ($ row [$ nameIndex ]) : '' ;
93100 $ tags = $ tagsIndex !== false && !empty ($ row [$ tagsIndex ]) ? trim ($ row [$ tagsIndex ]) : '' ;
94101 $ category = $ categoryIndex !== false && !empty ($ row [$ categoryIndex ]) ? trim ($ row [$ categoryIndex ]) : '' ;
95102
96103 $ this ->climate ->out ("Line {$ lineNumber }: Processing {$ url }" );
97104
98- $ result = $ this ->importFeed ($ url , $ tags , $ category );
105+ $ result = $ this ->importFeed ($ url , $ name , $ tags , $ category );
99106 $ results [] = [
100107 'line ' => $ lineNumber ,
101108 'url ' => $ url ,
@@ -124,7 +131,7 @@ public function import(string $csvPath): void
124131 $ this ->climate ->red ("Errors: {$ errorCount }" );
125132 }
126133
127- private function importFeed (string $ url , string $ tags , string $ category ): array
134+ private function importFeed (string $ url , string $ name , string $ tags , string $ category ): array
128135 {
129136 try {
130137 // 1. Discover feed URL
@@ -158,8 +165,8 @@ private function importFeed(string $url, string $tags, string $category): array
158165 ];
159166 }
160167
161- // 4. Get feed title
162- $ feedTitle = $ this ->getFeedTitle ($ feedUrl , $ feedType );
168+ // 4. Use provided name or get feed title
169+ $ feedTitle = ! empty ( $ name ) ? $ name : $ this ->getFeedTitle ($ feedUrl , $ feedType );
163170
164171 // 5. Insert feed
165172 DB ::insert ('feeds ' , [
@@ -200,6 +207,18 @@ private function importFeed(string $url, string $tags, string $category): array
200207 private function discoverFeedUrl (string $ url ): ?string
201208 {
202209 try {
210+ $ url = trim ($ url );
211+
212+ // Handle Substack URLs
213+ if (stripos ($ url , 'substack.com ' ) !== false ) {
214+ return rtrim ($ url , '/ ' ) . '/feed ' ;
215+ }
216+
217+ // Handle Buttondown URLs
218+ if (stripos ($ url , 'buttondown ' ) !== false ) {
219+ return rtrim ($ url , '/ ' ) . '/rss ' ;
220+ }
221+
203222 // First, try the URL directly
204223 $ feedType = $ this ->feedDetector ->detectType ($ url );
205224 if ($ feedType ) {
@@ -412,7 +431,7 @@ private function generateResultCsv(string $originalCsvPath, array $results): voi
412431 }
413432
414433 // Write header
415- fputcsv ($ handle , ['line ' , 'url ' , 'status ' , 'message ' ], ', ' , '" ' , '' );
434+ fputcsv ($ handle , ['line ' , 'url ' , 'status ' , 'message ' ], '; ' , '" ' , '' );
416435
417436 // Write results
418437 foreach ($ results as $ result ) {
@@ -421,7 +440,7 @@ private function generateResultCsv(string $originalCsvPath, array $results): voi
421440 $ result ['url ' ],
422441 $ result ['status ' ],
423442 $ result ['message ' ]
424- ], ', ' , '" ' , '' );
443+ ], '; ' , '" ' , '' );
425444 }
426445
427446 fclose ($ handle );
0 commit comments