add request batching and drawing module
parent
cca7ca2cd7
commit
9e638d94f1
100
src/client.ts
100
src/client.ts
|
@ -1,7 +1,15 @@
|
|||
import { MethodCall, TCJSONResponse, TCResponse, TCResponseRaw } from "./types";
|
||||
import { AskModule } from "./ask";
|
||||
import { MessagesModule } from "./messages";
|
||||
import { ForumModule } from "./forum";
|
||||
import { MethodCall, TCJSONResponse, TCResponse, TCResponseRaw } from "./types";
|
||||
import { DrawingModule } from "./drawing";
|
||||
|
||||
interface QueuedCall {
|
||||
methodCall: MethodCall;
|
||||
creator: new(r: TCResponseRaw) => TCResponse;
|
||||
resolve: (value: any) => void;
|
||||
reject: (reason: any) => void;
|
||||
}
|
||||
|
||||
/**
|
||||
* Client for Two Cans & String API.
|
||||
|
@ -13,6 +21,10 @@ export class Client {
|
|||
#messages: MessagesModule;
|
||||
#ask: AskModule;
|
||||
#forum: ForumModule;
|
||||
#drawing: DrawingModule;
|
||||
|
||||
#requestQueue: QueuedCall[] = [];
|
||||
#isBatching: boolean = false;
|
||||
|
||||
/** @internal */
|
||||
public _cache: { [key: string]: any; } = { };
|
||||
|
@ -33,6 +45,22 @@ export class Client {
|
|||
return this.#forum;
|
||||
}
|
||||
|
||||
public get drawing(): DrawingModule {
|
||||
return this.#drawing;
|
||||
}
|
||||
|
||||
public get isBatching(): boolean {
|
||||
return this.#isBatching;
|
||||
}
|
||||
|
||||
public set isBatching(value: boolean) {
|
||||
if (value) {
|
||||
this.beginBatch();
|
||||
} else {
|
||||
this.endBatch();
|
||||
}
|
||||
}
|
||||
|
||||
public constructor(auth?: string) {
|
||||
this.auth = auth;
|
||||
|
||||
|
@ -40,6 +68,7 @@ export class Client {
|
|||
this.#messages = new MessagesModule(this);
|
||||
this.#ask = new AskModule(this);
|
||||
this.#forum = new ForumModule(this);
|
||||
this.#drawing = new DrawingModule(this);
|
||||
}
|
||||
|
||||
//public login(username: string, password: string) {
|
||||
|
@ -53,7 +82,7 @@ export class Client {
|
|||
* @param args The arguments to pass to the API method.
|
||||
* @internal
|
||||
*/
|
||||
public async _call<T extends TCResponse>(
|
||||
public _call<T extends TCResponse>(
|
||||
creator: new(r: TCResponseRaw) => T,
|
||||
methodName: string,
|
||||
args: { [key: string]: any }
|
||||
|
@ -64,19 +93,82 @@ export class Client {
|
|||
payload: args,
|
||||
};
|
||||
|
||||
if (this.#isBatching) {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.#requestQueue.push({
|
||||
methodCall,
|
||||
creator,
|
||||
resolve,
|
||||
reject,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
const body = {
|
||||
auth: this.auth,
|
||||
requests: [methodCall],
|
||||
};
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
this.fetch(body)
|
||||
.then((res) => {
|
||||
const rawResponse: TCResponseRaw = {
|
||||
ok: res?.ok ?? false,
|
||||
...res?.responses[0],
|
||||
};
|
||||
|
||||
resolve(new creator(rawResponse));
|
||||
})
|
||||
.catch((reason) => reject(reason));
|
||||
});
|
||||
/*
|
||||
const res = await this.fetch(body);
|
||||
|
||||
const rawResponse: TCResponseRaw = {
|
||||
ok: res?.ok ?? false,
|
||||
...res?.responses[0],
|
||||
} as T;
|
||||
|
||||
|
||||
return new creator(rawResponse);
|
||||
*/
|
||||
}
|
||||
|
||||
public beginBatch(): void {
|
||||
this.#isBatching = true;
|
||||
}
|
||||
|
||||
public endBatch(process = true): void {
|
||||
this.#isBatching = false;
|
||||
if (process) {
|
||||
this.processBatch();
|
||||
}
|
||||
}
|
||||
|
||||
public processBatch(): void {
|
||||
const methodCalls = this.#requestQueue.map((c) => c.methodCall);
|
||||
|
||||
const body = {
|
||||
auth: this.auth,
|
||||
requests: methodCalls,
|
||||
};
|
||||
|
||||
this.fetch(body)
|
||||
.then((res) => {
|
||||
this.#requestQueue.forEach((c, index) => {
|
||||
const individualResponse: TCResponseRaw = {
|
||||
ok: res?.ok ?? false,
|
||||
...res?.responses[index],
|
||||
};
|
||||
|
||||
c.resolve(new c.creator(individualResponse));
|
||||
});
|
||||
})
|
||||
.catch((reason) => {
|
||||
this.#requestQueue.forEach((c) => c.reject(reason));
|
||||
})
|
||||
.finally(() => {
|
||||
this.#requestQueue.length = 0;
|
||||
});
|
||||
}
|
||||
|
||||
private async fetch(body: any): Promise<TCJSONResponse | undefined> {
|
||||
|
@ -93,7 +185,7 @@ export class Client {
|
|||
const res = await fetch(Client.BASE_URI, req);
|
||||
|
||||
if (!res.ok) {
|
||||
return;
|
||||
return Promise.reject();
|
||||
}
|
||||
|
||||
return await res.json() as TCJSONResponse;
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
import { Module } from "../module";
|
||||
import { TCResponse } from "../types";
|
||||
import { SaveDrawingResponse, ViewDrawingDataResponse } from "./types";
|
||||
|
||||
export class DrawingModule extends Module {
|
||||
public async saveDrawing(data: string, makeActive = false) {
|
||||
this.client._call(
|
||||
// newImageId: string
|
||||
SaveDrawingResponse,
|
||||
"legacy.drawing",
|
||||
{
|
||||
action: "save",
|
||||
data,
|
||||
makeActive,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
public async viewDrawingData(imageId: string) {
|
||||
// response { ok: boolean , pixelData: string }
|
||||
this.client._call(
|
||||
// newImageId: string
|
||||
ViewDrawingDataResponse,
|
||||
"legacy.drawing",
|
||||
{
|
||||
action: "initial-image-data",
|
||||
imageId,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
public async sendDrawing(imageId: string, receiver: string) {
|
||||
this.client._call(
|
||||
TCResponse,
|
||||
"drawing.send",
|
||||
{
|
||||
imageId,
|
||||
receiver,
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
import { TCResponse, TCResponseRaw } from "../types";
|
||||
|
||||
export class SaveDrawingResponse extends TCResponse {
|
||||
public newImageId: string;
|
||||
|
||||
public constructor(res: TCResponseRaw) {
|
||||
super(res);
|
||||
this.newImageId = res["newImageId"];
|
||||
}
|
||||
}
|
||||
|
||||
export class ViewDrawingDataResponse extends TCResponse {
|
||||
public data: string;
|
||||
|
||||
public constructor(res: TCResponseRaw) {
|
||||
super(res);
|
||||
this.data = res["data"];
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue