Skip to content

Instantly share code, notes, and snippets.

@letelete
Last active October 1, 2024 10:28
Show Gist options
  • Save letelete/843437eb21236b22adcb449194b0c6dc to your computer and use it in GitHub Desktop.
Save letelete/843437eb21236b22adcb449194b0c6dc to your computer and use it in GitHub Desktop.
Slack members scrapper
/**
* Slack members scrapper.
*
* Downloads a .csv file with members details.
*
* 1. Open /people on slack webapp: https://app.slack.com/client/<WORKSPACE_ID>/people
* 2. Paste it into the console
*/
(() => {
class CSVTransformer {
#columns = [];
/**
* @description Creates a new CSV transformer.
* @param {DataEntry[]} data An array of entries to include in the CSV file.
*/
constructor(data) {
this.data = data;
}
/**
* @description Add a new column that will be respected with the `build` method.
* @param {string} label A column title.
* @param {(item: DataEntry) => void} transformer Extract column data from the `data` entry.
* @returns `CSVTransformer`
*/
withColumn(label, transformer) {
this.#columns.push({ label, transformer });
return this;
}
/**
* @description Build raw string of CSV formatted `data`.
* @returns string
*/
build(delimiter = ";") {
const header = `${this.#columns.map(({ name }) => name).join(delimiter)}`;
const rows = this.data.map((item) =>
this.#columns
.map(({ transformer }) => transformer(item))
.join(delimiter)
);
return [header, ...rows].join(`\n`);
}
}
class SlackScrapper {
#selectors = {
memberCard: {
default: '[data-qa="browse_page_member"]',
image: "img",
name: '[data-qa="browse_page_member_card_entity__name_text"]',
},
};
getAllMembers() {
return [
...document.querySelectorAll(this.#selectors.memberCard.default),
].map((card) => {
const imageUrl = card.querySelector(
this.#selectors.memberCard.image
).src;
const name = card.querySelector(
this.#selectors.memberCard.name
).innerHTML;
return { imageUrl, name };
});
}
}
function downloadAsFile(fileContent, fileName, fileExtension) {
const hiddenElement = document.createElement("a");
hiddenElement.href = "data:attachment/text," + encodeURI(fileContent);
hiddenElement.target = "_blank";
hiddenElement.download = `${fileName}.${fileExtension}`;
hiddenElement.click();
}
function run() {
const slackScrapper = new SlackScrapper();
const members = slackScrapper.getAllMembers();
const csvContent = new CSVTransformer(members)
.withColumn("IMAGE_URL", (item) => item.imageUrl)
.withColumn("NAME", (item) => item.name)
.build();
downloadAsFile(csvContent, "slack-members", "csv");
}
run();
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment