Skip to content

Commit d105ac9

Browse files
feat: multiple discord+slack ids support (shubhaamgupta11#22)
* feat: added multiple slack and discord ids support * feat: version bumup to 1.0.1
1 parent 9b60b35 commit d105ac9

File tree

12 files changed

+191
-95
lines changed

12 files changed

+191
-95
lines changed

README.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ This [GitHub Action](https://github.com/marketplace/actions/repo-activity-monito
88

99
- Tracking new issues and pull requests.
1010
- Sending auto-generated notifications to **Slack** or **Discord**.
11-
- Customizing **Slack** notifications with the ability to ping specific users or groups.
12-
- Customizing **Discord** notifications with the ability to ping specific users or roles.
11+
- Customizing **Slack** notifications with the ability to multiple users or groups.
12+
- Customizing **Discord** notifications with the ability to multiple users or roles.
1313
- Allowing **Slack** notifications to be sent to designated channels.
1414

1515
With **Repo Activity Monitor**, you can stay on top of your repositories activities, streamline communication, and ensure no critical issues or pull requests fall through the cracks.
@@ -49,7 +49,7 @@ jobs:
4949
slack_bot_token: "${{ secrets.SLACK_BOT_TOKEN }}"
5050
slack_channel: "<channel-id>"
5151
slack_id_type: "<user/group>" # Optional: Only needed to ping someone directly.
52-
slack_id: "<user-id/group-id>" # Optional: Only needed if slack_id_type is provided.
52+
slack_ids: "<user-id/group-id>" # Optional: Only needed if slack_id_type is provided. Can pass multiple similar type ids separated by commas. e.g. "Uyyyxxxx,Uzzzxxxx"
5353
```
5454
5555
> **Note:** slack_id_type and slack_id are only needed if you want to ping someone directly.
@@ -86,7 +86,7 @@ jobs:
8686
# Discord-specific inputs
8787
discord_webhook_url: "${{ secrets.DISCORD_WEBHOOK_URL }}"
8888
discord_id_type: "<user/role>" # Optional: Only needed to ping someone directly.
89-
discord_id: "<user-id/role-id>" # Optional: Only needed if discord_id_type is provided.
89+
discord_ids: "<user-id/role-id>" # Optional: Only needed if discord_id_type is provided. Can pass multiple similar type ids separated by commas. e.g. "Uyyyxxxx,Uzzzxxxx"
9090
```
9191
9292
> **Note:** You can configure any notifier (slack, discord) for any task (monitor-issues, monitor-prs, etc.).
@@ -130,10 +130,10 @@ For Pull Requests
130130
| slack_bot_token | Slack bot token to send notifications (required if notifier=`slack`). | No | None |
131131
| slack_channel | The Slack channel id to send notifications to (required if notifier=`slack`). | No | None |
132132
| slack_id_type | Type of Slack ID (user or group, required if notifier=`slack`). This is needed to ping someone directly. | No | None |
133-
| slack_id | user id or group id as per `slack_id_type` (required if notifier=`slack`). | No | None |
133+
| slack_ids | user id or group id as per `slack_id_type` (required if notifier=`slack`). Can pass multiple similar type ids separated by commas. e.g. "Uyyyxxxx,Uzzzxxxx" | No | None |
134134
| discord_webhook_url | Discord webhook URL to send notifications (required if notifier=`discord`). | No | None |
135135
| discord_id_type | Type of Discord ID (user or role, required if notifier=`discord`). This is needed to ping someone directly. | No | None |
136-
| discord_id | user id or role id as per `discord_id_type` (required if notifier=`discord`). | No | None |
136+
| discord_ids | user id or role id as per `discord_id_type` (required if notifier=`discord`). Can pass multiple similar type ids separated by commas. e.g. "Uyyyxxxx,Uzzzxxxx" | No | None |
137137

138138
## 📖 How It Works
139139
- The action listens for new issues or PRs in the specified GitHub repository.
@@ -145,7 +145,7 @@ For Pull Requests
145145

146146
### Slack
147147

148-
- Create a [Slack App](https://api.slack.com/bot-users#creating-bot-user).
148+
- Create a [Slack App](https://api.slack.com/quickstart).
149149
- Generate a Slack Bot Token.
150150
- Retrieve the Channel ID and User/Group IDs.
151151
- Add these secrets to your GitHub repository:

action.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,8 @@ inputs:
3434
slack_id_type:
3535
description: Type of Slack ID (user or group).
3636
required: false
37-
slack_id:
38-
description: Slack ID of the recipient (user or group).
37+
slack_ids:
38+
description: Slack IDs of the recipients (user or group) must be comma separated and all must be of same type.
3939
required: false
4040
# Discord-specific inputs
4141
discord_webhook_url:
@@ -44,8 +44,8 @@ inputs:
4444
discord_id_type:
4545
description: Type of Discord ID (user or role).
4646
required: false
47-
discord_id:
48-
description: Discord ID of the recipient (user or role).
47+
discord_ids:
48+
description: Discord IDs of the recipients (user or role) must be comma separated and all must be of same type.
4949
required: false
5050

5151

action/index.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,12 @@ async function run() {
1717
const slackToken = core.getInput("slack_bot_token");
1818
const slackChannel = core.getInput("slack_channel");
1919
const slackIDType = core.getInput("slack_id_type");
20-
const slackID = core.getInput("slack_id");
20+
const slackIDs = core.getInput("slack_ids");
2121

2222
// Discord-specific inputs
2323
const discordWebhookUrl = core.getInput("discord_webhook_url");
2424
const discordIDType = core.getInput("discord_id_type");
25-
const discordID = core.getInput("discord_id");
25+
const discordIDs = core.getInput("discord_ids");
2626

2727
switch (task) {
2828
case "monitor-issues":
@@ -31,8 +31,8 @@ async function run() {
3131
owner,
3232
repo,
3333
notifier,
34-
slackConfig: { slackToken, slackChannel, slackIDType, slackID },
35-
discordConfig: { discordWebhookUrl, discordIDType, discordID },
34+
slackConfig: { slackToken, slackChannel, slackIDType, slackIDs },
35+
discordConfig: { discordWebhookUrl, discordIDType, discordIDs },
3636
alertTime,
3737
});
3838
break;
@@ -43,8 +43,8 @@ async function run() {
4343
owner,
4444
repo,
4545
notifier,
46-
slackConfig: { slackToken, slackChannel, slackIDType, slackID },
47-
discordConfig: { discordWebhookUrl, discordIDType, discordID },
46+
slackConfig: { slackToken, slackChannel, slackIDType, slackIDs },
47+
discordConfig: { discordWebhookUrl, discordIDType, discordIDs },
4848
alertTime,
4949
});
5050
break;

action/integrations/discord.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ const discordWrapper = (webhookUrl) => {
1717
};
1818

1919
// Send Discord Notifications
20-
const sendDiscordNotification = async (webhookUrl, issues, repo, type, discordIDType, discordID) => {
20+
const sendDiscordNotification = async (webhookUrl, issues, repo, type, discordIDType, discordIDs) => {
2121
if (!issues.length) {
2222
console.log("No issues found within the specified time frame.");
2323
return;
@@ -27,7 +27,7 @@ const sendDiscordNotification = async (webhookUrl, issues, repo, type, discordID
2727

2828

2929
for (const issue of issues) {
30-
let payload = generateDiscordPayload({type, repo, issue, discordIDType, discordID});
30+
let payload = generateDiscordPayload({type, repo, issue, discordIDType, discordIDs});
3131

3232
try {
3333
await discord.sendMessage(payload);

action/integrations/slack.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ const sendSlackNotification = async (
2929
slackToken,
3030
slackChannel,
3131
slackIDType,
32-
slackID,
32+
slackIDs,
3333
issues,
3434
repo,
3535
type
@@ -47,7 +47,7 @@ const sendSlackNotification = async (
4747
repo,
4848
issue,
4949
slackIDType,
50-
slackID,
50+
slackIDs,
5151
});
5252

5353
try {

action/monitor-new-issue.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ async function monitorIssues({
8888
slackToken,
8989
slackChannel,
9090
slackIDType,
91-
slackID,
91+
slackIDs,
9292
} = slackConfig;
9393
console.log(
9494
"🔔 Sending notifications to Slack for issues:",
@@ -98,7 +98,7 @@ async function monitorIssues({
9898
slackToken,
9999
slackChannel,
100100
slackIDType,
101-
slackID,
101+
slackIDs,
102102
issues,
103103
repo,
104104
"issue"
@@ -107,13 +107,13 @@ async function monitorIssues({
107107
const {
108108
discordWebhookUrl,
109109
discordIDType,
110-
discordID,
110+
discordIDs,
111111
} = discordConfig;
112112
console.log(
113113
"🔔 Sending notifications to Discord for issues:",
114114
issues.map((issue) => issue.title)
115115
);
116-
await sendDiscordNotification(discordWebhookUrl, issues, repo, "issue", discordIDType, discordID);
116+
await sendDiscordNotification(discordWebhookUrl, issues, repo, "issue", discordIDType, discordIDs);
117117
} else {
118118
throw new Error("Unsupported notifier. Use 'slack' or 'discord'.");
119119
}

action/monitor-new-pr.js

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ const fetchNewPRs = async (gitToken, owner, repo, alertTime) => {
2020

2121
let newPRs = [];
2222
let page = 1;
23+
let olderThanCutoff = false;
2324

2425
try {
2526
while (true) {
@@ -32,10 +33,12 @@ const fetchNewPRs = async (gitToken, owner, repo, alertTime) => {
3233
page, // Current page of the results
3334
},
3435
});
35-
3636
const recentPRs = response.data.filter((pr) => {
3737
const createdAt = new Date(pr.created_at);
3838
// Exclude PRs created by dependabot and older than the cutoff date
39+
if (createdAt < new Date(cutoffDate)) {
40+
olderThanCutoff = true;
41+
}
3942
return (
4043
pr.user?.login !== "dependabot[bot]" &&
4144
createdAt >= new Date(cutoffDate)
@@ -53,6 +56,8 @@ const fetchNewPRs = async (gitToken, owner, repo, alertTime) => {
5356
}))
5457
);
5558

59+
if (olderThanCutoff) break;
60+
5661
const hasNextPage = response.headers["link"]?.includes('rel="next"');
5762
if (!hasNextPage) break;
5863

@@ -90,7 +95,7 @@ async function monitorPRs({
9095
slackToken,
9196
slackChannel,
9297
slackIDType,
93-
slackID,
98+
slackIDs,
9499
} = slackConfig;
95100
console.log(
96101
"🔔 Sending notifications to Slack for PRs:",
@@ -100,7 +105,7 @@ async function monitorPRs({
100105
slackToken,
101106
slackChannel,
102107
slackIDType,
103-
slackID,
108+
slackIDs,
104109
prs,
105110
repo,
106111
"pr"
@@ -109,13 +114,14 @@ async function monitorPRs({
109114
const {
110115
discordWebhookUrl,
111116
discordIDType,
112-
discordID,
117+
discordIDs,
113118
} = discordConfig;
119+
114120
console.log(
115121
"🔔 Sending notifications to Discord for PRs:",
116122
prs.map((pr) => pr.title)
117123
);
118-
await sendDiscordNotification(discordWebhookUrl, prs, repo, "pr", discordIDType, discordID);
124+
await sendDiscordNotification(discordWebhookUrl, prs, repo, "pr", discordIDType, discordIDs);
119125
} else {
120126
throw new Error("Unsupported notifier. Use 'slack' or 'discord'.");
121127
}

action/utility/generatePayload.js

Lines changed: 63 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,42 @@
1-
function generateSlackPayload({ type, repo, issue, slackIDType, slackID }) {
1+
const generateSlackContent = (slackIDType, slackIDs) => {
2+
let content = "";
3+
let isAssignee = false;
4+
if (slackIDType === "user") {
5+
if (slackIDs) {
6+
const slackIDsArray = slackIDs.split(",");
7+
slackIDsArray.forEach(id => {
8+
if (id.trim() !== "") {
9+
isAssignee = true;
10+
content += `<@${id.trim()}> `;
11+
}
12+
});
13+
if (isAssignee) {
14+
content = `*Assignee:* ` + content;
15+
}
16+
}
17+
} else if (slackIDType === "group") {
18+
if (slackIDs) {
19+
const slackIDsArray = slackIDs.split(",");
20+
slackIDsArray.forEach(id => {
21+
if (id.trim() !== "") {
22+
isAssignee = true;
23+
content += `<!subteam^${id.trim()}> `;
24+
}
25+
});
26+
if (isAssignee) {
27+
content = `*Assignee:* ` + content;
28+
}
29+
}
30+
}
31+
return content;
32+
}
33+
34+
function generateSlackPayload({ type, repo, issue, slackIDType, slackIDs }) {
235
let assigneeText = "";
336
const shouldDisplayAvatar = true;
437

538
if (type === "issue") {
6-
assigneeText =
7-
slackIDType === "group"
8-
? `*Assignee:* <!subteam^${slackID}>`
9-
: slackIDType === "user"
10-
? `*Assignee:* <@${slackID}>`
11-
: "";
39+
assigneeText = generateSlackContent(slackIDType, slackIDs);
1240

1341
return {
1442
text: `📈 New Issue in ${repo}: ${issue.title}`, // Fallback text for notifications
@@ -75,12 +103,7 @@ function generateSlackPayload({ type, repo, issue, slackIDType, slackID }) {
75103
],
76104
};
77105
} else if (type === "pr") {
78-
assigneeText =
79-
slackIDType === "group"
80-
? `*Reviewer:* <!subteam^${slackID}> `
81-
: slackIDType === "user"
82-
? `*Reviewer:* <@${slackID}> `
83-
: "";
106+
assigneeText = generateSlackContent(slackIDType, slackIDs);
84107

85108
return {
86109
text: `🚀 New Pull Request in ${repo}: ${issue.title}`, // Fallback text for notifications
@@ -153,22 +176,41 @@ function generateSlackPayload({ type, repo, issue, slackIDType, slackID }) {
153176
}
154177
}
155178

179+
const generateDiscordContent = (discordIDType, discordIDs) => {
180+
let content = "";
181+
if (discordIDType === "user") {
182+
if (discordIDs) {
183+
const discordIDsArray = discordIDs.split(",");
184+
discordIDsArray.forEach(id => {
185+
if (id.trim() !== "") {
186+
content += `<@${id.trim()}> `;
187+
}
188+
});
189+
}
190+
} else if (discordIDType === "role") {
191+
if (discordIDs) {
192+
const discordIDsArray = discordIDs.split(",");
193+
discordIDsArray.forEach(id => {
194+
if (id.trim() !== "") {
195+
content += `<@&${id.trim()}> `;
196+
}
197+
});
198+
}
199+
}
200+
return content;
201+
}
202+
203+
156204
const generateDiscordPayload = ({
157205
type,
158206
repo,
159207
issue,
160208
discordIDType,
161-
discordID,
209+
discordIDs,
162210
}) => {
163-
let content = "";
211+
let content = generateDiscordContent(discordIDType, discordIDs);
164212
let message = "";
165213

166-
if (discordIDType === "user") {
167-
content = `<@${discordID}>`;
168-
} else if (discordIDType === "role") {
169-
content = `<@&${discordID}>`;
170-
}
171-
172214
if (type === "issue") {
173215
message = {
174216
content: content,

0 commit comments

Comments
 (0)