11const got = require ( 'got' ) ;
22const fuzz = require ( 'fuzzball' ) ;
3+ const Parser = require ( 'rss-parser' ) ;
4+ const { fail, success } = require ( '../lib/healthchecks' ) ;
35const { logger } = require ( '../middleware/logger' ) ;
46
57const YOUTUBE_PREFIX = 'https://youtu.be' ;
6- const API = process . env . SPACEX_API ;
78const CHANNEL_ID = 'UCtI0Hodo5o5dUb67FeUjDeA' ;
89const {
910 SPACEX_KEY ,
10- YOUTUBE_KEY ,
1111 WEBCAST_HEALTHCHECK ,
12+ SPACEX_API : API ,
1213} = process . env ;
1314
1415/**
@@ -17,91 +18,85 @@ const {
1718 */
1819module . exports = async ( ) => {
1920 try {
20- // Check if any upcoming streams on youtube
21- const url = `https://www.googleapis.com/youtube/v3/search?part=snippet&channelId=${ CHANNEL_ID } &eventType=upcoming&maxResults=1&type=video&key=${ YOUTUBE_KEY } ` ;
22- const upcomingStreams = await got ( url , {
21+ let updated = false ;
22+ let match = false ;
23+ const parser = new Parser ( ) ;
24+ const url = `https://www.youtube.com/feeds/videos.xml?channel_id=${ CHANNEL_ID } ` ;
25+ const rssResult = await got ( url , {
26+ resolveBodyOnly : true ,
27+ } ) ;
28+ const result = await parser . parseString ( rssResult ) ;
29+ const latest = result . items [ 0 ] ;
30+ const rssTitle = latest . title ;
31+ const rssYoutubeId = latest . link . split ( 'v=' ) [ 1 ] ;
32+
33+ const launches = await got . post ( `${ API } /launches/query` , {
34+ json : {
35+ query : {
36+ upcoming : true ,
37+ } ,
38+ options : {
39+ sort : {
40+ flight_number : 'asc' ,
41+ } ,
42+ limit : 1 ,
43+ } ,
44+ } ,
2345 resolveBodyOnly : true ,
2446 responseType : 'json' ,
2547 } ) ;
48+ const launchId = launches . docs [ 0 ] . id ;
49+ const missionName = launches . docs [ 0 ] . name ;
2650
27- if ( upcomingStreams ?. items ?. length === 1 ) {
28- const launches = await got . post ( `${ API } /launches/query` , {
51+ const ratio = fuzz . ratio ( rssTitle , missionName ) ;
52+ if ( ratio >= 50 ) {
53+ match = true ;
54+ const pastLaunches = await got . post ( `${ API } /launches/query` , {
2955 json : {
3056 query : {
31- upcoming : true ,
57+ upcoming : false ,
3258 } ,
3359 options : {
3460 sort : {
35- flight_number : 'asc ' ,
61+ flight_number : 'desc ' ,
3662 } ,
3763 limit : 1 ,
3864 } ,
3965 } ,
4066 resolveBodyOnly : true ,
4167 responseType : 'json' ,
4268 } ) ;
43- const launchId = launches . docs [ 0 ] . id ;
44- const missionName = launches . docs [ 0 ] . name ;
45- const youtubeTitle = upcomingStreams . items [ 0 ] . snippet . title ;
46- const youtubeId = upcomingStreams . items [ 0 ] . id . videoId ;
47-
48- // Fuzzy check video title to make sure it's at least related to the launch
49- const ratio = fuzz . ratio ( youtubeTitle , missionName ) ;
50- if ( ratio >= 50 ) {
51- const pastLaunches = await got . post ( `${ API } /launches/query` , {
69+ const pastYoutubeId = pastLaunches . docs [ 0 ] . links . youtube_id ;
70+ if ( rssYoutubeId !== pastYoutubeId ) {
71+ await got . patch ( `${ API } /launches/${ launchId } ` , {
5272 json : {
53- query : {
54- upcoming : false ,
55- } ,
56- options : {
57- sort : {
58- flight_number : 'desc' ,
59- } ,
60- limit : 1 ,
61- } ,
73+ 'links.webcast' : `${ YOUTUBE_PREFIX } /${ rssYoutubeId } ` ,
74+ 'links.youtube_id' : rssYoutubeId ,
75+ } ,
76+ headers : {
77+ 'spacex-key' : SPACEX_KEY ,
6278 } ,
63- resolveBodyOnly : true ,
64- responseType : 'json' ,
65- } ) ;
66- const pastYoutubeId = pastLaunches . docs [ 0 ] . links . youtube_id ;
67- if ( youtubeId !== pastYoutubeId ) {
68- await got . patch ( `${ API } /launches/${ launchId } ` , {
69- json : {
70- 'links.webcast' : `${ YOUTUBE_PREFIX } /${ youtubeId } ` ,
71- 'links.youtube_id' : youtubeId ,
72- } ,
73- headers : {
74- 'spacex-key' : SPACEX_KEY ,
75- } ,
76- } ) ;
77- logger . info ( {
78- rawMission : youtubeTitle ,
79- apiMission : missionName ,
80- url : `${ YOUTUBE_PREFIX } /${ youtubeId } ` ,
81- matchRatio : ratio ,
82- match : true ,
83- } ) ;
84- }
85- logger . info ( 'Past youtube id matches, skipping...' ) ;
86- } else {
87- logger . info ( {
88- rawMission : youtubeTitle ,
89- apiMission : missionName ,
90- url : `${ YOUTUBE_PREFIX } /${ youtubeId } ` ,
91- matchRatio : ratio ,
92- match : false ,
9379 } ) ;
80+ updated = true ;
9481 }
95- } else {
96- logger . info ( {
97- match : false ,
98- } ) ;
99- }
100-
101- if ( WEBCAST_HEALTHCHECK ) {
102- await got ( WEBCAST_HEALTHCHECK ) ;
10382 }
83+ const log = {
84+ name : 'webcast' ,
85+ ratio,
86+ match,
87+ updated,
88+ youtubeTitle : rssTitle ,
89+ youtubeId : rssYoutubeId ,
90+ } ;
91+ await success ( WEBCAST_HEALTHCHECK , log ) ;
92+ logger . info ( log ) ;
10493 } catch ( error ) {
105- console . log ( `Webcast Error: ${ error . message } ` ) ;
94+ const formatted = {
95+ name : 'webcast' ,
96+ error : error . message ,
97+ stack : error . stack ,
98+ } ;
99+ await fail ( WEBCAST_HEALTHCHECK , formatted ) ;
100+ logger . error ( formatted ) ;
106101 }
107102} ;
0 commit comments