Bluesky client in Google Sheets
at main 84 lines 2.8 kB view raw
1function RESOLVEHANDLE(handle) { 2 url = "https://api.bsky.app/xrpc/com.atproto.identity.resolveHandle?handle=" + handle; 3 const result = UrlFetchApp.fetch(url).getContentText(); 4 const response = JSON.parse(result); 5 did = response.did; 6 return did; 7} 8 9function GETPOST(did, postid) { 10 url = `https://api.bsky.app/xrpc/com.atproto.repo.getRecord?repo=${did}&collection=app.bsky.feed.post&rkey=${postid}` 11 const result = UrlFetchApp.fetch(url).getContentText(); 12 const response = JSON.parse(result); 13 const content = response.value.text; 14 return content 15} 16 17function postToBluesky() { 18 const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet(); 19 const statusText = sheet.getRange("A2").getValue(); 20 21 const BSKY_HANDLE = sheet.getRange("B27").getValue(); 22 const BSKY_PASSWORD = sheet.getRange("A27").getValue(); 23 const PDS_URL = sheet.getRange("C27").getValue(); 24 25 if (!statusText) { 26 SpreadsheetApp.getUi().alert("Cell A2 is empty!"); 27 return; 28 } 29 30 try { 31 SpreadsheetApp.getUi().alert("Logging in"); 32 const sessionResponse = UrlFetchApp.fetch(`https://${PDS_URL}/xrpc/com.atproto.server.createSession`, { 33 method: "POST", 34 contentType: "application/json", 35 payload: JSON.stringify({ 36 identifier: BSKY_HANDLE, 37 password: BSKY_PASSWORD 38 }), 39 muteHttpExceptions: true 40 }); 41 42 const sessionText = sessionResponse.getContentText(); 43 if (!sessionText) throw new Error("Empty response from Bluesky during login."); 44 45 const sessionData = JSON.parse(sessionText); 46 if (sessionResponse.getResponseCode() !== 200) { 47 throw new Error("Login failed: " + (sessionData.message || "Unknown error")); 48 } 49 50 const token = sessionData.accessJwt; 51 const did = sessionData.did; 52 53 SpreadsheetApp.getUi().alert("Posting"); 54 const postRecord = { 55 repo: did, 56 collection: "app.bsky.feed.post", 57 record: { 58 text: statusText, 59 createdAt: new Date().toISOString(), 60 $type: "app.bsky.feed.post" 61 } 62 }; 63 64 const postResponse = UrlFetchApp.fetch(`https://${PDS_URL}/xrpc/com.atproto.repo.createRecord`, { 65 method: "POST", 66 contentType: "application/json", 67 headers: { "Authorization": `Bearer ${token}` }, 68 payload: JSON.stringify(postRecord), 69 muteHttpExceptions: true 70 }); 71 72 const postText = postResponse.getContentText(); 73 if (postResponse.getResponseCode() === 200) { 74 SpreadsheetApp.getUi().alert("Post successful!"); 75 } else { 76 const errorData = postText ? JSON.parse(postText) : { message: "No response body" }; 77 throw new Error(errorData.message || "Post failed"); 78 } 79 80 } catch (e) { 81 Logger.log(e.toString()); 82 SpreadsheetApp.getUi().alert("Error: " + e.message); 83 } 84}