hacker news alerts in slack (incessant pings if you make front page)
1import { eq } from "drizzle-orm";
2import { db, slackApp } from "../../index";
3import { users as usersTable } from "../../libs/schema";
4import { generatePassphrase } from "../../libs/words";
5import { getUser } from "../../libs/hackernews";
6
7// Helper functions for each command action
8async function handleLinkRequest(
9 userId: string,
10 userInput: string | null,
11): Promise<string> {
12 let hnUsername = userInput;
13
14 // Extract username from URL if provided
15 if (userInput?.includes("news.ycombinator.com/user?id=")) {
16 try {
17 const cleanedInput = userInput.replace(/[<>]/g, "");
18 const username = new URL(cleanedInput).searchParams.get("id");
19 if (username) hnUsername = username;
20 } catch (e) {
21 console.log("Failed to parse URL, using raw input", e);
22 }
23 }
24
25 if (!hnUsername) {
26 return "Please provide your Hacker News username: `/hn-alerts-link your_username`";
27 }
28
29 const verificationPhrase = generatePassphrase(3);
30
31 await db.insert(usersTable).values({
32 id: userId,
33 hackernewsUsername: hnUsername,
34 challenge: verificationPhrase,
35 });
36
37 return `Please verify your Hacker News username: <https://news.ycombinator.com/user?id=${hnUsername}|\`${hnUsername}\`> by adding the verification phrase: \`${verificationPhrase}\`. When you're done, type \`/hn-alerts-link verify\` to complete the process.`;
38}
39
40async function handleVerify(
41 userId: string,
42 hackernewsUsername: string,
43 challenge: string,
44): Promise<string> {
45 const res = await getUser(hackernewsUsername as string).then((user) =>
46 user?.about?.includes(challenge as string),
47 );
48
49 if (!res) {
50 return `Your Hacker News account is not verified. Add \`${challenge}\` to your <https://news.ycombinator.com/user?id=${hackernewsUsername}|profile>.`;
51 }
52
53 await db
54 .update(usersTable)
55 .set({ verified: true })
56 .where(eq(usersTable.id, userId));
57
58 return "Your Hacker News account has been verified :yay:";
59}
60
61async function handleUnlink(userId: string): Promise<string> {
62 await db.delete(usersTable).where(eq(usersTable.id, userId));
63
64 return "Your Hacker News account has been unlinked successfully.";
65}
66
67function handleHelp(): string {
68 return (
69 "Available commands:\n" +
70 "• `/hn-alerts-link your_username` - Link your account\n" +
71 "• `/hn-alerts-link verify` - Verify your Hacker News account\n" +
72 "• `/hn-alerts-link unlink` - Remove your linked account\n" +
73 "• `/hn-alerts-link help` - Show this help message"
74 );
75}
76
77export { handleVerify, handleUnlink, handleHelp, handleLinkRequest };