diff --git a/WordpressSync/index.js b/WordpressSync/index.js index 61f48ff..23fdd58 100644 --- a/WordpressSync/index.js +++ b/WordpressSync/index.js @@ -5,11 +5,7 @@ const { GitHubCredentials, SourceEndpointConfigData } = require("@cagov/wordpress-to-github/common"); -const { - slackBotReportError, - slackBotChatPost, - slackBotReplyPost -} = require("../common/slackBot"); +const SlackBot = require("@cagov/slack-connector"); const debugChannel = "C01DBP67MSQ"; // #testingbot //const debugChannel = 'C01H6RB99E2'; //Carter debug const endPointsJson = require("./endpoints.json"); @@ -25,6 +21,20 @@ const gitHubCredentials = { token: `${process.env["GITHUB_TOKEN"]}` }; +const slackBotGetToken = () => { + const token = process.env["SLACKBOT_TOKEN"]; + + if (!token) { + //developers that don't set the creds can still use the rest of the code + console.error( + `You need local.settings.json to contain "SLACKBOT_TOKEN" to use slackbot features.` + ); + return; + } + + return token; +}; + /** * * @param {{executionContext:{functionName:string}}} context @@ -51,13 +61,8 @@ module.exports = async function (context, myTimer, activeEndpoints) { try { await doProcessEndpoints(work); } catch (e) { - await slackBotReportError( - debugChannel, - `Error running ${appName}`, - e, - context, - myTimer - ); + const slackBot = new SlackBot(slackBotGetToken(), debugChannel); + await slackBot.Error(e, myTimer); } }; @@ -84,7 +89,7 @@ const doProcessEndpoints = async work => { gitHubCommitter ); - if (endpoint.ReportingChannel_Slack) { + if (endpoint.ReportingChannel_Slack && slackBotGetToken()) { //Endpoint reporting channel enabled. Add a post for each commit report. if (commitReports?.length) { /** @type {string[]} */ @@ -97,25 +102,22 @@ const doProcessEndpoints = async work => { ); }); + const slackBot = new SlackBot( + slackBotGetToken(), + endpoint.ReportingChannel_Slack, + { username: endpoint.name } + ); + const allfileNames = [...new Set(mergeFileNames)]; - const slackPostTS = ( - await ( - await slackBotChatPost( - endpoint.ReportingChannel_Slack, - `${endpoint.name} - _${allfileNames.join(", ")}_` - ) - ).json() - ).ts; + await slackBot.Chat(`_${allfileNames.join(", ")}_`); for (const commitReport of commitReports) { const fileData = commitReport.Files.map( x => `• ${x.status} - _${x.filename.split("/").slice(-1)[0]}_` ).join("\n"); - await slackBotReplyPost( - endpoint.ReportingChannel_Slack, - slackPostTS, + await slackBot.Reply( `<${commitReport.Commit.html_url}|${commitReport.Commit.message}>\n${fileData}` ); } diff --git a/common/slackBot/index.js b/common/slackBot/index.js deleted file mode 100644 index a7ee528..0000000 --- a/common/slackBot/index.js +++ /dev/null @@ -1,197 +0,0 @@ -// @ts-check -const fetchRetry = require("fetch-retry")(require("node-fetch/lib"), { - retries: 3, - retryDelay: 2000 -}); -const slackApiChatPost = "https://slack.com/api/chat.postMessage"; -const slackApiChannelHistory = "https://slack.com/api/conversations.history"; -const slackApiChannelReplies = "https://slack.com/api/conversations.replies"; -const slackApiReaction = "https://slack.com/api/reactions.add"; - -//For help building attachments...go here... -//https://api.slack.com/docs/messages/builder - -const slackBotGetToken = () => { - const token = process.env["SLACKBOT_TOKEN"]; - - if (!token) { - //developers that don't set the creds can still use the rest of the code - console.error( - `You need local.settings.json to contain "SLACKBOT_TOKEN" to use slackbot features.` - ); - return; - } - - return token; -}; - -const slackApiHeaders = { - Authorization: `Bearer ${slackBotGetToken()}`, - "Content-Type": "application/json;charset=utf-8" -}; - -const slackApiPost = bodyJSON => ({ - method: "POST", - headers: slackApiHeaders, - body: JSON.stringify(bodyJSON) -}); -const slackApiGet = () => ({ - headers: slackApiHeaders -}); - -/** - * List the post history for a channel - * - * (See https://api.slack.com/methods/conversations.history) - * - * @param {string} channel - Slack channel to search in - */ -const slackBotChannelHistory = async channel => - fetchRetry(`${slackApiChannelHistory}?channel=${channel}`, slackApiGet()); - -/** - * Get a list of replies for a post - * - * (See https://api.slack.com/methods/conversations.replies) - * - * @param {string} channel - Slack channel to search in - * @param {string} ts - Timestamp (TS) for root Slack post - */ -const slackBotChannelReplies = async (channel, ts) => - fetchRetry( - `${slackApiChannelReplies}?channel=${channel}&ts=${ts}`, - slackApiGet() - ); - -/** - * Add a Slack post - * - * (See https://api.slack.com/methods/chat.postMessage) - * - * (Also https://api.slack.com/docs/messages/builder) - * - * @param {string} channel - Slack channel to post in - * @param {string} text - Post text - * @param {string} [attachments] - Optional Post attachments - */ -const slackBotChatPost = async (channel, text, attachments) => { - const payload = { - channel, - text, - attachments - }; - return fetchRetry(slackApiChatPost, slackApiPost(payload)); -}; -/** - * Add a reply to a Slack post. - * - * @param {string} channel - Slack channel to post in - * @param {string} thread_ts - Timestamp (TS) for Slack post - * @param {string} text - Post text - * @param {string} [attachments] - Optional Post attachments - */ -const slackBotReplyPost = async (channel, thread_ts, text, attachments) => { - const payload = { - channel, - text, - thread_ts, - attachments - }; - - return fetchRetry(slackApiChatPost, slackApiPost(payload)); -}; - -/** - * Add a reaction to a Slack post.
- * - * (see https://api.slack.com/methods/reactions.add) - * - * @param {string} channel - Slack channel to post in - * @param {string} timestamp - Timestamp (TS) for Slack post - * @param {string} name - emoji name - */ -const slackBotReactionAdd = async (channel, timestamp, name) => { - const payload = { - channel, - timestamp, - name - }; - - return fetchRetry(slackApiReaction, slackApiPost(payload)); -}; - -const slackBotDelayedChatPost = async (channel, text, post_at) => { - const payload = { - channel, - text, - post_at - }; - - const fetchResp = await fetchRetry( - "https://slack.com/api/chat.scheduleMessage", - slackApiPost(payload) - ); - const postInfo = await fetchResp.json(); - return postInfo; -}; - -/** - * Report an error to a slack channel. - * - * @param {string} channel - Slack channel to post in - * @param {string} title - the post title - * @param {{stack:string}} errorObject - the error object to display - * @param {*} [request] - optional request object to display - * @param {*} [data] - optional data object to display - */ -const slackBotReportError = async ( - channel, - title, - errorObject, - request, - data -) => { - console.error(errorObject); - - let slackText = `${title}\n*Error Stack*\n\`\`\`${errorObject.stack}\`\`\``; - - if (request) { - slackText += `\n\n*Request*\n\`\`\`${JSON.stringify( - request, - null, - 2 - )}\`\`\``; - } - if (data) { - slackText += `\n\n*Data*\n\`\`\`${JSON.stringify(data, null, 2)}\`\`\``; - } - - const historyResponse = await slackBotChannelHistory(channel); - const history = await historyResponse.json(); - const lastHourHistory = history.messages.filter( - c => - c.text.startsWith(`${title}\n`) && - // @ts-ignore - // prettier-ignore - (new Date() - new Date(1000 * Number(c.latest_reply || c.ts))) / 1000 / 60 / 60 < 1 - ); //last hour - //check to see if the last post was the same title, if so make this a reply - - if (lastHourHistory && lastHourHistory.length) { - //add to error thread - return slackBotReplyPost(channel, lastHourHistory[0].ts, slackText); - } else { - //new error - return slackBotChatPost(channel, slackText); - } -}; - -module.exports = { - slackBotChatPost, - slackBotReplyPost, - slackBotDelayedChatPost, - slackBotReportError, - slackBotChannelHistory, - slackBotChannelReplies, - slackBotReactionAdd -}; diff --git a/package-lock.json b/package-lock.json index 46354b4..76a0f4e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,8 @@ "version": "1.0.0", "license": "ISC", "dependencies": { - "@cagov/wordpress-to-github": "^0.0.2" + "@cagov/slack-connector": "^0.0.1", + "@cagov/wordpress-to-github": "file:wordpress-to-github" }, "devDependencies": { "eslint": "^7.32.0", @@ -110,17 +111,19 @@ "node": ">=4" } }, - "node_modules/@cagov/wordpress-to-github": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/@cagov/wordpress-to-github/-/wordpress-to-github-0.0.2.tgz", - "integrity": "sha512-AVmIS2FWNKHTNjKbl+mofQ/H/S+NKSUnbg3+xgSlhh/gJOR7TCo7SN0A5HvgzEhz4w6gWuey5Mp8IHy5MEAkWA==", + "node_modules/@cagov/slack-connector": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/@cagov/slack-connector/-/slack-connector-0.0.1.tgz", + "integrity": "sha512-YDJ4k9tg7JkWen90WlZzT+x+fG3Iiefn0/6YD8lHIX0mcueOrN/l7bjqFolSVFjTv+z4grXSfDGck78mEFBbRw==", "dependencies": { "fetch-retry": "^4.1.1", - "github-api": "^3.4.0", - "node-fetch": "^2.6.1", - "sha1": "^1.1.1" + "node-fetch": "^2.6.1" } }, + "node_modules/@cagov/wordpress-to-github": { + "resolved": "wordpress-to-github", + "link": true + }, "node_modules/@es-joy/jsdoccomment": { "version": "0.10.8", "integrity": "sha512-3P1JiGL4xaR9PoTKUHa2N/LKwa2/eUdRqGwijMWWgBqbFEqJUVpmaOi2TcjcemrsRMgFLBzQCK4ToPhrSVDiFQ==", @@ -1395,7 +1398,6 @@ "wordpress-to-github": { "name": "@cagov/wordpress-to-github", "version": "0.0.2", - "extraneous": true, "license": "MIT", "dependencies": { "fetch-retry": "^4.1.1", @@ -1480,10 +1482,17 @@ } } }, + "@cagov/slack-connector": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/@cagov/slack-connector/-/slack-connector-0.0.1.tgz", + "integrity": "sha512-YDJ4k9tg7JkWen90WlZzT+x+fG3Iiefn0/6YD8lHIX0mcueOrN/l7bjqFolSVFjTv+z4grXSfDGck78mEFBbRw==", + "requires": { + "fetch-retry": "^4.1.1", + "node-fetch": "^2.6.1" + } + }, "@cagov/wordpress-to-github": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/@cagov/wordpress-to-github/-/wordpress-to-github-0.0.2.tgz", - "integrity": "sha512-AVmIS2FWNKHTNjKbl+mofQ/H/S+NKSUnbg3+xgSlhh/gJOR7TCo7SN0A5HvgzEhz4w6gWuey5Mp8IHy5MEAkWA==", + "version": "file:wordpress-to-github", "requires": { "fetch-retry": "^4.1.1", "github-api": "^3.4.0", diff --git a/package.json b/package.json index a27a7c1..71c856e 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,7 @@ "author": "", "license": "ISC", "dependencies": { + "@cagov/slack-connector": "^0.0.1", "@cagov/wordpress-to-github": "file:wordpress-to-github" }, "devDependencies": {