function RESOLVEHANDLE(handle) { url = "https://api.bsky.app/xrpc/com.atproto.identity.resolveHandle?handle=" + handle; const result = UrlFetchApp.fetch(url).getContentText(); const response = JSON.parse(result); did = response.did; return did; } function GETPOST(did, postid) { url = `https://api.bsky.app/xrpc/com.atproto.repo.getRecord?repo=${did}&collection=app.bsky.feed.post&rkey=${postid}` const result = UrlFetchApp.fetch(url).getContentText(); const response = JSON.parse(result); const content = response.value.text; return content } function postToBluesky() { const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet(); const statusText = sheet.getRange("A2").getValue(); const BSKY_HANDLE = sheet.getRange("B27").getValue(); const BSKY_PASSWORD = sheet.getRange("A27").getValue(); const PDS_URL = sheet.getRange("C27").getValue(); if (!statusText) { SpreadsheetApp.getUi().alert("Cell A2 is empty!"); return; } try { SpreadsheetApp.getUi().alert("Logging in"); const sessionResponse = UrlFetchApp.fetch(`https://${PDS_URL}/xrpc/com.atproto.server.createSession`, { method: "POST", contentType: "application/json", payload: JSON.stringify({ identifier: BSKY_HANDLE, password: BSKY_PASSWORD }), muteHttpExceptions: true }); const sessionText = sessionResponse.getContentText(); if (!sessionText) throw new Error("Empty response from Bluesky during login."); const sessionData = JSON.parse(sessionText); if (sessionResponse.getResponseCode() !== 200) { throw new Error("Login failed: " + (sessionData.message || "Unknown error")); } const token = sessionData.accessJwt; const did = sessionData.did; SpreadsheetApp.getUi().alert("Posting"); const postRecord = { repo: did, collection: "app.bsky.feed.post", record: { text: statusText, createdAt: new Date().toISOString(), $type: "app.bsky.feed.post" } }; const postResponse = UrlFetchApp.fetch(`https://${PDS_URL}/xrpc/com.atproto.repo.createRecord`, { method: "POST", contentType: "application/json", headers: { "Authorization": `Bearer ${token}` }, payload: JSON.stringify(postRecord), muteHttpExceptions: true }); const postText = postResponse.getContentText(); if (postResponse.getResponseCode() === 200) { SpreadsheetApp.getUi().alert("Post successful!"); } else { const errorData = postText ? JSON.parse(postText) : { message: "No response body" }; throw new Error(errorData.message || "Post failed"); } } catch (e) { Logger.log(e.toString()); SpreadsheetApp.getUi().alert("Error: " + e.message); } }