diff --git a/packages/kol.js/package.json b/packages/kol.js/package.json index f26c59f..a8ea784 100644 --- a/packages/kol.js/package.json +++ b/packages/kol.js/package.json @@ -30,6 +30,7 @@ "tough-cookie": "^4.1.4", "ts-dedent": "^2.2.0", "typed-emitter": "^2.1.0", + "typescript-memoize": "^1.1.1", "xpath": "^0.0.34" } } diff --git a/packages/kol.js/src/Client.test.ts b/packages/kol.js/src/Client.test.ts index 9126824..11f71d8 100644 --- a/packages/kol.js/src/Client.test.ts +++ b/packages/kol.js/src/Client.test.ts @@ -204,3 +204,44 @@ describe("Familiars", () => { expect(familiars).toHaveLength(206); }); }); + +describe("Raffle", () => { + it("can fetch the current raffle", async () => { + text.mockResolvedValueOnce(await loadFixture(__dirname, "raffle.html")); + text.mockResolvedValueOnce(""); + text.mockResolvedValueOnce(""); + text.mockResolvedValueOnce(""); + text.mockResolvedValueOnce(""); + + const raffle = await client.getRaffle(); + + expect(raffle).toMatchObject({ + today: { + first: 1, + second: 2, + }, + yesterday: [ + { + player: { id: 809337, name: "Collective Consciousness" }, + item: 3, + tickets: 3333, + }, + { + player: { id: 852958, name: "Ryo_Sangnoir" }, + item: 4, + tickets: 1011, + }, + { + player: { id: 1765063, name: "SSpectre_Karasu" }, + item: 4, + tickets: 1000, + }, + { + player: { id: 1652370, name: "yueli7" }, + item: 4, + tickets: 2040, + }, + ], + }); + }); +}); diff --git a/packages/kol.js/src/Client.ts b/packages/kol.js/src/Client.ts index 45b633b..199b4cc 100644 --- a/packages/kol.js/src/Client.ts +++ b/packages/kol.js/src/Client.ts @@ -16,6 +16,7 @@ import { import { PlayerCache } from "./Cache.js"; import { CookieJar } from "tough-cookie"; import got, { OptionsOfJSONResponseBody, OptionsOfTextResponseBody } from "got"; +import { Memoize } from "typescript-memoize"; type TypedEmitter = TypedEventEmitter.default; @@ -510,4 +511,43 @@ export class Client extends (EventEmitter as unknown as new () => TypedEmitter { + const page = await this.fetchText("desc_item.php", { + searchParams: { + whichitem: descId, + }, + }); + return Number(page.match(//)?.[1] ?? -1); + } + + async getRaffle() { + const page = await this.fetchText("raffle.php"); + const today = page.matchAll( + /(?:First|Second) Prize:<\/td>.*?descitem\((\d+)\)/g, + ); + const [first, second] = await Promise.all( + today + ? [...today].map(async (p) => await this.descIdToId(Number(p[1]))) + : [null, null], + ); + const winners = page.matchAll( + /(.*?) \(#(\d+)\).*?descitem\((\d+)\).*?([\d,]+)<\/td><\/tr>/g, + ); + const yesterday = await Promise.all( + winners + ? [...winners].map(async (w) => ({ + player: new Player(this, Number(w[2]), w[1]), + item: await this.descIdToId(Number(w[3])), + tickets: Number(w[4].replace(",", "")), + })) + : [], + ); + + return { + today: { first, second }, + yesterday, + }; + } } diff --git a/packages/kol.js/src/Player.test.ts b/packages/kol.js/src/Player.test.ts index b68c0c1..7c928dc 100644 --- a/packages/kol.js/src/Player.test.ts +++ b/packages/kol.js/src/Player.test.ts @@ -41,8 +41,6 @@ describe("Player searching", () => { expectNotNull(player); - console.log(player); - expect(player.id).toBe(1046951); // Learns correct capitalisation expect(player.name).toBe("Beldur"); diff --git a/packages/kol.js/src/__fixtures__/raffle.html b/packages/kol.js/src/__fixtures__/raffle.html new file mode 100644 index 0000000..214714f --- /dev/null +++ b/packages/kol.js/src/__fixtures__/raffle.html @@ -0,0 +1,41 @@ + + + + + + + + + + + +
Raffle House
Greetings, Adventurer, and welcome to our Raffle House, which is completely and totally legitimate and fully-licensed by the Council of Loathing.

Here's how it works: you buy some raffle tickets, and every day (at rollover) we'll draw one to see who wins our Fabulous Prize, which will be delivered to you in one of our special packages. Tickets are non-transferrable, but we will accept tickets from Hagnk's if you should ascend before the drawing.

All proceeds will be donated to an unspecified but very worthy charity of our choosing. So, how many tickets do you want?

Today's Raffle Prize:
First Prize:maypole miniature gravy-covered maypole
Second Prize:vcase Doll Moll violin case
1 first prize lot and 3 second prize lots are available. One prize lot per winner. All ticket sales are final. Void where prohibited by law. Part of a complete breakfast.

You haven't bought any tickets for today's raffle.

Winners of Yesterday's Raffle:

NamePrizeTickets
Purchased
Collective Consciousness (#809337) Discontent™ Winter Garden Catalog  3,333
Ryo_Sangnoir (#852958) Colera Peste Nebbiolo  1,011
SSpectre_Karasu (#1765063) Colera Peste Nebbiolo  1,000
yueli7 (#1652370) Colera Peste Nebbiolo  2,040
Buy Raffle Tickets:
raffle ticket10,000 Meat

Go back to Bordertown

+ \ No newline at end of file diff --git a/packages/kol.js/tsconfig.json b/packages/kol.js/tsconfig.json index 4c1005f..d65570a 100644 --- a/packages/kol.js/tsconfig.json +++ b/packages/kol.js/tsconfig.json @@ -3,6 +3,7 @@ "target": "ESNext", "module": "NodeNext", "esModuleInterop": true, + "experimentalDecorators": true, "forceConsistentCasingInFileNames": true, "strict": true, "skipLibCheck": true, diff --git a/yarn.lock b/yarn.lock index a3c6547..23404e9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7772,6 +7772,7 @@ __metadata: ts-dedent: "npm:^2.2.0" typed-emitter: "npm:^2.1.0" typescript: "npm:^5.5.3" + typescript-memoize: "npm:^1.1.1" vitest: "npm:^1.6.0" xpath: "npm:^0.0.34" languageName: unknown