@@ -30,6 +30,102 @@ const client = createClient({
3030 useCdn : false ,
3131} ) ;
3232
33+ async function createGoogleSyndicationTask ( { title, canonicalUrl, tags = [ ] } ) {
34+ const refreshToken = process . env . GOOGLE_WORKSPACE_REFRESH_TOKEN ;
35+ const clientId = process . env . GOOGLE_CLIENT_ID ;
36+ const clientSecret = process . env . GOOGLE_CLIENT_SECRET ;
37+
38+ if ( ! refreshToken || ! clientId || ! clientSecret ) {
39+ console . log ( "Google Workspace credentials not set; skipping Google Task creation." ) ;
40+ return ;
41+ }
42+
43+ try {
44+ const tokenRes = await fetch ( "https://oauth2.googleapis.com/token" , {
45+ method : "POST" ,
46+ headers : { "Content-Type" : "application/x-www-form-urlencoded" } ,
47+ body : new URLSearchParams ( {
48+ client_id : clientId ,
49+ client_secret : clientSecret ,
50+ refresh_token : refreshToken ,
51+ grant_type : "refresh_token" ,
52+ } ) ,
53+ } ) ;
54+ const tokenData = await tokenRes . json ( ) ;
55+ const accessToken = tokenData . access_token ;
56+ if ( ! accessToken ) {
57+ console . warn ( "Could not obtain Google access_token for Task creation." ) ;
58+ return ;
59+ }
60+
61+ const taskTitle = `Cross-post to Hashnode & Medium: ${ title } ` ;
62+ const taskNotes = [
63+ `Canonical URL: ${ canonicalUrl } ` ,
64+ `Tags: ${ tags . join ( ", " ) } ` ,
65+ `` ,
66+ `1. Hashnode (Free UI Editor):` ,
67+ ` - Open: https://hashnode.com/draft` ,
68+ ` - Set Original Article URL (Canonical): ${ canonicalUrl } ` ,
69+ `` ,
70+ `2. Medium (1-Click Import):` ,
71+ ` - Open: https://medium.com/p/import` ,
72+ ` - Paste: ${ canonicalUrl } (automatically sets canonical tag)` ,
73+ `` ,
74+ `3. daily.dev Squad:` ,
75+ ` - Open: https://daily.dev/squads/codingcatdev -> Click "Share a link" -> Paste ${ canonicalUrl } ` ,
76+ ] . join ( "\n" ) ;
77+
78+ // 1. Try Google Tasks API first
79+ const tasksRes = await fetch ( "https://tasks.googleapis.com/tasks/v1/lists/@default/tasks" , {
80+ method : "POST" ,
81+ headers : {
82+ Authorization : `Bearer ${ accessToken } ` ,
83+ "Content-Type" : "application/json" ,
84+ } ,
85+ body : JSON . stringify ( {
86+ title : taskTitle ,
87+ notes : taskNotes ,
88+ due : new Date ( Date . now ( ) + 24 * 60 * 60 * 1000 ) . toISOString ( ) ,
89+ } ) ,
90+ } ) ;
91+
92+ if ( tasksRes . ok ) {
93+ const createdTask = await tasksRes . json ( ) ;
94+ console . log ( `✓ Created Google Task: "${ taskTitle } " (ID: ${ createdTask . id } )` ) ;
95+ return ;
96+ }
97+
98+ // 2. Fallback to Google Calendar To-Do Event on alex.patterson@gmail.com if Tasks scope is not yet authorized
99+ const startDate = new Date ( Date . now ( ) + 60 * 60 * 1000 ) ;
100+ const endDate = new Date ( startDate . getTime ( ) + 30 * 60 * 1000 ) ;
101+ const calRes = await fetch (
102+ "https://www.googleapis.com/calendar/v3/calendars/alex.patterson%40gmail.com/events" ,
103+ {
104+ method : "POST" ,
105+ headers : {
106+ Authorization : `Bearer ${ accessToken } ` ,
107+ "Content-Type" : "application/json" ,
108+ } ,
109+ body : JSON . stringify ( {
110+ summary : `📋 [Task] ${ taskTitle } ` ,
111+ description : taskNotes ,
112+ start : { dateTime : startDate . toISOString ( ) } ,
113+ end : { dateTime : endDate . toISOString ( ) } ,
114+ } ) ,
115+ }
116+ ) ;
117+
118+ if ( calRes . ok ) {
119+ const createdEvent = await calRes . json ( ) ;
120+ console . log ( `✓ Created Google Calendar Task Reminder: "${ taskTitle } " (${ createdEvent . htmlLink } )` ) ;
121+ } else {
122+ console . warn ( "Could not create Google Calendar fallback reminder:" , await calRes . text ( ) ) ;
123+ }
124+ } catch ( err ) {
125+ console . warn ( "Error creating Google syndication task:" , err ) ;
126+ }
127+ }
128+
33129async function run ( ) {
34130 const doc = await client . getDocument ( docId ) ;
35131 if ( ! doc ) {
@@ -303,6 +399,11 @@ async function run() {
303399 console . log ( `✓ Updated Sanity doc ${ doc . _id } hashnode slug` ) ;
304400 } else {
305401 console . error ( "✗ Hashnode publication failed:" , publishData ?. errors ) ;
402+ await createGoogleSyndicationTask ( {
403+ title : doc . title || "Untitled" ,
404+ canonicalUrl,
405+ tags : hashnodeTags . map ( ( t ) => t . slug ) ,
406+ } ) ;
306407 }
307408 } catch ( err ) {
308409 console . error ( "✗ Hashnode request error:" , err ) ;
0 commit comments