aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuca Matei Pintilie <lucafulger@gmail.com>2022-07-03 12:49:52 +0000
committerLuca Matei Pintilie <lucafulger@gmail.com>2022-07-03 12:49:52 +0000
commit439284472ddc7825728159f03b727667f5a21969 (patch)
tree9e6b7643c9607f1aa6e3f0ee8c6a31341976e8aa
parent16e6131b2a5ccd183a2ec4037cf38e7f87197647 (diff)
downloadspeedrunbot-slash-439284472ddc7825728159f03b727667f5a21969.tar
speedrunbot-slash-439284472ddc7825728159f03b727667f5a21969.tar.gz
speedrunbot-slash-439284472ddc7825728159f03b727667f5a21969.tar.bz2
speedrunbot-slash-439284472ddc7825728159f03b727667f5a21969.tar.lz
speedrunbot-slash-439284472ddc7825728159f03b727667f5a21969.tar.xz
speedrunbot-slash-439284472ddc7825728159f03b727667f5a21969.tar.zst
speedrunbot-slash-439284472ddc7825728159f03b727667f5a21969.zip
Add BROKEN posts command
-rwxr-xr-xsrc/srcom/posts.ts134
-rw-r--r--src/srcom/slash_commands.ts19
-rw-r--r--tests/srcom/posts.test.ts13
3 files changed, 166 insertions, 0 deletions
diff --git a/src/srcom/posts.ts b/src/srcom/posts.ts
new file mode 100755
index 0000000..c7aba2f
--- /dev/null
+++ b/src/srcom/posts.ts
@@ -0,0 +1,134 @@
+#!/usr/bin/env -S deno run --allow-net=www.speedrun.com --allow-env=NO_COLOR --no-check
+import { Format } from "./fmt.ts";
+import { CommandError, getUser } from "./utils.ts";
+import type { Opts } from "./utils.ts";
+
+export const dateFormat = Intl.DateTimeFormat("en-uk", {
+ day: "numeric",
+ month: "long",
+ year: "numeric",
+ timeZone: "Europe/London",
+}).format;
+
+export interface Posts {
+ game: number;
+ site: number;
+ secret: number;
+ total: number;
+}
+
+// Strongly copied from
+// https://github.com/Mango0x45/speedrunbot-plusplus/blob/38a7231805c966d55b1e23cd7e94a7ddd042088e/src/srcom/posts.sh
+export async function posts(
+ username: string,
+ { outputType }: { outputType?: "object" },
+): Promise<Posts>;
+export async function posts(
+ username: string,
+ { outputType }: Opts,
+): Promise<string>;
+export async function posts(
+ username: string,
+ { outputType = "markdown" }: Opts = {},
+): Promise<string | Posts> {
+ const fmt = new Format(outputType);
+ const output: string[] = [];
+
+ const user = await getUser(username);
+ if (!user) throw new CommandError(`No user with the username "${username}"`);
+
+ const userAllPostsRes = await fetch(
+ `https://www.speedrun.com/${user.names.international}/allposts`,
+ );
+ const userAllPostsText = await userAllPostsRes.text();
+ const numberOfPages = parseInt(
+ // @ts-ignore the regex will only match numbers
+ // And we check below if it's NaN
+ userAllPostsText.match(/Page 1 of (\d+)+/)?.[1],
+ );
+ const fetchPageTasks: Promise<string>[] = [];
+
+ if (
+ userAllPostsText.includes(
+ "This user has not posted anything on the forum yet.",
+ )
+ ) {
+ return "This user has not posted anything on the forum yet.";
+ } else if (isNaN(numberOfPages)) {
+ fetchPageTasks.push(
+ fetch(
+ `https://www.speedrun.com/${user.names.international}/allposts`,
+ ).then((res) => res.text()),
+ );
+ } else {
+ for (let i = 0; i < numberOfPages; i++) {
+ fetchPageTasks.push(
+ fetch(
+ `https://www.speedrun.com/${user.names.international}/allposts/${i}`,
+ ).then((res) => res.text()),
+ );
+ }
+ }
+
+ const results = (await Promise.all(fetchPageTasks)).map((page) => {
+ const match = page.match(
+ /<\s*a href='\/(.*?)\/forum'[^>]*>(.*?)<\s*\/\s*a>/g,
+ );
+ const sitePattern =
+ /supporter|news|introductions|speedrunning|streaming_recording_equipment|tournaments_and_races|talk|the_site/;
+ let game = 0;
+ let site = 0;
+
+ if (match) {
+ for (const link of match) {
+ if (sitePattern.test(link)) site++;
+ else game++;
+ }
+ }
+
+ return {
+ game,
+ site,
+ };
+ });
+
+ const userInfoRes = await fetch(
+ `https://www.speedrun.com/user/${user.names.international}/info`,
+ );
+ const userInfoText = await userInfoRes.text();
+
+ // @ts-ignore I don't think this is possible to fail
+ const total = parseInt(userInfoText.match(/.*Posts:[^0-9]*([0-9]*).*/)?.[1]);
+ let game = 0;
+ let site = 0;
+
+ for (const result of results) {
+ game += result.game;
+ site += result.site;
+ }
+
+ const secret = total - site - game;
+
+ if (outputType === "object") {
+ return {
+ game,
+ site,
+ secret,
+ total,
+ };
+ }
+
+ output.push(`${fmt.bold("Posts")}: ${user.names.international}`);
+ output.push(`Site Forums: ${site}`);
+ output.push(`Game Forums: ${game}`);
+ if (secret) output.push(`Secret Forums: ${secret}`);
+ output.push(`Total: ${total}`);
+
+ return output.join("\n");
+}
+
+export default posts;
+
+if (import.meta.main) {
+ console.log(await posts(Deno.args[0], { outputType: "terminal" }));
+}
diff --git a/src/srcom/slash_commands.ts b/src/srcom/slash_commands.ts
index d4ed885..762461c 100644
--- a/src/srcom/slash_commands.ts
+++ b/src/srcom/slash_commands.ts
@@ -12,6 +12,7 @@ import {
} from "../../deps_server.ts";
import { games } from "./games.ts";
+import { posts } from "./posts.ts";
import { examined } from "./examined.ts";
import { examinedLeaderboard } from "./examined_leaderboard.ts";
import { categories } from "./categories.ts";
@@ -77,6 +78,16 @@ export const commands: SlashCommandPartial[] = [
],
},
{
+ name: "posts",
+ description: "See how many posts a player has posted on the site.",
+ options: [
+ {
+ ...srcUser,
+ required: true,
+ },
+ ],
+ },
+ {
name: "mod-count",
description: "See how many games and series a user moderates.",
options: [
@@ -483,6 +494,14 @@ export class SpeedrunCom extends ApplicationCommandsModule {
);
}
+ @slash()
+ async posts(i: ApplicationCommandInteraction) {
+ await sendCommand(
+ i,
+ (i) => posts(i.option("username"), { outputType: "markdown" }),
+ );
+ }
+
@slash("mod-count")
async modCount(i: ApplicationCommandInteraction) {
await sendCommand(
diff --git a/tests/srcom/posts.test.ts b/tests/srcom/posts.test.ts
new file mode 100644
index 0000000..b111c17
--- /dev/null
+++ b/tests/srcom/posts.test.ts
@@ -0,0 +1,13 @@
+import { assertEquals } from "../../deps_testing.ts";
+import { posts } from "../../src/srcom/posts.ts";
+
+
+Deno.test("Get user posts by username", async () => {
+ const res = await posts("1", { outputType: "plain" });
+ const expected = `Posts: 1
+Site Forums: 606
+Game Forums: 774
+Secret Forums: 1365
+Total: 1365`;
+ assertEquals(res, expected);
+});