@@ -4,6 +4,10 @@ const { initializeApp } = require("firebase-admin/app");
4
4
const { google } = require ( 'googleapis' ) ;
5
5
const sheets = google . sheets ( 'v4' ) ;
6
6
7
+ const { format, isValid } = require ( 'date-fns' ) ;
8
+
9
+ const feedUtils = require ( './helper.js' ) ;
10
+
7
11
setGlobalOptions ( { region : "us-central1" } ) ;
8
12
const api_key_2nd_gen = process . env . SHEETS_API_KEY ;
9
13
initializeApp ( ) ;
@@ -95,68 +99,95 @@ function generateFeedContent(values, mode) {
95
99
return { xmlItems, feedDescription } ;
96
100
}
97
101
102
+
98
103
function generateFeedAutoMode ( values ) {
99
- let xmlItemsAll = "" ;
100
104
if ( ! values || values . length === 0 ) {
105
+ console . error ( "No values provided to generateFeedAutoMode." ) ;
101
106
return "" ;
102
107
}
103
108
109
+ const parsedItems = [ ] ;
104
110
for ( const row of values ) {
105
111
if ( row && row . length > 0 ) {
106
- let currentRowData = [ ...row ] ;
107
- let title = String ( currentRowData . shift ( ) || '' ) ;
108
112
109
- if ( ! title ) continue ;
113
+ let title = '' ;
114
+ let titleIndex = - 1 ;
115
+ for ( let i = 0 ; i < row . length ; i ++ ) {
116
+ const cellValue = String ( row [ i ] || '' ) . trim ( ) ;
117
+ if ( cellValue !== '' ) {
118
+ title = cellValue ; // Found the title
119
+ titleIndex = i ;
120
+ break ; // Stop searching
121
+ }
122
+ }
110
123
111
- let link = undefined ;
112
- let dateString = undefined ;
124
+ if ( titleIndex === - 1 ) {
125
+ console . warn ( 'Skipping row because no non-empty cell found:' , row ) ;
126
+ continue ;
127
+ }
113
128
114
- const linkIndex = currentRowData . findIndex ( cell => typeof cell === 'string' && cell . startsWith ( 'http' ) ) ;
115
- if ( linkIndex !== - 1 ) {
116
- link = currentRowData . splice ( linkIndex , 1 ) [ 0 ] ;
117
- }
129
+ const remainingRowData = row . filter ( ( _ , index ) => index !== titleIndex ) ;
118
130
119
- const dateIndex = currentRowData . findIndex ( cell => {
120
- if ( typeof cell !== 'string' ) return false ;
121
- try {
122
- const potentialDate = new Date ( cell ) ;
123
- return ! isNaN ( potentialDate . getTime ( ) ) && potentialDate . toUTCString ( ) . slice ( 0 , 25 ) === cell . slice ( 0 , 25 ) ;
124
- } catch ( e ) {
125
- return false ;
126
- }
127
- } ) ;
128
- if ( dateIndex !== - 1 ) {
129
- dateString = currentRowData . splice ( dateIndex , 1 ) [ 0 ] ;
130
- }
131
+ let link = undefined ;
132
+ let dateObject = null ;
133
+ let descriptionContent = '' ;
131
134
132
- const descriptionContent = currentRowData . map ( cell => String ( cell || '' ) ) . join ( ' ' ) ;
135
+ const remainingCells = [ ] ;
136
+ for ( const cell of remainingRowData ) {
137
+ const cellString = String ( cell || '' ) ;
133
138
139
+ if ( ! link && cellString . startsWith ( 'http' ) ) {
140
+ link = cellString ;
141
+ continue ;
142
+ }
134
143
135
- let itemDate = new Date ( ) ;
136
- if ( dateString ) {
137
- try {
138
- const parsedDate = new Date ( dateString ) ;
139
- if ( ! isNaN ( parsedDate . getTime ( ) ) ) {
140
- itemDate = parsedDate ;
141
- }
142
- } catch ( e ) { /* Keep default date if parsing fails */ }
144
+ if ( ! dateObject ) {
145
+ const parsed = feedUtils . parseDateString ( cellString ) ;
146
+ if ( parsed instanceof Date && isValid ( parsed ) ) {
147
+ dateObject = parsed ;
148
+ continue ;
149
+ }
150
+ }
151
+ remainingCells . push ( cellString ) ;
143
152
}
144
- const pubDateString = itemDate . toUTCString ( ) ;
153
+ descriptionContent = remainingCells . join ( ' ' ) ;
145
154
146
- const xmlItem = `<item>
147
- <title><![CDATA[${ title } ]]></title>
148
- <description><![CDATA[${ descriptionContent } ]]></description>
149
- ${ link !== undefined ? `<link><![CDATA[${ link } ]]></link>` : '' }
150
- ${ link !== undefined ? `<guid><![CDATA[${ link } ]]></guid>` : '' }
155
+ parsedItems . push ( {
156
+ title,
157
+ link,
158
+ dateObject, // Can be null if no valid date was found
159
+ descriptionContent
160
+ } ) ;
161
+ }
162
+ }
163
+
164
+ feedUtils . sortFeedItems ( parsedItems ) ;
165
+
166
+ let xmlItemsAll = "" ;
167
+ for ( const item of parsedItems ) {
168
+ const itemDate = ( item . dateObject instanceof Date && isValid ( item . dateObject ) )
169
+ ? item . dateObject
170
+ : new Date ( ) ; // Fallback to now if dateObject is null or invalid
171
+ const pubDateString = format ( itemDate , "EEE, dd MMM yyyy HH:mm:ss 'GMT'" , { timeZone : 'GMT' } ) ;
172
+
173
+ const titleCDATA = `<![CDATA[${ item . title } ]]>` ;
174
+ const descriptionCDATA = `<![CDATA[${ item . descriptionContent } ]]>` ;
175
+ const linkElement = item . link ? `<link><![CDATA[${ item . link } ]]></link>` : '' ;
176
+ const guidElement = item . link ? `<guid><![CDATA[${ item . link } ]]></guid>` : '' ;
177
+
178
+ const xmlItem = ` <item>
179
+ <title>${ titleCDATA } </title>
180
+ <description>${ descriptionCDATA } </description>
181
+ ${ linkElement }
182
+ ${ guidElement }
151
183
<pubDate>${ pubDateString } </pubDate>
152
184
</item>` ;
153
-
154
- xmlItemsAll += xmlItem ;
155
- }
185
+ xmlItemsAll += xmlItem ;
156
186
}
157
187
return xmlItemsAll ;
158
188
}
159
189
190
+
160
191
function generateFeedManualMode ( values ) {
161
192
let xmlItemsAll = [ ]
162
193
for ( const key in values ) {
0 commit comments