mirror of
https://github.com/System-End/slack-end.git
synced 2026-04-19 22:05:10 +00:00
feat: slack lb
This commit is contained in:
parent
011f2da2eb
commit
d9e107fe8a
6 changed files with 197 additions and 2 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
|
@ -145,3 +145,5 @@ tiktok.json
|
|||
assets/list_of_slack_users.json
|
||||
assets/dice/frames
|
||||
t5.ts
|
||||
s.csv
|
||||
slack-users*
|
||||
2
TODO.md
2
TODO.md
|
|
@ -5,3 +5,5 @@ _this is a high seas project..._
|
|||
- [ ] finish hangman
|
||||
- [x] finish blind mail
|
||||
- [ ] finish `docs/` and zeon canvas
|
||||
- [ ] solve memory issues (maybe just maybe, graph it)
|
||||
- - OR MIGRATE TO NOCODB HOLY
|
||||
|
|
@ -5,9 +5,10 @@
|
|||
"author": "Saahil <neon@saahild.com>",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"start": "ts-node src/index.ts"
|
||||
"start": "NODE_OPTIONS=\"--max-old-space-size=4096\" ts-node src/index.ts"
|
||||
},
|
||||
"dependencies": {
|
||||
"@js-temporal/polyfill": "^0.4.4",
|
||||
"@sentry/node": "^8.41.0",
|
||||
"@sentry/profiling-node": "^8.41.0",
|
||||
"@slack/bolt": "^3.21.2",
|
||||
|
|
|
|||
121
src/modules/getSlackAnalytics.ts
Normal file
121
src/modules/getSlackAnalytics.ts
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
// sourced from skyfall :3
|
||||
import { Temporal } from "@js-temporal/polyfill";
|
||||
export enum Mode {
|
||||
Last30Days,
|
||||
LastYear,
|
||||
AdrianMethod,
|
||||
}
|
||||
export interface MemberActivity {
|
||||
user_id: string;
|
||||
team_id: string;
|
||||
username: string;
|
||||
is_primary_owner: boolean;
|
||||
is_owner: boolean;
|
||||
is_admin: boolean;
|
||||
is_restricted: boolean;
|
||||
is_ultra_restricted: boolean;
|
||||
is_invited_member: boolean;
|
||||
is_invited_guest: boolean;
|
||||
messages_posted_in_channel: number;
|
||||
reactions_added: number;
|
||||
days_active: number;
|
||||
days_active_desktop: number;
|
||||
days_active_android: number;
|
||||
days_active_ios: number;
|
||||
files_added_count: number;
|
||||
days_active_apps: number;
|
||||
// days_active_workflows: number;
|
||||
// days_active_slack_connect: number;
|
||||
// total_calls_count: number;
|
||||
// slack_calls_count: number;
|
||||
slack_huddles_count: number;
|
||||
// search_count: number;
|
||||
// is_billable_seat: boolean;
|
||||
messages_posted: number;
|
||||
date_claimed: number;
|
||||
date_last_active: number;
|
||||
date_last_active_ios: number;
|
||||
date_last_active_android: number;
|
||||
date_last_active_desktop: number;
|
||||
// slack_huddles_count: z.number().nonnegative(), Always 0 on non-Enterprise plans
|
||||
}
|
||||
export interface AnalyticsResult {
|
||||
ok: boolean;
|
||||
num_found: number;
|
||||
member_activity: MemberActivity[];
|
||||
}
|
||||
|
||||
|
||||
export async function fetchAnalyticsData(
|
||||
// username: string,
|
||||
xoxc: string,
|
||||
xoxd: string,
|
||||
workspace: string,
|
||||
mode: Mode = Mode.Last30Days
|
||||
): Promise<AnalyticsResult> {
|
||||
const formData = new FormData();
|
||||
formData.append("token", xoxc);
|
||||
if (mode === Mode.Last30Days) {
|
||||
// Last30Days handles only the last 30 days
|
||||
console.log(`[DEBUG] Fetching analytics data for the last 30 days.`);
|
||||
formData.append("date_range", "30d");
|
||||
} else {
|
||||
// For other modes (e.g., LastYear), calculate start and end dates
|
||||
const currentDate = Temporal.Now.plainDateISO();
|
||||
const oneWeekAgo = currentDate.subtract({ weeks: 1 });
|
||||
const startDate = oneWeekAgo.subtract({ years: 1 });
|
||||
|
||||
// Subtract 4 days from both startDate and oneWeekAgo
|
||||
const adjustedEndDate = oneWeekAgo.subtract({ days: 4 });
|
||||
const adjustedStartDate = startDate.subtract({ days: 4 });
|
||||
|
||||
const formattedEndDate = adjustedEndDate.toString();
|
||||
const formattedStartDate = adjustedStartDate.toString();
|
||||
|
||||
console.log(
|
||||
`[DEBUG] Fetching analytics data from ${formattedStartDate} to ${formattedEndDate}`
|
||||
);
|
||||
|
||||
formData.append("start_date", formattedStartDate);
|
||||
formData.append("end_date", formattedEndDate);
|
||||
}
|
||||
formData.append("count", "1");
|
||||
formData.append("sort_column", "messages_posted");
|
||||
formData.append("sort_direction", "desc");
|
||||
// formData.append("query", username);
|
||||
formData.append("count", "5000");
|
||||
|
||||
const authCookie = `d=${xoxd}`;
|
||||
const response = await fetch(
|
||||
`https://${workspace}.slack.com/api/admin.analytics.getMemberAnalytics`,
|
||||
{
|
||||
method: "POST",
|
||||
body: formData,
|
||||
headers: {
|
||||
Authority: `${workspace}.slack.com`,
|
||||
Cookie: authCookie, // We don't really need anything fancy here.
|
||||
},
|
||||
}
|
||||
);
|
||||
const text = await response.text();
|
||||
// console.log(text)
|
||||
const json = JSON.parse(text);
|
||||
// console.log(json)
|
||||
const data = json as AnalyticsResult;
|
||||
// if (!data.ok) {
|
||||
// throw new Error("Failed to fetch analytics data");
|
||||
// }
|
||||
// if (data.num_found > 1) {
|
||||
// console.warn(`[WARN] Found ${data.num_found} users`);
|
||||
// }
|
||||
// const member = data.member_activity.find(
|
||||
// (member) => member.username === username
|
||||
// );
|
||||
|
||||
// if (!member) {
|
||||
// throw new Error(`User ${username} not found`);
|
||||
// }
|
||||
|
||||
// return member;
|
||||
return data;
|
||||
}
|
||||
56
src/modules/slackLb.ts
Normal file
56
src/modules/slackLb.ts
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
import { MemberActivity } from "./getSlackAnalytics";
|
||||
export interface SlackDbEntry {
|
||||
msgCount: number;
|
||||
nonChannelMessages: number;
|
||||
userID: string;
|
||||
is_admin: boolean;
|
||||
is_guest: boolean;
|
||||
is_using_android: boolean;
|
||||
is_using_ios: boolean;
|
||||
is_using_desktop: boolean;
|
||||
daysActive: number;
|
||||
last_login: string;
|
||||
timeRecorded: number;
|
||||
}
|
||||
export function formatSlackBadge(entry: SlackDbEntry):string {
|
||||
let str = ""
|
||||
if(entry.is_admin) str += `:tw_shield: `
|
||||
if(entry.is_guest) str += `:eyes: `
|
||||
if(entry.is_using_android) str += `:android: `
|
||||
if(entry.is_using_ios) str += `:iphone: `
|
||||
if(entry.is_using_desktop) str += `:laptopparrot: `
|
||||
return str.trimEnd();
|
||||
}
|
||||
export function diffSlackLB(oldLB: SlackDbEntry[], newLB: SlackDbEntry[]) {
|
||||
const msgs = [];
|
||||
for (const entry of newLB) {
|
||||
const oldEntry = oldLB.find((e) => e.userID === entry.userID);
|
||||
if (!oldEntry) {
|
||||
msgs.push(
|
||||
`:yay: <@${entry.userID}> Welcome to the leaderboard joining us in #${
|
||||
newLB.indexOf(entry) + 1
|
||||
} place with 💬 \`${entry.msgCount}\` msgs. tags: ${formatSlackBadge(entry)}`,
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
const diff = entry.msgCount - oldEntry.msgCount;
|
||||
// console.log(diff, entry.msgCount, oldEntry.msgCount)
|
||||
let newRankMessage =
|
||||
newLB.indexOf(entry) !== oldLB.findIndex((e) => e.userID == entry.userID)
|
||||
? newLB.indexOf(entry) - oldLB.findIndex((e) => e.userID == entry.userID) > 0
|
||||
? `You have moved down to #${newLB.indexOf(entry) + 1} from #${oldLB.findIndex((e) => e.userID == entry.userID) + 1} -- diff of ${newLB.indexOf(entry) - oldLB.findIndex((e) => e.userID == entry.userID)}, o: ${oldLB.findIndex((e) => e.userID == entry.userID)}, n: ${newLB.indexOf(entry)} (debug)`
|
||||
: `You have moved up to #${newLB.indexOf(entry) + 1} from #${oldLB.findIndex((e) => e.userID == entry.userID) + 1} -- diff of ${newLB.indexOf(entry) - oldLB.findIndex((e) => e.userID == entry.userID)}, o: ${oldLB.findIndex((e) => e.userID == entry.userID)}, n: ${newLB.indexOf(entry)} (debug)`
|
||||
: ``;
|
||||
if (diff > 0) {
|
||||
msgs.push(
|
||||
`${newRankMessage ? (newRankMessage.includes("up") ? ":upvote:" : ":downvote:") : ""}:yay: ${entry.userID} (${formatSlackBadge(entry)}) You have gained \`${diff}\` 💬. ${newRankMessage ?? "No rank change"}`,
|
||||
);
|
||||
} else if (diff < 0) {
|
||||
msgs.push(
|
||||
`${newRankMessage ? (newRankMessage.includes("up") ? ":upvote:" : ":downvote:") : ""}:noooovanish: ${entry.userID} (${formatSlackBadge(entry)}) You lost \`${Math.abs(diff)}\` 💬. ${newRankMessage ?? "No rank change"}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
return msgs;
|
||||
}
|
||||
15
yarn.lock
15
yarn.lock
|
|
@ -27,6 +27,14 @@
|
|||
"@jridgewell/resolve-uri" "^3.0.3"
|
||||
"@jridgewell/sourcemap-codec" "^1.4.10"
|
||||
|
||||
"@js-temporal/polyfill@^0.4.4":
|
||||
version "0.4.4"
|
||||
resolved "https://registry.yarnpkg.com/@js-temporal/polyfill/-/polyfill-0.4.4.tgz#4c26b4a1a68c19155808363f520204712cfc2558"
|
||||
integrity sha512-2X6bvghJ/JAoZO52lbgyAPFj8uCflhTo2g7nkFzEQdXd/D8rEeD4HtmTEpmtGCva260fcd66YNXBOYdnmHqSOg==
|
||||
dependencies:
|
||||
jsbi "^4.3.0"
|
||||
tslib "^2.4.1"
|
||||
|
||||
"@mapbox/node-pre-gyp@^1.0.0", "@mapbox/node-pre-gyp@^1.0.11":
|
||||
version "1.0.11"
|
||||
resolved "https://registry.yarnpkg.com/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz#417db42b7f5323d79e93b34a6d7a2a12c0df43fa"
|
||||
|
|
@ -2765,6 +2773,11 @@ iterate-value@^1.0.2:
|
|||
es-get-iterator "^1.0.2"
|
||||
iterate-iterator "^1.0.1"
|
||||
|
||||
jsbi@^4.3.0:
|
||||
version "4.3.0"
|
||||
resolved "https://registry.yarnpkg.com/jsbi/-/jsbi-4.3.0.tgz#b54ee074fb6fcbc00619559305c8f7e912b04741"
|
||||
integrity sha512-SnZNcinB4RIcnEyZqFPdGPVgrg2AcnykiBy0sHVJQKHYeaLUvi3Exj+iaPpLnFVkDPZIV4U0yvgC9/R4uEAZ9g==
|
||||
|
||||
jsep@^1.3.8:
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/jsep/-/jsep-1.4.0.tgz#19feccbfa51d8a79f72480b4b8e40ce2e17152f0"
|
||||
|
|
@ -4063,7 +4076,7 @@ tslib@^1.9.0:
|
|||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00"
|
||||
integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==
|
||||
|
||||
tslib@^2.4.0, tslib@^2.6.2:
|
||||
tslib@^2.4.0, tslib@^2.4.1, tslib@^2.6.2:
|
||||
version "2.8.1"
|
||||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f"
|
||||
integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue