-
You need to create a new Slack app with following scopes:
- channels:read
- groups:read
- users:read
- users:read.email
-
Install it into a workspace
-
Invite it into a channel:
/invite @<app-name>
-
Install
npm i @slack/web-api
-
Run the script (NodeJS v20+ required):
export SLACK_TOKEN=<apps-bot-token> ./slack-channel-users.mjs --channel="<channel-id>"
Last active
August 23, 2024 08:03
-
-
Save aripalo/2e64623a65cc89b60dd45de5cdf50ebb to your computer and use it in GitHub Desktop.
Get users (and their email, first name and last name) from Slack channel
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
#!/usr/bin/env node | |
import { parseArgs } from "node:util"; | |
import assert from "node:assert/strict"; | |
import { WebClient } from "@slack/web-api"; | |
const token = process.env.SLACK_TOKEN; | |
assert(typeof token === "string", "SLACK_TOKEN missing"); | |
const web = new WebClient(token); | |
/** | |
* Reads channel ID from `--channel` CLI option | |
* @returns {string} | |
*/ | |
function getChannelFromArgs() { | |
const args = parseArgs({ options: { channel: { type: "string" } } }); | |
assert( | |
typeof args.values.channel === "string", | |
"Channel CLI option is required" | |
); | |
return args.values.channel; | |
} | |
/** | |
* Asserts that the response is a valid ConversationsMembers | |
* @param {unknown} value | |
* @returns {asserts value is import("@slack/web-api").ConversationsMembersResponse} | |
*/ | |
function assertMembersResponse(value) { | |
assert(value.ok, "API request failed"); | |
assert(Array.isArray(value.members), "Members not found"); | |
} | |
/** | |
* Get members of a channel | |
* @param {string} channel | |
* @returns {Promise<string[]>} list of member IDs | |
*/ | |
async function getMembers(channel) { | |
/** @type {string[]} */ | |
const members = []; | |
for await (const page of web.paginate("conversations.members", { channel })) { | |
assert(page.ok, "API request failed"); | |
assert(Array.isArray(page.members), "Members not found"); | |
members.push(...page.members); | |
} | |
return members; | |
} | |
/** | |
* Get single user | |
* @param {string} user | |
* @returns {Promise<Exclude<import("@slack/web-api").UsersInfoResponse["user"], undefined>>} | |
*/ | |
async function getUser(user) { | |
const response = await web.users.info({ user }); | |
assert(response.ok, "API request failed"); | |
assert(typeof response.user !== "undefined", "User not found"); | |
return response.user; | |
} | |
/** | |
* Describe user basic data | |
* @typedef {Object} UserBasicData | |
* @prop {string} email | |
* @prop {string} firstName | |
* @prop {string} lastName | |
*/ | |
/** | |
* Parse User object from UsersInfoResponse | |
* @param {Exclude<import("@slack/web-api").UsersInfoResponse["user"], undefined>} user | |
* @returns {UserBasicData} | |
*/ | |
function parseUserBasicData(user) { | |
assert(typeof user.profile !== "undefined", "Profile not found"); | |
const { profile } = user; | |
return { | |
email: profile.email, | |
firstName: profile.first_name, | |
lastName: profile.last_name, | |
}; | |
} | |
/** | |
* Main workflow | |
* @param {string} channelId | |
*/ | |
async function main(channelId) { | |
const members = await getMembers(channelId); | |
const users = await Promise.all(members.map((member) => getUser(member))); | |
const usersBasicData = users.map(parseUserBasicData); | |
console.log(usersBasicData); | |
} | |
main(getChannelFromArgs()).catch(console.error); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment