@@ -10,8 +10,10 @@ import fetch from 'isomorphic-fetch';
10
10
// import logger from 'utils/logger';
11
11
// import moment from 'moment';
12
12
import qs from 'qs' ;
13
+ import { logger } from 'topcoder-react-lib' ;
13
14
14
15
const contentful = require ( 'contentful-management' ) ;
16
+ const xml2json = require ( 'xml2json' ) ;
15
17
16
18
/* Holds Contentful CDN URL. */
17
19
const CDN_URL = 'https://cdn.contentful.com/spaces' ;
@@ -191,6 +193,113 @@ export function articleVote(body) {
191
193
. then ( entry => entry . publish ( ) ) ;
192
194
}
193
195
196
+ /**
197
+ * This function fetches TC RSS feed to create draft articles in THRIVE for the new posted blogs.
198
+ * It calls itself by interval to poll for new blogs.
199
+ * Runs on server side only.
200
+ */
201
+ export async function pollArticlesForThrive ( ) {
202
+ // make this function execute only when in production
203
+ if ( process . env . BABEL_ENV !== 'production' ) return ;
204
+ logger . log ( 'polling blog articles for THRIVE -> INIT' ) ;
205
+ // fetch the RSS feed and parse it
206
+ const feedXML = await fetch ( config . URL . THRIVE_POLL_FEED ) ;
207
+ if ( feedXML . ok ) {
208
+ let feed = await feedXML . text ( ) ;
209
+ feed = await Promise . resolve ( xml2json . toJson ( feed , { object : true } ) ) ;
210
+ if ( feed ) {
211
+ // when feed loaded and parsed ok
212
+ // connect to Thrive space
213
+ const client = contentful . createClient ( {
214
+ accessToken : config . SECRET . CONTENTFUL . MANAGEMENT_TOKEN ,
215
+ } ) ;
216
+ client . getSpace ( config . SECRET . CONTENTFUL . EDU . SPACE_ID )
217
+ . then ( space => space . getEnvironment ( 'master' ) )
218
+ // loop all feed items and check if those exists in space
219
+ // if not existing then create
220
+ . then ( env => Promise . all (
221
+ _ . map ( feed . rss . channel . item ,
222
+ blogPost => env . getEntries ( {
223
+ content_type : 'article' ,
224
+ 'fields.title[match]' : blogPost . title ,
225
+ } )
226
+ . then ( ( queryData ) => {
227
+ if ( queryData . total === 0 ) {
228
+ // article not found in Contentful space
229
+ // will create it with payload...
230
+ const article = {
231
+ fields : {
232
+ title : { 'en-US' : blogPost . title } ,
233
+ type : { 'en-US' : 'Article' } ,
234
+ tags : { 'en-US' : blogPost . category } ,
235
+ creationDate : { 'en-US' : new Date ( blogPost . pubDate ) } ,
236
+ content : { 'en-US' : blogPost . description } ,
237
+ externalArticle : { 'en-US' : true } ,
238
+ contentUrl : { 'en-US' : blogPost . link } ,
239
+ } ,
240
+ } ;
241
+ // check if author exists
242
+ // if yes link it if no create it?
243
+ return env . getEntries ( {
244
+ content_type : 'person' ,
245
+ query : blogPost [ 'dc:creator' ] ,
246
+ } )
247
+ . then ( ( author ) => {
248
+ // found an author that matches link it
249
+ if ( author . total ) {
250
+ article . fields . contentAuthor = {
251
+ 'en-US' : [ {
252
+ sys : {
253
+ type : 'Link' , linkType : 'Entry' , id : author . items [ 0 ] . sys . id ,
254
+ } ,
255
+ } ] ,
256
+ } ;
257
+ }
258
+ // try get the page to extract its featured image
259
+ return fetch ( blogPost . link )
260
+ . then ( rsp => rsp . text ( ) )
261
+ . then ( ( HTMLsrc ) => {
262
+ const match = / < i m a g e [ ^ > ] * h r e f = " ( [ ^ " ] + ) " / gm. exec ( HTMLsrc ) ;
263
+ if ( match && match [ 1 ] ) {
264
+ // create the asset in Contentful
265
+ return env . createAsset ( {
266
+ fields : {
267
+ title : { 'en-US' : blogPost . title } ,
268
+ file : {
269
+ 'en-US' : { fileName : blogPost . title , contentType : 'image' , upload : match [ 1 ] } ,
270
+ } ,
271
+ } ,
272
+ } )
273
+ . then ( asset => asset . processForAllLocales ( ) )
274
+ . then ( ( asset ) => {
275
+ article . fields . featuredImage = {
276
+ 'en-US' : {
277
+ sys : {
278
+ type : 'Link' , linkType : 'Asset' , id : asset . sys . id ,
279
+ } ,
280
+ } ,
281
+ } ;
282
+ return env . createEntry ( 'article' , article ) ;
283
+ } ) ;
284
+ }
285
+ // could not find image
286
+ // just create the article without it...
287
+ return env . createEntry ( 'article' , article ) ;
288
+ } ) ;
289
+ } ) ;
290
+ }
291
+ // Article exists in Contentful space
292
+ // do nothing...
293
+ return 1 ;
294
+ } ) ) ,
295
+ ) )
296
+ . then ( ( ) => logger . log ( 'polling blog articles for THRIVE -> DONE' ) ) ;
297
+ }
298
+ }
299
+ // schedule a repeat each TC_EDU_POLL_TIME
300
+ setTimeout ( pollArticlesForThrive , config . TC_EDU_POLL_TIME * 1000 ) . unref ( ) ;
301
+ }
302
+
194
303
// /* Contentful CDN service. */
195
304
// export const cdnService = new ApiService(CDN_URL, CDN_KEY);
196
305
0 commit comments