|
| 1 | +const { |
| 2 | + LE_BOT_USERNAME, |
| 3 | + CLOSE_CONTRIBUTORS, |
| 4 | + KEYWORDS_DETECT_ASSIGNMENT_REQUEST, |
| 5 | + ISSUE_LABEL_HELP_WANTED, |
| 6 | + BOT_MESSAGE_ISSUE_NOT_OPEN |
| 7 | +} = require('./constants'); |
| 8 | + |
| 9 | +module.exports = async ({ github, context, core }) => { |
| 10 | + try { |
| 11 | + const issueNumber = context.payload.issue.number; |
| 12 | + const issueUrl = context.payload.issue.html_url; |
| 13 | + const issueTitle = context.payload.issue.title; |
| 14 | + const escapedTitle = issueTitle.replace(/"/g, '\\"'); |
| 15 | + const commentId = context.payload.comment.id; |
| 16 | + const commentTime = new Date(context.payload.comment.created_at); |
| 17 | + const oneHourBefore = new Date(commentTime - 3600000); |
| 18 | + const commentAuthor = context.payload.comment.user.login; |
| 19 | + const commentBody = context.payload.comment.body; |
| 20 | + const repo = context.repo.repo; |
| 21 | + const owner = context.repo.owner; |
| 22 | + const supportDevSlackWebhookUrl = process.env.SLACK_WEBHOOK_URL; |
| 23 | + const supportDevNotificationsSlackWebhookUrl = process.env.SLACK_COMMUNITY_NOTIFICATIONS_WEBHOOK_URL; |
| 24 | + const keywordRegexes = KEYWORDS_DETECT_ASSIGNMENT_REQUEST |
| 25 | + .map(k => k.trim().toLowerCase()) |
| 26 | + .filter(Boolean) |
| 27 | + .map(keyword => new RegExp(`\\b${keyword}\\b`, 'i')); |
| 28 | + |
| 29 | + |
| 30 | + |
| 31 | + async function hasLabel(name) { |
| 32 | + let labels = []; |
| 33 | + try { |
| 34 | + const response = await github.rest.issues.listLabelsOnIssue({ |
| 35 | + owner, |
| 36 | + repo, |
| 37 | + issue_number: issueNumber |
| 38 | + }); |
| 39 | + labels = response.data.map(label => label.name); |
| 40 | + } catch (error) { |
| 41 | + core.warning(`⚠️ Failed to fetch labels on issue #${issueNumber}: ${error.message}`); |
| 42 | + labels = []; |
| 43 | + } |
| 44 | + return labels.some(label => label.toLowerCase() === name.toLowerCase()); |
| 45 | + } |
| 46 | + |
| 47 | + async function findRecentCommentsByUser(username) { |
| 48 | + try{ |
| 49 | + let response = await github.rest.issues.listComments({ |
| 50 | + owner, |
| 51 | + repo, |
| 52 | + issue_number: issueNumber, |
| 53 | + since: oneHourBefore.toISOString() |
| 54 | + }); |
| 55 | + return response.data.filter(comment => comment.user.login === username); |
| 56 | + } catch (error) { |
| 57 | + core.warning(`⚠️ Failed to fetch comments on issue #${issueNumber}: ${error.message}`); |
| 58 | + return []; |
| 59 | + } |
| 60 | + } |
| 61 | + |
| 62 | + async function botReply(){ |
| 63 | + let response = null; |
| 64 | + try { |
| 65 | + response = await github.rest.issues.createComment({ |
| 66 | + owner, |
| 67 | + repo, |
| 68 | + issue_number: issueNumber, |
| 69 | + body: BOT_MESSAGE_ISSUE_NOT_OPEN |
| 70 | + }); |
| 71 | + if (response?.data?.html_url) { |
| 72 | + core.setOutput('bot_replied', true); |
| 73 | + const slackMessage = `*[${repo}] <${response.data.html_url}|Bot response sent> on issue: <${issueUrl}|${escapedTitle}>*`; |
| 74 | + core.setOutput('slack_notification_bot_comment', slackMessage); |
| 75 | + } |
| 76 | + } catch (error) { |
| 77 | + core.warning(`Failed to post bot comment: ${error.message}`); |
| 78 | + core.setOutput('bot_replied', false); |
| 79 | + } |
| 80 | + return response; |
| 81 | + } |
| 82 | + |
| 83 | + |
| 84 | + if (await hasLabel(ISSUE_LABEL_HELP_WANTED) || CLOSE_CONTRIBUTORS.includes(commentAuthor)) { |
| 85 | + core.setOutput('webhook_url', supportDevSlackWebhookUrl); |
| 86 | + } else { |
| 87 | + core.setOutput('webhook_url', supportDevNotificationsSlackWebhookUrl); |
| 88 | + const matchedKeyword = keywordRegexes.find(regex => regex.test(commentBody)); |
| 89 | + // post a bot reply if there is matched keyword and no previous bot comment in past hour |
| 90 | + if(matchedKeyword){ |
| 91 | + let lastBotComment; |
| 92 | + let PastBotComments = await findRecentCommentsByUser(LE_BOT_USERNAME); |
| 93 | + if(PastBotComments.length > 0){ |
| 94 | + lastBotComment = PastBotComments.at(-1); |
| 95 | + core.setOutput('bot_replied', false); |
| 96 | + } else if(PastBotComments.length === 0){ |
| 97 | + console.log("bot is replying"); |
| 98 | + lastBotComment = await botReply(); |
| 99 | + } |
| 100 | + } |
| 101 | + } |
| 102 | + |
| 103 | + const message = `*[${repo}] <${issueUrl}#issuecomment-${commentId}|New comment> on issue: <${issueUrl}|${escapedTitle}> by ${commentAuthor}*`; |
| 104 | + core.setOutput('slack_notification_comment', message); |
| 105 | + |
| 106 | + } catch (error) { |
| 107 | + core.setFailed(`Action failed with error: ${error.message}`); |
| 108 | + } |
| 109 | +}; |
0 commit comments