diff --git a/index.ts b/index.ts index f7e8ee2..d8196d3 100644 --- a/index.ts +++ b/index.ts @@ -8,6 +8,20 @@ const app = new App({ signingSecret: process.env.SLACK_SIGNING_SECRET, }); +const whitelist: string[] = (() => { + try { + return require('./whitelist.json') + } catch (e) { + return [] + } +})(); + +function checkUserOk(user: UsersInfoResponse['user']) { + if (whitelist.includes(user!.id!)) return true + + return user!.is_admin || user!.is_owner || user!.is_primary_owner +} + const eligibilityCmd = async (ctx: any) => { await ctx.ack(); @@ -16,43 +30,52 @@ const eligibilityCmd = async (ctx: any) => { let userId = ctx.context.userId; let matchedBy = "no input" + const iUser = await ctx.client.users.info({ user: ctx.context.userId! }); + if ((match = text.match(/\<\@(.+)\|(.+)>/))) { - userId = match[1]; - matchedBy = "user mention" + if (!checkUserOk(iUser.user!)) { + matchedBy = "not allowed" + } else { + userId = match[1]; + matchedBy = "user mention" + } } else if (text) matchedBy = "invalid input" - const res = await fetch("https://identity.hackclub.com/api/external/check?slack_id=" + userId, { - headers: { - 'User-Agent': 'HackClubEligibilityBot/1.0 (ran by Loop / dainfloop)' - }, + const res = await fetch("https://verify.hackclub.dev/api/status", { + method: "POST", + headers: { 'content-type': 'application/json' }, + body: JSON.stringify({ + "slack_id": userId + }), redirect: "follow" }).then(res => res.json()) - if (res.result === "not_found") + if (res === `User ${userId} not found!`) return await ctx.respond({ response_type: 'ephemeral', - text: `${matchedBy !== "user mention" ? "You aren't" : `<@${userId}> isn't`} verified. ${matchedBy !== "user mention" ? `\nCheck out the to verify.` : ""}`, + text: `${matchedBy !== "user mention" ? "You aren't" : `<@${userId}> isn't`} verified and therefore aren't eligible for rewards from your program.${matchedBy !== "user mention" ? `\nCheck out the to verify.` : ""}${matchedBy == "not allowed" ? " (Only whitelisted users can check other people's verification statuses.)" : ""}`, unfurl_links: true }) - else if (res.result === "needs_submission") { + else if (res.status === "Insufficient") { return await ctx.respond({ response_type: 'ephemeral', - text: `${matchedBy !== "user mention" ? "You" : `<@${userId}>`} provided insufficient evidence of who ${matchedBy !== "user mention" ? "you" : "they"} are.${matchedBy !== "user mention" ? `\nCheck out the to re-verify.` : ""}`, + text: `${matchedBy !== "user mention" ? "You" : `<@${userId}>`} provided insufficient evidence that ${matchedBy !== "user mention" ? "you" : "they"} are a student.${matchedBy !== "user mention" ? `\nCheck out the to re-verify.` : ""}${matchedBy == "not allowed" ? " (Only whitelisted users can check other people's verification statuses.)" : ""}`, unfurl_links: true - }) + }) } - else if (res.result === "pending") { + else if (res.status === "Unknown") { return await ctx.respond({ response_type: 'ephemeral', - text: `${matchedBy !== "user mention" ? "Your verification" : `<@${userId}>'s verification`} has not been accepted yet.`, - }) + text: `${matchedBy !== "user mention" ? "Your verification" : `<@${userId}>'s verification`} has not been accepted yet.${matchedBy == "not allowed" ? " (Only whitelisted users can check other people's verification statuses.)" : ""}`, + unfurl_links: true + }) } - else if (res.result === "rejected") { + else if (res.status === "Ineligible") { if (matchedBy === "user mention") { return await ctx.respond({ response_type: 'ephemeral', @@ -61,15 +84,11 @@ const eligibilityCmd = async (ctx: any) => { } else { return await ctx.respond({ response_type: 'ephemeral', - text: `Your verification has been denied. If you believe this to be a mistake, please send a message in <#C092833JXKK>.` + text: `Your verification has been denied. If you believe this to be a mistake, please contact an admin of the program you are applying for.${matchedBy == "not allowed" ? " (Only whitelisted users can check other people's verification statuses.)" : ""},` }) } } - /** - * The sanctioned country status seems to have been deprecated in the Identity Vault. - * However, this piece of code is being kept for documentation purposes. - else if (res.status === "Sanctioned country") { if (matchedBy === "user mention") { return await ctx.respond({ @@ -81,21 +100,22 @@ const eligibilityCmd = async (ctx: any) => { response_type: 'ephemeral', text: `You live in a country that cannot have packages delivered to due to sanctions.${matchedBy == "not allowed" ? " (Only whitelisted users can check other people's verification statuses.)" : ""},` }) - } - } - */ - - else if (res.result === "verified_eligible") { - return await ctx.respond({ - response_type: 'ephemeral', - text: `${matchedBy !== "user mention" ? "You have verified your" : `<@${userId}> has verified their`} identity, and ${matchedBy !== "user mention" ? "are" : "is"} eligible for YSWS prizes.`, - }) + } } - else if (res.result === "verified_but_over_18") { + else { return await ctx.respond({ response_type: 'ephemeral', - text: `${matchedBy !== "user mention" ? "You have verified your" : `<@${userId}> has verified their`} identity, but since ${matchedBy !== "user mention" ? "you're" : "they're"} over 18, ${matchedBy !== "user mention" ? "you're" : "they're"} ineligible for YSWS prizes.`, + text: `${matchedBy !== "user mention" ? "You have verified your" : `<@${userId}> has verified their`} student status, and ${matchedBy !== "user mention" ? "are" : "is"} ${res.status}.${matchedBy == "not allowed" ? " (Only whitelisted users can check other people's verification statuses.)" : ""}`, + blocks: [ + { + type: 'section', + text: { + type: 'mrkdwn', + text: `${matchedBy !== "user mention" ? "You have verified your" : `<@${userId}> has verified their`} student status, and ${matchedBy !== "user mention" ? "are" : "is"} *${res.status}*.${matchedBy == "not allowed" ? " (Only whitelisted users can check other people's verification statuses.)" : ""}` + } + } + ] }) } } diff --git a/package-lock.json b/package-lock.json index 49f8e14..b6444f6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -297,16 +297,16 @@ } }, "node_modules/@slack/web-api": { - "version": "7.3.4", - "resolved": "https://registry.npmjs.org/@slack/web-api/-/web-api-7.3.4.tgz", - "integrity": "sha512-KwLK8dlz2lhr3NO7kbYQ7zgPTXPKrhq1JfQc0etJ0K8LSJhYYnf8GbVznvgDT/Uz1/pBXfFQnoXjrQIOKAdSuw==", + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/@slack/web-api/-/web-api-7.8.0.tgz", + "integrity": "sha512-d4SdG+6UmGdzWw38a4sN3lF/nTEzsDxhzU13wm10ejOpPehtmRoqBKnPztQUfFiWbNvSb4czkWYJD4kt+5+Fuw==", "license": "MIT", "dependencies": { "@slack/logger": "^4.0.0", "@slack/types": "^2.9.0", "@types/node": ">=18.0.0", "@types/retry": "0.12.0", - "axios": "^1.7.4", + "axios": "^1.7.8", "eventemitter3": "^5.0.1", "form-data": "^4.0.0", "is-electron": "2.2.2", @@ -561,9 +561,9 @@ } }, "node_modules/axios": { - "version": "1.7.7", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz", - "integrity": "sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==", + "version": "1.7.9", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.9.tgz", + "integrity": "sha512-LhLcE7Hbiryz8oMDdDptSrWowmB4Bl6RCt6sIJKpRB4XtVf0iEgewX3au/pJqm+Py1kCASkb/FFKjxQaLtxJvw==", "license": "MIT", "dependencies": { "follow-redirects": "^1.15.6",