feature: add answer endpoints

master
John Montagu, the 4th Earl of Sandvich 2026-04-29 16:17:24 -07:00
parent b59b72b021
commit 48222309cd
Signed by: sandvich
GPG Key ID: 9A39BE37E602B22D
3 changed files with 149 additions and 4 deletions

View File

@ -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,
}
);
}
}

View File

@ -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)");
});
});

View File

@ -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;