Skip to content

Commit

Permalink
feat: support mark-as-read
Browse files Browse the repository at this point in the history
  • Loading branch information
Ebonsignori committed Aug 1, 2022
1 parent 40db739 commit bfa48b1
Show file tree
Hide file tree
Showing 5 changed files with 74 additions and 21 deletions.
14 changes: 10 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ jobs:
## Finding The Channel ID
In order for a Slack bot to DM you, it needs privledges to.
In order for a Slack bot to DM you, it needs privileges to.
In order for your bot to post to a channel, you should invite it with `/invite @botname`

Expand Down Expand Up @@ -96,7 +96,7 @@ The ID of a slack channel or DM that you wish your notifications to go to. See [

### Reason Filtering

For `reason` filters, refer to [notification reason types](https://docs.github.com/en/account-and-profile/managing-subscriptions-and-notifications-on-github/setting-up-notifications/configuring-notifications#filtering-email-notifications) for a more detailed explination of each `reason`.
For `reason` filters, refer to [notification reason types](https://docs.github.com/en/account-and-profile/managing-subscriptions-and-notifications-on-github/setting-up-notifications/configuring-notifications#filtering-email-notifications) for a more detailed explanation of each `reason`.

A list of accepted reasons can be found [here](https://github.com/Ebonsignori/github-notifications-slack-forwarder/blob/main/action.yml#L19)

Expand Down Expand Up @@ -144,6 +144,12 @@ Defaults to `"true"`

### Optional Configuration

#### `mark-as-read`

Set to `"true"` to mark forwarded notifications as "read"

Defaults to `"false"`

#### `sort-oldest-first`

Sort Slack message(s) by oldest notifications first.
Expand All @@ -166,12 +172,12 @@ Defaults to `"M/DD h:mm A"`

By default notifications are sent as a single Slack message.

Set to "false" to send a new Slack messages for each notification (may run into rate limiting problems)
Set to "false" to send a new Slack messages for each notification (may run into rate limiting problems depending on bot limits)

Defaults to `"true"`

#### `paginate-all`

By default, the action checks the last 100 notifications since the last `action-schedule` was fired. Set to "true" to check all notifications at the cost of a bigger fetch.

Useful if you recieve a lot of notifications and not all are being forwarded to you.
Useful if you receive a lot of notifications and not all are being forwarded to you, for instance if you have an `action-schedule` with long gaps between runs.
8 changes: 4 additions & 4 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ inputs:
description: 'Set to "false" to include notifications marked as "read"'
required: false
default: "true"
mark-as-read:
description: 'Set to "true" to mark forwarded notifications as "read"'
required: false
default: "false"
sort-oldest-first:
required: false
description: "Sort Slack message(s) by oldest notifications first."
Expand All @@ -57,10 +61,6 @@ inputs:
description: 'Set to "false" to send Slack messages for each notification rather than a single rollup of all notifications into one message.'
required: false
default: "true"
mark-as-read:
description: 'Set to "true" to mark forwarded notifications as "read"'
required: false
default: "false"

runs:
using: node16
Expand Down
36 changes: 33 additions & 3 deletions src/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,12 @@ const defaultEnv = {
"filter-exclude-repositories": "",
"filter-only-participating": "false",
"filter-only-unread": "true",
"rollup-notifications": "true",
"mark-as-read": "false",
"sort-oldest-first": "true",
timezone: "UTC",
"date-format": "M/D h:ma",
"rollup-notifications": "true",
"paginate-all": "false",
"mark-as-read": "false",
};

function setMockEnv(envMap: { [key: string]: any }) {
Expand Down Expand Up @@ -72,6 +72,8 @@ function mockGetOctokit(
listNotificationsForAuthenticatedUser: sinon
.stub()
.resolves({ data: notifications }),
markThreadAsRead: sinon
.stub()
},
},
paginate: sinon.stub().resolves(notifications),
Expand Down Expand Up @@ -237,6 +239,33 @@ test("sends slack message of notifications using defaults", async (t) => {
t.true(slack.chat.postMessage.getCall(0).args[0].text.includes("<A notification>"));
});

test("marks sent notifications as read when mark-as-read is true", async (t) => {
setMockEnv({
"mark-as-read": "true",
// Don't reverse order to make testing easier
"sort-oldest-first": "false",
});
const getCore = mockGetCore();
const getOctokit = mockGetOctokit([
createMockNotification("<Notification 1>", "github/github", REASONS.ASSIGN),
createMockNotification("<Notification 2>", "github/howie", REASONS.PUSH)
]);
const getSlack = mockGetSlack();

await run(getCore as any, getOctokit as any, getSlack as any);

const core = getCore();
const octokit = getOctokit();
const slack = getSlack();

t.true(core.setFailed.notCalled);
t.is(octokit.rest.activity.listNotificationsForAuthenticatedUser.callCount, 1);
t.is(slack.chat.postMessage.callCount, 1);
t.is(octokit.rest.activity.markThreadAsRead.callCount, 2);
t.true(octokit.rest.activity.markThreadAsRead.getCall(0).args[0].thread_id.includes("<Notification 1>"));
t.true(octokit.rest.activity.markThreadAsRead.getCall(1).args[0].thread_id.includes("<Notification 2>"));
});

test("filters on filter-include-reasons", async (t) => {
setMockEnv({
"filter-include-reasons": `${REASONS.ASSIGN}, ${REASONS.PUSH}, ${REASONS.AUTHOR}`
Expand Down Expand Up @@ -378,5 +407,6 @@ test("filters on filter-exclude-repositories", async (t) => {
t.true(messageBody.includes("<Notification 5>"));
});

// TODO: Test mark as read
// TODO: Test rollup-notifications
// TODO: test timezone
// TODO: test timezone and date-format
27 changes: 23 additions & 4 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,9 +97,9 @@ async function run(
return core.info(
`No new notifications fetched since last run with given filters:\n<filter-only-unread>: ${inputs.filterOnlyUnread}\n<filter-only-participating>: ${inputs.filterOnlyParticipating}`
);
}

}
let notifications = notificationsFetch;
core.info(`${notifications.length} notifications fetched before filtering.`);

// Filter notifications to include/exclude user defined "reason"s
if (inputs.filterIncludeReasons.length) {
Expand Down Expand Up @@ -139,16 +139,35 @@ async function run(
);
}

for (const notification of notifications) {
console.log(notification)
console.log(notification.subject.url);
const item = await octokit.request(notification.subject.url);
console.log(item)
}

// Default return is DESC, we want ASC to show oldest first
if (inputs.sortOldestFirst) {
notifications = notifications.reverse();
}

// Send Slack Message
core.info("Forwarding notifications to Slack...");
core.info(`Forwarding ${notifications.length} notifications to Slack...`);
await sendToSlack(core, slack, inputs, notifications);

return core.info("Notification message(s) sent!");
core.info("Notification message(s) sent!");

// Mark notifications as read if configured to
if (inputs.markAsRead) {
core.info("Marking ${notifications.length} as read...");
for (const notification of notifications) {
await octokit.rest.activity.markThreadAsRead({
thread_id: notification.id,
})
}
}

core.info("Action complete!");
} catch (error: any) {
core.error(error);
core.setFailed(error?.message);
Expand Down
10 changes: 4 additions & 6 deletions src/lib/get-inputs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,12 @@ export enum INPUTS {
filterExcludeRepositories = "filter-exclude-repositories",
filterOnlyParticipating = "filter-only-participating",
filterOnlyUnread = "filter-only-unread",
rollupNotifications = "rollup-notifications",
markAsRead = "mark-as-read",
sortOldestFirst = "sort-oldest-first",
timezone = "timezone",
dateFormat = "date-format",
paginateAll = "paginate-all",
// TODO: When supported in API
markAsRead = "mark-as-read",
rollupNotifications = "rollup-notifications",
}

export enum REASONS {
Expand Down Expand Up @@ -177,17 +176,16 @@ function getInputs(core: typeof CoreLibrary) {
INPUT_TYPE.boolean,
false
),
markAsRead: getInput(INPUTS.markAsRead, INPUT_TYPE.boolean, false),
sortOldestFirst: getInput(INPUTS.sortOldestFirst, INPUT_TYPE.boolean, false),
timezone: getInput(INPUTS.timezone, INPUT_TYPE.string, false),
dateFormat: getInput(INPUTS.dateFormat, INPUT_TYPE.string, false),
paginateAll: getInput(INPUTS.paginateAll, INPUT_TYPE.boolean, false),
rollupNotifications: getInput(
INPUTS.rollupNotifications,
INPUT_TYPE.boolean,
false
),
paginateAll: getInput(INPUTS.paginateAll, INPUT_TYPE.boolean, false),
// TODO: When supported in API
markAsRead: getInput(INPUTS.markAsRead, INPUT_TYPE.boolean, false),
};
}

Expand Down

0 comments on commit bfa48b1

Please sign in to comment.