@@ -17,207 +17,226 @@ const optionDefinitions = [
1717const fs = require ( 'fs' ) ;
1818const axios = require ( 'axios' ) ;
1919const commandLineArgs = require ( 'command-line-args' ) ;
20+ const process = require ( 'process' ) ;
2021require ( 'dotenv' ) . config ( { path : './.env.local' } ) ;
2122
2223const options = commandLineArgs ( optionDefinitions ) ;
2324
24- if ( options . help ) {
25+ if ( ' help' in options ) {
2526 console . log ( `
2627 Usage: node scripts/issueEmailGenerator.js [--issueNumber=<issueNumber>]
2728 ` ) ;
28- return ;
29+ process . exitCode = 1 ;
2930}
3031
31- if ( typeof options . issueNumber !== 'number' ) {
32+ if ( 'issueNumber' in options && typeof options . issueNumber !== 'number' ) {
3233 console . log ( 'Please provide a valid issue number' ) ;
33- return ;
34+ process . exitCode = - 1 ;
3435}
3536
36- ( async ( ) => {
37- const currentIssue = await axios
38- . get ( `${ process . env . CMS_API } issues/${ options . issueNumber } ` )
39- . then ( response => response . data ) ;
40-
41- const PROFILE_TYPES = {
42- website : 'Website' ,
43- twitter : 'Twitter' ,
44- github : 'GitHub' ,
45- youtube : 'YouTube' ,
46- linkedin : 'LinkedIn' ,
47- instagram : 'Instagram' ,
48- } ;
49-
50- const PROFILE_KEYS = [ 'webiste' , 'twitter' , 'github' , 'youtube' , 'linkedin' , 'instagram' ] ;
51-
52- const convertDate = date => {
53- const options = {
54- year : 'numeric' ,
55- month : 'long' ,
56- day : 'numeric' ,
37+ if ( 'issueNumber' in options && typeof options . issueNumber === 'number' ) {
38+ ( async ( ) => {
39+ const currentIssue = await axios . default
40+ . get ( `${ process . env . CMS_API } issues/${ options . issueNumber } ` )
41+ . then ( response => response . data )
42+ . catch ( err => console . error ( err ) ) ;
43+
44+ const PROFILE_TYPES = {
45+ website : 'Website' ,
46+ twitter : 'Twitter' ,
47+ github : 'GitHub' ,
48+ youtube : 'YouTube' ,
49+ linkedin : 'LinkedIn' ,
50+ instagram : 'Instagram' ,
5751 } ;
58- return new Date ( date ) . toLocaleDateString ( 'en-US' , options ) ;
59- } ;
60-
61- function getOGImage ( title , issueNumber , date ) {
62- const parsedDate = convertDate ( date ) ;
63- return `${ process . env . NEXT_PUBLIC_OG_IMAGE_BASE } ${ encodeURIComponent (
64- title
65- ) } .png?issue_number=${ issueNumber } &date=${ encodeURIComponent ( parsedDate ) } `;
66- }
67-
68- function isValidHttpUrl ( str ) {
69- let url ;
7052
71- try {
72- url = new URL ( str ) ;
73- } catch ( _ ) {
74- return false ;
75- }
53+ const PROFILE_KEYS = [ 'webiste' , 'twitter' , 'github' , 'youtube' , 'linkedin' , 'instagram' ] ;
7654
77- return url . protocol === 'http:' || url . protocol === 'https:' ;
78- }
55+ const convertDate = date => {
56+ const options = {
57+ year : 'numeric' ,
58+ month : 'long' ,
59+ day : 'numeric' ,
60+ } ;
61+ return new Date ( date ) . toLocaleDateString ( 'en-US' , options ) ;
62+ } ;
7963
80- function getAssetURL ( issueNumber , assetURL ) {
81- if ( isValidHttpUrl ( assetURL ) ) {
82- return assetURL ;
64+ function getOGImage ( title , issueNumber , date ) {
65+ const parsedDate = convertDate ( date ) ;
66+ return `${ process . env . NEXT_PUBLIC_OG_IMAGE_BASE } ${ encodeURIComponent (
67+ title
68+ ) } .png?issue_number=${ issueNumber } &date=${ encodeURIComponent ( parsedDate ) } `;
8369 }
84- return `${ process . env . NEXT_PUBLIC_ASSETS_URL } issue-${ issueNumber } /${ assetURL } ` ;
85- }
86-
87- const ogImgURL = getOGImage ( currentIssue . title , currentIssue . id , currentIssue . dateOfPublishing ) ;
88-
89- const emailTemplate = `
90- 
9170
92- <center>[Read issue on web](https://scriptified.dev/issues/${ currentIssue . id } )</center>
71+ function isValidHttpUrl ( str ) {
72+ let url ;
9373
94- ${ currentIssue . description }
74+ try {
75+ url = new URL ( str ) ;
76+ } catch ( _ ) {
77+ return false ;
78+ }
9579
96- # Tip of the day
97- ${ currentIssue . tipOfTheWeek . description }
98-
99- ${
100- currentIssue . tipOfTheWeek . codeSnippet &&
101- `
102- \`\`\`${ currentIssue . tipOfTheWeek . codeSnippet . language }
103- ${ currentIssue . tipOfTheWeek . codeSnippet . code }
104- \`\`\`
105- `
106- }
107- ___
80+ return url . protocol === 'http:' || url . protocol === 'https:' ;
81+ }
10882
109- # Articles
83+ function getAssetURL ( issueNumber , assetURL ) {
84+ if ( isValidHttpUrl ( assetURL ) ) {
85+ return assetURL ;
86+ }
87+ return `${ process . env . NEXT_PUBLIC_ASSETS_URL } issue-${ issueNumber } /${ assetURL } ` ;
88+ }
11089
111- ${ currentIssue . articles
112- . map (
113- article =>
114- `[**${ article . title } **](${ article . url } )
115-
116- ${ article . description }
90+ function getAuthors ( authors ) {
91+ if ( authors ?. length ) {
92+ const authorsWithWebsite = authors . map ( author => {
93+ return `[${ author . Name } ](${ author . Website } )` ;
94+ } ) ;
11795
118- *by ${ article . authors . map ( author => author . Name ) . join ( ', ' ) } *
119- `
120- )
121- . join ( '\n' ) }
96+ return `*by ${ authorsWithWebsite . join ( ', ' ) } *` ;
97+ } else {
98+ return '' ;
99+ }
100+ }
122101
123- ___
102+ const ogImgURL = getOGImage ( currentIssue . title , currentIssue . id , currentIssue . dateOfPublishing ) ;
124103
125- ${
126- currentIssue . devOfTheWeek
127- ? `# Dev of the Week
128-
129- <img alt="${ currentIssue . devOfTheWeek . name } " src="${ getAssetURL (
130- currentIssue . id ,
131- currentIssue . devOfTheWeek . profileImg
132- ) } " style="width:200px;"/>
104+ const emailTemplate = `
105+ 
133106
134- ## ${ currentIssue . devOfTheWeek . name }
135- ${ currentIssue . devOfTheWeek . bio }
107+ <center>[Read issue on web](https://scriptified.dev/issues/${ currentIssue . id } )</center>
136108
137- ${ Object . keys ( currentIssue . devOfTheWeek )
138- . filter ( key => PROFILE_KEYS . includes ( key ) && currentIssue . devOfTheWeek [ key ] !== null )
139- . map ( profile => `[${ PROFILE_TYPES [ profile ] } ](${ currentIssue . devOfTheWeek [ profile ] } )` )
140- . join ( ' | ' ) }
141-
142- ___`
143- : ''
144- }
145-
146- # Tools
147-
148- ${ currentIssue . tools
149- . map (
150- tool =>
151- `[**${ tool . name } **](${ tool . url } )
109+ ${ currentIssue . description }
110+
111+ # Tip of the day
112+
113+ ${ currentIssue . tipOfTheWeek . description }
114+
115+ ${
116+ currentIssue . tipOfTheWeek . codeSnippet &&
117+ `
118+ \`\`\`${ currentIssue . tipOfTheWeek . codeSnippet . language }
119+ ${ currentIssue . tipOfTheWeek . codeSnippet . code }
120+ \`\`\`
121+ `
122+ }
123+
124+ ${ getAuthors ( currentIssue . tipOfTheWeek ?. authors ) }
125+ ___
126+
127+ # Articles
128+
129+ ${ currentIssue . articles
130+ . map (
131+ article =>
132+ `[**${ article . title } **](${ article . url } )
133+
134+ ${ article . description }
135+
136+ ${ getAuthors ( article ?. authors ) }
137+ `
138+ )
139+ . join ( '\n' ) }
140+
141+ ___
142+
143+ ${
144+ currentIssue . devOfTheWeek
145+ ? `# Dev of the Week
146+
147+ <img alt="${ currentIssue . devOfTheWeek . name } " src="${ getAssetURL (
148+ currentIssue . id ,
149+ currentIssue . devOfTheWeek . profileImg
150+ ) } " style="width:200px;"/>
152151
153- ${ tool . description }
154-
155- *by ${ tool . authors . map ( author => author . Name ) . join ( ', ' ) } *
156- `
157- )
158- . join ( '\n' ) }
159-
160- ___
161-
162- # Tech Talks
163-
164- [**${ currentIssue . talks [ 0 ] . title } **](${ currentIssue . talks [ 0 ] . url } )
165-
166- ${ currentIssue . talks [ 0 ] . url }
167-
168- ${ currentIssue . talks [ 0 ] . description }
169-
170- ___
171-
172- # Quiz
173-
174- ### ${ currentIssue . quiz . question }
175-
176- \`\`\`${ currentIssue . quiz . CodeSnippet . language }
177- ${ currentIssue . quiz . CodeSnippet . code }
178- \`\`\`
179-
180- ${ currentIssue . quiz . Option . map (
181- option => `<a href="https://scriptified.dev/issues/${ currentIssue . id } ?section=quiz&option=${ option . option_id } " style="text-decoration:none;">
182- <div style="margin: 12px 0px; border: 1px solid gray; padding: 16px; background: #F2F3F5;">
183- ${ option . text }
184- </div>
185- </a>
186- `
187- ) . join ( '\n' ) }
188-
189-
190- ___
191-
192- # This week in GIF
193-
194-  } )
195-
196- <center>${ currentIssue . gif . caption } </center>
197-
198- ---
199-
200- Liked this issue? [Share on Twitter](https://twitter.com/intent/tweet?text=${ encodeURIComponent ( `Have a look at issue #${ currentIssue . id } of Scriptified.
201-
202- Subscribe to @scriptified_dev for more.` ) } &url=${ encodeURIComponent (
203- `https://scriptified.dev/issues/${ currentIssue . id } `
204- ) } ) or [read previous issues](https://scriptified.dev/issues).
205- ` ;
152+ ## ${ currentIssue . devOfTheWeek . name }
153+ ${ currentIssue . devOfTheWeek . bio }
154+
155+ ${ Object . keys ( currentIssue . devOfTheWeek )
156+ . filter ( key => PROFILE_KEYS . includes ( key ) && currentIssue . devOfTheWeek [ key ] !== null )
157+ . map ( profile => `[${ PROFILE_TYPES [ profile ] } ](${ currentIssue . devOfTheWeek [ profile ] } )` )
158+ . join ( ' | ' ) }
159+
160+ ___`
161+ : ''
162+ }
163+
164+ # Tools
165+
166+ ${ currentIssue . tools
167+ . map (
168+ tool =>
169+ `[**${ tool . name } **](${ tool . url } )
170+
171+ ${ tool . description }
172+
173+ ${ getAuthors ( tool ?. authors ) }
174+ `
175+ )
176+ . join ( '\n' ) }
177+
178+ ___
179+
180+ # Tech Talks
181+
182+ [**${ currentIssue . talks [ 0 ] . title } **](${ currentIssue . talks [ 0 ] . url } )
183+
184+ ${ currentIssue . talks [ 0 ] . url }
185+
186+ ${ currentIssue . talks [ 0 ] . description }
187+
188+ ${ getAuthors ( currentIssue . talks ?. [ 0 ] ?. authors ) }
189+
190+ ___
191+
192+ # Quiz
193+
194+ ### ${ currentIssue . quiz . question }
195+
196+ \`\`\`${ currentIssue . quiz . CodeSnippet . language }
197+ ${ currentIssue . quiz . CodeSnippet . code }
198+ \`\`\`
199+
200+ ${ currentIssue . quiz . Option . map (
201+ option => `<a href="https://scriptified.dev/issues/${ currentIssue . id } ?section=quiz&option=${ option . option_id } " style="text-decoration:none;">
202+ <div style="margin: 12px 0px; border: 1px solid gray; padding: 16px; background: #F2F3F5;">
203+ ${ option . text }
204+ </div>
205+ </a>
206+ `
207+ ) . join ( '\n' ) }
208+
209+
210+ ___
211+
212+ # This week in GIF
213+
214+ [${ currentIssue . gif . caption } ](${ process . env . SITE_URL } issues/${ options . issueNumber } ?section=gif)
215+
216+ ---
217+
218+ Liked this issue? [Share on Twitter](https://twitter.com/intent/tweet?text=${ encodeURIComponent ( `Have a look at issue #${ currentIssue . id } of Scriptified.
219+
220+ Subscribe to @scriptified_dev for more.` ) } &url=${ encodeURIComponent (
221+ `https://scriptified.dev/issues/${ currentIssue . id } `
222+ ) } ) or [read previous issues](https://scriptified.dev/issues).
223+ ` ;
206224
207- const archiveDirectory = './archives' ;
208- const issueFile = `${ archiveDirectory } /issue${ currentIssue . id } .md` ;
225+ const archiveDirectory = './archives' ;
226+ const issueFile = `${ archiveDirectory } /issue${ currentIssue . id } .md` ;
209227
210- // create archives folder if iot doesn't exist
211- if ( ! fs . existsSync ( archiveDirectory ) ) {
212- fs . mkdirSync ( archiveDirectory ) ;
213- }
228+ // create archives folder if iot doesn't exist
229+ if ( ! fs . existsSync ( archiveDirectory ) ) {
230+ fs . mkdirSync ( archiveDirectory ) ;
231+ }
214232
215- // const issueFile = `./issue${currentIssue.id}.md`;
233+ // const issueFile = `./issue${currentIssue.id}.md`;
216234
217- // create a issue-{id}.md file in archives
218- fs . closeSync ( fs . openSync ( issueFile , 'a' ) ) ;
235+ // create a issue-{id}.md file in archives
236+ fs . closeSync ( fs . openSync ( issueFile , 'a' ) ) ;
219237
220- // write email template to issue-{id}.md file
221- fs . writeFileSync ( issueFile , emailTemplate ) ;
222- console . log ( `Created the template at - ${ issueFile } ` ) ;
223- } ) ( ) ;
238+ // write email template to issue-{id}.md file
239+ fs . writeFileSync ( issueFile , emailTemplate ) ;
240+ console . log ( `Created the template at - ${ issueFile } ` ) ;
241+ } ) ( ) ;
242+ }
0 commit comments