From 48222309cd810c09b35b8b7925058441511ca199 Mon Sep 17 00:00:00 2001 From: HumanoidSandvichDispenser Date: Wed, 29 Apr 2026 16:17:24 -0700 Subject: [PATCH] feature: add answer endpoints --- src/answer/index.ts | 50 ++++++++++++++++++++++++++++++++++--- src/answer/types.test.ts | 49 ++++++++++++++++++++++++++++++++++++ src/answer/types.ts | 54 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 149 insertions(+), 4 deletions(-) create mode 100644 src/answer/types.test.ts diff --git a/src/answer/index.ts b/src/answer/index.ts index bbfa6c2..b6b7303 100644 --- a/src/answer/index.ts +++ b/src/answer/index.ts @@ -1,8 +1,17 @@ -import { DismissAction, QuestionFetchResponse } from "./types"; +import { + AnswerDismissResponse, + AnswerPollVoteResponse, + AnswerQueueQuestionResponse, + AnswerReplyResponse, + DismissAction, + QuestionFetchResponse, +} from "./types"; import { Module } from "../module"; -import { TCResponse } from "../types"; export class AnswerModule extends Module { + /** + * Fetches the next unanswered question. + */ public async fetchNext() { return await this.client._call( QuestionFetchResponse, @@ -11,9 +20,12 @@ export class AnswerModule extends Module { ); } + /** + * Dismisses a question with the provided action. + */ public async dismissQuestion(questionId: number, action: DismissAction) { return await this.client._call( - TCResponse, + AnswerDismissResponse, "answer.dismissquestion", { questionId, @@ -22,9 +34,12 @@ export class AnswerModule extends Module { ); } + /** + * Submits a poll vote for a question. + */ public async pollVote(questionId: number, optionNum: number) { return await this.client._call( - TCResponse, + AnswerPollVoteResponse, "answer.pollvote", { questionId, @@ -32,4 +47,31 @@ export class AnswerModule extends Module { } ); } + + /** + * Queues a question to be asked later. + */ + public async queueQuestion(questionId: number) { + return await this.client._call( + AnswerQueueQuestionResponse, + "answer.queuequestion", + { + questionId, + } + ); + } + + /** + * Replies to a question. + */ + public async reply(questionId: number, text: string) { + return await this.client._call( + AnswerReplyResponse, + "answer.reply", + { + questionId, + text, + } + ); + } } diff --git a/src/answer/types.test.ts b/src/answer/types.test.ts new file mode 100644 index 0000000..c85d3fc --- /dev/null +++ b/src/answer/types.test.ts @@ -0,0 +1,49 @@ +import { describe, expect, it } from "vitest"; +import { AnswerQueueQuestionResponse, AnswerReplyResponse } from "./types"; +import { TCResponseRaw } from "../types"; + +describe("answer types", () => { + it("should parse AnswerReplyResponse", () => { + const response: TCResponseRaw = { + ok: true, + id: 2254111, + time: 1753856495, + text: "Hey you, name me a black game character.", + }; + + const constructed = new AnswerReplyResponse(response); + + expect(constructed.ok).toBe(true); + expect(constructed.id).toBe(2254111); + expect(constructed.time).toBe(1753856495); + expect(constructed.text).toBe("Hey you, name me a black game character."); + }); + + it("should parse AnswerQueueQuestionResponse with poll", () => { + const response: TCResponseRaw = { + ok: true, + id: 2266300, + time: 1775463826, + text: "[USER SATISFACTION SURVEY]", + author: "user64837", + poll: { + answered: false, + options: [ + { text: "1 (terrible)", color: "ff0000" }, + { text: "5 (great)", color: "ff0000" }, + ], + }, + }; + + const constructed = new AnswerQueueQuestionResponse(response); + + expect(constructed.ok).toBe(true); + expect(constructed.id).toBe(2266300); + expect(constructed.time).toBe(1775463826); + expect(constructed.text).toBe("[USER SATISFACTION SURVEY]"); + expect(constructed.author).toBe("user64837"); + expect(constructed.poll?.answered).toBe(false); + expect(constructed.poll?.options).toHaveLength(2); + expect(constructed.poll?.options[0].text).toBe("1 (terrible)"); + }); +}); diff --git a/src/answer/types.ts b/src/answer/types.ts index 530b79e..76da090 100644 --- a/src/answer/types.ts +++ b/src/answer/types.ts @@ -1,5 +1,59 @@ import { TCResponse, TCResponseRaw } from "../types"; +/** + * Response for answer.reply. + */ +export class AnswerReplyResponse extends TCResponse { + public id: number; + public time: number; + public text: string; + + public constructor(res: TCResponseRaw) { + super(res); + this.id = res["id"]; + this.time = res["time"]; + this.text = res["text"]; + } +} + +/** + * Response for answer.queuequestion. + */ +export class AnswerQueueQuestionResponse extends TCResponse { + public id: number; + public time: number; + public text: string; + public author?: string; + public poll?: Poll; + + public constructor(res: TCResponseRaw) { + super(res); + this.id = res["id"]; + this.time = res["time"]; + this.text = res["text"]; + this.author = res["author"]; + this.poll = res["poll"]; + } +} + +/** + * Response for answer.dismissquestion. + */ +export class AnswerDismissResponse extends TCResponse { + public constructor(res: TCResponseRaw) { + super(res); + } +} + +/** + * Response for answer.pollvote. + */ +export class AnswerPollVoteResponse extends TCResponse { + public constructor(res: TCResponseRaw) { + super(res); + } +} + export class QuestionFetchResponse extends TCResponse { id: number; time: number;