basic message fetching

master
John Montagu, the 4th Earl of Sandvich 2023-10-11 10:04:24 -07:00
parent 602c8cc2c9
commit bcf00e1cd7
Signed by: sandvich
GPG Key ID: 9A39BE37E602B22D
9 changed files with 1683 additions and 0 deletions

12
.gitignore vendored 100644
View File

@ -0,0 +1,12 @@
# Exclude jsii outdir and build output
dist
*.js
*.d.ts
.jsii
node_modules
obj/
tsconfig.json
tsconfig.tsbuildinfo

15
.npmignore 100644
View File

@ -0,0 +1,15 @@
# Exclude typescript source and config
*.ts
tsconfig.json
# Include javascript files and typescript declarations
!*.js
!*.d.ts
# Exclude jsii outdir
dist
# Include .jsii and .jsii.gz
!.jsii
!.jsii.gz

17
README.md 100644
View File

@ -0,0 +1,17 @@
# Pewcans
Pretty Easy Wrapper for Two Cans & String API for version 1.68.
Typescript module that can also be used in Python, .NET, and Java using
[jsii](https://github.com/aws/jsii).
## Example
```py
from pewcans import Client
client = Client("AUTH COOKIE HERE")
res = client.messages.folder_view()
for msg in res.messages:
print(msg.preview)
```

1430
package-lock.json generated 100644

File diff suppressed because it is too large Load Diff

43
package.json 100644
View File

@ -0,0 +1,43 @@
{
"name": "pewcans",
"version": "1.0.0",
"description": "Pretty easy wrapper for Two Cans & String API",
"scripts": {
"build": "jsii --strict",
"dist": "jsii --strict && jsii-pacmak",
"clean": "rm -r dist obj || true",
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"repository": {
"url": "https://github.com/humanoidsandvichdispenser/pew.git"
},
"main": "obj/index.js",
"types": "obj/index.d.ts",
"author": {
"name": "HumanoidSandvichDispenser",
"email": "humanoidsandvichdispenser@gmail.com"
},
"license": "GPL-3.0-only",
"jsii": {
"excludeTypescript": ["*.test.ts"],
"versionFormat": "full",
"outdir": "dist",
"tsc": {
"outDir": "obj",
"rootDir": "src"
},
"targets": {
"python": {
"distName": "pewcans",
"module": "pewcans"
}
}
},
"stability": "experimental",
"devDependencies": {
"@types/node": "^20.8.4",
"jsii": "^5.2.14",
"jsii-pacmak": "^1.90.0"
}
}

113
src/client.ts 100644
View File

@ -0,0 +1,113 @@
import { MessagesModule } from "./messages";
export interface MethodCall {
readonly fn: string;
readonly payload: { [key: string]: any };
}
export interface TCJSONResponse {
readonly ok: boolean;
readonly loginId: string;
readonly responses: TCResponse[];
readonly profiles: TCProfile[];
readonly auth: string;
readonly ver: string;
}
export interface TCResponse {
readonly ok: boolean;
readonly profiles: TCProfile[];
}
// TODO: move this to another file
export interface TCUser {
readonly id?: string;
readonly anon?: boolean;
}
export interface TCProfile {
readonly id: string;
readonly name: string;
readonly online: number;
readonly avatar: string;
}
/**
* Client for Two Cans & String API.
*/
export class Client {
static readonly BASE_URI = "https://twocansandstring.com/api";
static readonly VERSION = "1.68"
#messages: MessagesModule;
public get messages(): MessagesModule {
return this.#messages;
}
public auth: string;
public constructor(auth: string) {
this.auth = auth;
// init modules
this.#messages = new MessagesModule(this);
}
/**
* Calls an API method.
* @param methodName The name of the API method to call.
* @param args The arguments to pass to the API method.
*/
public async call<T extends TCResponse>(
methodName: string, args: { [key: string]: any }
): Promise<T>
{
let methodCall: MethodCall = {
fn: methodName,
payload: args,
};
let body = {
auth: this.auth,
requests: [ methodCall ],
};
let res = await this.fetch(body);
if (res?.ok) {
let methodRes = res.responses[0];
return {
...methodRes,
profiles: res.profiles,
} as T;
}
return {
ok: false,
} as T;
}
private async fetch(body: any): Promise<TCJSONResponse | undefined> {
let req = {
method: "POST",
headers: {
"Content-Type": "application/json",
"Cookie": "twocansandstring_com_auth2=" + this.auth,
"User-Agent": "pewcans",
},
body: JSON.stringify(body),
};
let res = await fetch(Client.BASE_URI, req);
if (!res.ok) {
return;
}
let json: TCJSONResponse = await res.json() as TCJSONResponse;
return json;
}
}

6
src/index.ts 100644
View File

@ -0,0 +1,6 @@
// hi
//export * from "./test";
export * from "./messages";
export * from "./module";
export * from "./client";

34
src/messages.ts 100644
View File

@ -0,0 +1,34 @@
import { Module } from "./module";
import { TCResponse, TCUser } from "./client";
export interface FolderViewResponse extends TCResponse {
readonly hasMore: boolean;
readonly hasPrevious: boolean;
readonly messages: MessagePreview[];
}
export interface MessagePreview {
readonly id: string;
readonly subject: string;
readonly preview: string;
readonly time: number;
readonly users: TCUser[];
}
export class MessagesModule extends Module {
public async folderView(folder = "inbox", page = 1): Promise<FolderViewResponse> {
let ret = await this.client.call<FolderViewResponse>(
"messages.folderview",
{
folder,
page,
}
);
if (!ret) {
throw 0;
}
return ret;
}
}

13
src/module.ts 100644
View File

@ -0,0 +1,13 @@
import { Client } from "./client";
export class Module {
#client: Client;
protected get client(): Client {
return this.#client;
}
public constructor(client: Client) {
this.#client = client;
}
}