Skip to content

Commit

Permalink
Merge pull request #4 from kcoderhtml/Add-10daysinpublic-leaderboard-…
Browse files Browse the repository at this point in the history
…route

Add 10daysinpublic leaderboard route
  • Loading branch information
taciturnaxolotl authored Feb 16, 2024
2 parents 2d0a977 + a453d5d commit 11eb1c3
Show file tree
Hide file tree
Showing 2 changed files with 108 additions and 0 deletions.
10 changes: 10 additions & 0 deletions index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { getPostSummaries, getPostDetail } from "./utils/vrite.ts";
import { getMessage } from "./utils/files.ts";
import { streamData } from "./utils/streaming.ts";
import { getGist } from "./utils/apis.ts";
import { get10DaysLeaderboard } from "./utils/slack.ts";

const app = express();
const port = 3000;
Expand Down Expand Up @@ -47,6 +48,15 @@ app.get("/g/:id", async (req, res) => {
streamData(req, res, gist);
});

// #10daysinpublic leaderboard
app.get("/s/10days", async (req, res) => {
const leaderboard = await get10DaysLeaderboard(
new Date("2024-02-15"),
new Date("2024-02-30"),
);
streamData(req, res, leaderboard);
});

// Create server
const server = http.createServer(app);

Expand Down
98 changes: 98 additions & 0 deletions utils/slack.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
interface post {
timestamp: Date;
content: string;
}

interface user {
user: string;
posts: post[];
}

// Function to generate the leaderboard table
function generateLeaderboardTable(users: user[]): string {
const uniqueTimestamps = Array.from(
new Set(
users.flatMap((u) =>
u.posts.map((p) => p.timestamp.toISOString().split("T")[0]),
),
),
).sort();

// Calculate the maximum username length
const maxUsernameLength = Math.max(...users.map((user) => user.user.length));

// Calculate the length of each date
const dateLengths = uniqueTimestamps.map(
(timestamp, index) => timestamp.length,
);

const headerRow = `| User${" ".repeat(maxUsernameLength - 4)} |${uniqueTimestamps.map((timestamp, index) => ` ${timestamp} `).join("|")}|`;
const separatorRow = `|${"-".repeat(maxUsernameLength + 2)}|${dateLengths.map((length) => "-".repeat(length + 2)).join("|")}|`;

const bodyRows = users.map((user) => {
const postsByDate = new Set(
user.posts.map((post) => post.timestamp.toISOString().split("T")[0]),
);

const userCell = ` ${user.user}${" ".repeat(maxUsernameLength - user.user.length)} `;
const cells = uniqueTimestamps.map((timestamp, index) =>
postsByDate.has(timestamp)
? " ✓".padEnd(dateLengths[index] + 2)
: " ".repeat(dateLengths[index] + 2),
);

return `|${userCell}|${cells.join("|")}|`;
});

return [
separatorRow,
headerRow,
separatorRow,
...bodyRows,
separatorRow,
].join("\n");
}

export async function get10DaysLeaderboard(start: Date, end: Date) {
const users: user[] = [];

const response = await fetch(
"https://scrapbook.hackclub.com/api/r/10daysinpublic",
);

const posts = await response.json();

posts.forEach((post: any) => {
const timestampAdjusted = new Date();
timestampAdjusted.setTime(
(post.timestamp + post.user.timezoneOffset) * 1000,
);

if (
timestampAdjusted.getTime() < start.getTime() ||
timestampAdjusted.getTime() > end.getTime()
) {
return;
}

// add user to the list if they don't exist
// otherwise, add the post to the user's posts
const userIndex = users.findIndex((u) => u.user === post.user.username);
if (userIndex === -1) {
users.push({
user: post.user.username,
posts: [{ timestamp: timestampAdjusted, content: post.text }],
});
} else {
users[userIndex].posts.push({
timestamp: timestampAdjusted,
content: post.text,
});
}
});

// display the leaderboard in markdown format
const leaderboardFormatted = `# 10 Days in Public Leaderboard from ${start.toISOString().split("T")[0]} to ${end.toISOString().split("T")[0]}\nGood Luck and have fun!\n\n${generateLeaderboardTable(users)}`;

return leaderboardFormatted;
}

0 comments on commit 11eb1c3

Please sign in to comment.