Created
March 26, 2023 18:53
-
-
Save royharmon4/fe93ed2b3a4d732d6662aa501b90c11d to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // Replace these with your own LinkedIn App's Client ID and Client Secret | |
| const CLIENT_ID = '{INSERT CLIENT ID}'; | |
| const CLIENT_SECRET = '{INSERT CLIENT SECRET}'; | |
| // Replace this with your Google Sheet ID | |
| const SPREADSHEET_ID = '{INSERT SPREADSHEET ID}'; | |
| // OAuth2 library | |
| const LinkedInOAuth2 = OAuth2; | |
| function getLinkedInService() { | |
| return LinkedInOAuth2.createService('LinkedIn') | |
| .setAuthorizationBaseUrl('https://www.linkedin.com/oauth/v2/authorization') | |
| .setTokenUrl('https://www.linkedin.com/oauth/v2/accessToken') | |
| .setClientId(CLIENT_ID) | |
| .setClientSecret(CLIENT_SECRET) | |
| .setCallbackFunction('authCallback') | |
| .setPropertyStore(PropertiesService.getUserProperties()) | |
| .setScope('r_liteprofile w_member_social'); | |
| } | |
| function showSidebar() { | |
| const service = getLinkedInService(); | |
| if (!service.hasAccess()) { | |
| const authorizationUrl = service.getAuthorizationUrl(); | |
| const template = HtmlService.createTemplate(` | |
| <a href="<?= authorizationUrl ?>" target="_blank">Authorize</a> | |
| <br> | |
| <button onclick="window.top.close();">Close</button> | |
| <script> | |
| setTimeout(() => { | |
| window.top.close(); | |
| }, 10000); | |
| </script> | |
| `); | |
| template.authorizationUrl = authorizationUrl; | |
| const page = template.evaluate(); | |
| SpreadsheetApp.getUi().showSidebar(page); | |
| } | |
| } | |
| function authCallback(request) { | |
| const service = getLinkedInService(); | |
| const authorized = service.handleCallback(request); | |
| if (authorized) { | |
| return HtmlService.createHtmlOutput('Success! You can close this tab.'); | |
| } else { | |
| return HtmlService.createHtmlOutput('Failed to authenticate.'); | |
| } | |
| } | |
| function resetAuth() { | |
| getLinkedInService().reset(); | |
| } | |
| function schedulePosts() { | |
| const service = getLinkedInService(); | |
| if (service.hasAccess()) { | |
| const sheet = SpreadsheetApp.openById(SPREADSHEET_ID).getActiveSheet(); | |
| const data = sheet.getDataRange().getValues(); | |
| const header = data.shift(); | |
| const now = new Date(); | |
| data.forEach((row, index) => { | |
| const rowData = row.reduce((obj, val, i) => { | |
| obj[header[i]] = val; | |
| return obj; | |
| }, {}); | |
| const scheduledTime = rowData['Date and Time']; | |
| if (scheduledTime instanceof Date && scheduledTime > now) { | |
| const remainingMs = scheduledTime.getTime() - now.getTime(); | |
| ScriptApp.newTrigger('postToLinkedIn') | |
| .timeBased() | |
| .after(remainingMs) | |
| .create(); | |
| } | |
| }); | |
| } else { | |
| showSidebar(); | |
| } | |
| } | |
| function postToLinkedIn() { | |
| const service = getLinkedInService(); | |
| if (service.hasAccess()) { | |
| const sheet = SpreadsheetApp.openById(SPREADSHEET_ID).getActiveSheet(); | |
| const data = sheet.getDataRange().getValues(); | |
| const header = data.shift(); | |
| const now = new Date(); | |
| data.forEach((row, index) => { | |
| const rowData = row.reduce((obj, val, i) => { | |
| obj[header[i]] = val; | |
| return obj; | |
| }, {}); | |
| const scheduledTime = rowData['Date and Time']; | |
| if (scheduledTime instanceof Date && Math.abs(scheduledTime - now) < 60000) { // Check if the post is scheduled within 1 minute from now | |
| const post = { | |
| author: "urn:li:person:{INSERT LINKEDIN ID}", | |
| lifecycleState: 'PUBLISHED', | |
| specificContent: { | |
| 'com.linkedin.ugc.ShareContent': { | |
| shareCommentary: { | |
| text: rowData['Post Content'] | |
| }, | |
| shareMediaCategory: 'NONE' | |
| } | |
| }, | |
| visibility: { | |
| 'com.linkedin.ugc.MemberNetworkVisibility': 'PUBLIC' | |
| } | |
| }; | |
| const options = { | |
| method: 'POST', | |
| contentType: 'application/json', | |
| payload: JSON.stringify(post), | |
| headers: { | |
| Authorization: `Bearer ${service.getAccessToken()}`, | |
| 'X-Restli-Protocol-Version': '2.0.0' | |
| } | |
| }; | |
| const response = UrlFetchApp.fetch('https://api.linkedin.com/v2/ugcPosts', options); | |
| const result = JSON.parse(response.getContentText()); | |
| if (response.getResponseCode() === 201) { | |
| sheet.getRange(index + 2, header.indexOf('Status') + 1).setValue('Posted'); | |
| } else { | |
| sheet.getRange(index + 2, header.indexOf('Status') + 1).setValue('Error'); | |
| } | |
| } | |
| }); | |
| } else { | |
| showSidebar(); | |
| } | |
| } | |
| function onOpen() { | |
| const ui = SpreadsheetApp.getUi(); | |
| ui.createMenu('LinkedIn') | |
| .addItem('Schedule Posts', 'schedulePosts') | |
| .addItem('Reset Authentication', 'resetAuth') | |
| .addToUi(); | |
| } | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment