implemented most message api functions

master
John Montagu, the 4th Earl of Sandvich 2023-10-14 11:51:02 -07:00
parent bcf00e1cd7
commit d275848536
Signed by: sandvich
GPG Key ID: 9A39BE37E602B22D
10 changed files with 345 additions and 99 deletions

View File

@ -3,9 +3,14 @@
Pretty Easy Wrapper for Two Cans & String API for version 1.68. 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 Typescript module that can also be used in Python, .NET, and Java using
[jsii](https://github.com/aws/jsii). [jsii](https://github.com/aws/jsii). Requires node to be installed to use the
language bindings.
## Example ## Requirements
- `node`
## Python Example
```py ```py
from pewcans import Client from pewcans import Client
@ -15,3 +20,20 @@ res = client.messages.folder_view()
for msg in res.messages: for msg in res.messages:
print(msg.preview) print(msg.preview)
``` ```
## C# Example
```cs
public class Program
{
public static void Main(string[] args)
{
var client = new Pecans.Client("AUTH COOKIE HERE");
var res = client.Messages.FolderView();
foreach (var msg in res.Messages)
{
Console.WriteLine(msg.Preview);
}
}
}
```

6
package-lock.json generated
View File

@ -1,13 +1,13 @@
{ {
"name": "pewcans", "name": "pecans",
"version": "1.0.0", "version": "1.0.0",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "pewcans", "name": "pecans",
"version": "1.0.0", "version": "1.0.0",
"license": "GPL-3.0", "license": "GPL-3.0-only",
"devDependencies": { "devDependencies": {
"@types/node": "^20.8.4", "@types/node": "^20.8.4",
"jsii": "^5.2.14", "jsii": "^5.2.14",

View File

@ -1,7 +1,7 @@
{ {
"name": "pewcans", "name": "pecans",
"version": "1.0.0", "version": "1.0.0",
"description": "Pretty easy wrapper for Two Cans & String API", "description": "Pretty easy Two Cans & String API wrapper",
"scripts": { "scripts": {
"build": "jsii --strict", "build": "jsii --strict",
"dist": "jsii --strict && jsii-pacmak", "dist": "jsii --strict && jsii-pacmak",
@ -29,8 +29,12 @@
}, },
"targets": { "targets": {
"python": { "python": {
"distName": "pewcans", "distName": "pecans",
"module": "pewcans" "module": "pecans"
},
"dotnet": {
"namespace": "Pecans",
"packageId": "Pecans"
} }
} }
}, },

View File

@ -1,37 +1,5 @@
import { MessagesModule } from "./messages"; import { MessagesModule } from "./messages";
import { MethodCall, TCJSONResponse, TCResponse } from "./types";
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. * Client for Two Cans & String API.
@ -64,50 +32,41 @@ export class Client {
methodName: string, args: { [key: string]: any } methodName: string, args: { [key: string]: any }
): Promise<T> ): Promise<T>
{ {
let methodCall: MethodCall = { const methodCall: MethodCall = {
fn: methodName, fn: methodName,
payload: args, payload: args,
}; };
let body = { const body = {
auth: this.auth, auth: this.auth,
requests: [ methodCall ], requests: [ methodCall ],
}; };
let res = await this.fetch(body); const res = await this.fetch(body);
if (res?.ok) {
let methodRes = res.responses[0];
return {
...methodRes,
profiles: res.profiles,
} as T;
}
return { return {
ok: false, ok: res?.ok ?? false,
...res?.responses[0],
} as T; } as T;
} }
private async fetch(body: any): Promise<TCJSONResponse | undefined> { private async fetch(body: any): Promise<TCJSONResponse | undefined> {
let req = { const req = {
method: "POST", method: "POST",
headers: { headers: {
"Content-Type": "application/json", "Content-Type": "application/json",
"Cookie": "twocansandstring_com_auth2=" + this.auth, "Cookie": "twocansandstring_com_auth2=" + this.auth,
"User-Agent": "pewcans", "User-Agent": "pecans",
}, },
body: JSON.stringify(body), body: JSON.stringify(body),
}; };
let res = await fetch(Client.BASE_URI, req); const res = await fetch(Client.BASE_URI, req);
if (!res.ok) { if (!res.ok) {
return; return;
} }
let json: TCJSONResponse = await res.json() as TCJSONResponse; return await res.json() as TCJSONResponse;
return json;
} }
} }

View File

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

View File

@ -1,34 +0,0 @@
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;
}
}

View File

@ -0,0 +1,54 @@
import { Module } from "../module";
import { TCResponse } from "../types";
import { FolderListResponse, FolderViewResponse, MessageViewResponse } from "./types";
export class MessagesModule extends Module {
public async folderView(folder = "inbox", page = 1) {
return await this.client.call<FolderViewResponse>(
"messages.folderview",
{
folder,
page,
}
);
}
public async view(
conversationId: string,
includeHeader = true,
markAsRead = true,
page = 1
) {
return await this.client.call<MessageViewResponse>(
"messages.view",
{
conversationId,
includeHeader,
markAsRead,
page,
},
);
}
public async reply(
conversationId: string,
text: string,
unanonymize = false
) {
return await this.client.call<TCResponse>(
"messages.reply",
{
conversationId,
text,
unanonymize,
},
);
}
public async folderList() {
return await this.client.call<FolderListResponse>(
"messages.folderlist",
{ }
);
}
}

View File

@ -0,0 +1,209 @@
import { TCResponse, TCUser } from "../types";
export interface FolderViewResponse extends TCResponse {
readonly hasMore: boolean;
readonly hasPrevious: boolean;
readonly messages: MessagePreview[];
}
export interface MessageViewResponse extends TCResponse {
readonly messages: Message[];
readonly header: MessageThreadHeader;
}
export interface MessagePreview {
readonly id: string;
readonly subject: string;
readonly preview: string;
readonly time: number;
readonly users: TCUser[];
readonly new?: boolean;
}
export interface Message {
readonly id: number;
readonly member: number;
readonly time: number;
readonly type: string;
readonly html: string;
readonly new?: boolean;
}
export interface MessageThreadHeader {
readonly title: string;
readonly members: MessageThreadMember[];
readonly folder: MessageFolder;
}
export interface MessageThreadMember {
readonly mid: number;
readonly anon?: boolean;
readonly readTo: number;
}
export interface MessageFolder {
readonly id: string;
readonly name: string;
}
export interface FolderListResponse extends TCResponse {
readonly folders: Folder[];
}
export interface Folder {
readonly id: string;
readonly name: string;
}
//interface MessagePreviewRaw {
// readonly id: string;
// readonly subject: string;
// readonly preview: string;
// readonly time: number;
// readonly users: TCUser[];
// readonly new: boolean;
//}
//
//class MessagePreview {
// id: string;
// subject: string;
// preview: string;
// time: number;
// users: TCUser[];
// isNew: boolean;
// context: Client;
//
// /** @internal */
// public constructor(context: Client, msg: MessagePreviewRaw) {
// this.context = context;
// this.id = msg.id;
// this.subject = msg.subject;
// this.preview = msg.preview;
// this.time = msg.time;
// this.users = msg.users;
// this.isNew = msg.new;
// }
//
// public open() {
// return this.context.messages.view(this.id);
// }
//}
//
//interface MessageRaw {
// readonly id: number;
// readonly member: number;
// readonly time: number;
// readonly messageType: string;
// readonly html: string;
// readonly new: boolean;
//}
//
//class Message {
// id: number;
// member: number;
// time: number;
// messageType: string;
// html: string;
// isNew: boolean;
//
// /** @internal */
// public constructor(msg: MessageRaw) {
// this.id = msg.id;
// this.member = msg.member;
// this.time = msg.time;
// this.messageType = msg.messageType;
// this.html = msg.html;
// this.isNew = msg.new;
// }
//}
//export class Message {
// id: number;
// member: number;
// time: number;
// messageType: string;
// html: string;
// isNew: boolean;
//
// /** @internal */
// public constructor(msg: TCMessage) {
// this.id = msg.id;
// this.member = msg.member;
// this.time = msg.time;
// this.messageType = msg.messageType;
// this.html = msg.html;
// this.isNew = msg.isNew;
// }
//}
//interface MessagePreview {
// readonly id: string;
// readonly subject: string;
// readonly preview: string;
// readonly time: number;
// readonly users: TCUser[];
// readonly new: boolean;
//}
//
////export class MessagePreview {
//// id: string;
//// subject: string;
//// preview: string;
//// time: number;
//// users: TCUser[];
//// isNew: boolean;
////
//// /** @internal */
//// public constructor(msg: TCMessagePreview) {
//// this.id = msg.id;
//// this.subject = msg.subject;
//// this.preview = msg.preview;
//// this.time = msg.time;
//// this.users = msg.users;
//// this.isNew = msg.new;
//// }
////}
//
//interface TCMessage {
// readonly id: number;
// readonly member: number;
// readonly time: number;
// readonly messageType: string;
// readonly html: string;
// readonly isNew: boolean;
//}
//
//export class Message {
// id: number;
// member: number;
// time: number;
// messageType: string;
// html: string;
// isNew: boolean;
//
// /** @internal */
// public constructor(msg: TCMessage) {
// this.id = msg.id;
// this.member = msg.member;
// this.time = msg.time;
// this.messageType = msg.messageType;
// this.html = msg.html;
// this.isNew = msg.isNew;
// }
//}
//
//export interface MessageThreadHeader {
// readonly title: string;
// readonly members: MessageThreadMember[];
// readonly folder: MessageFolder;
//}
//
//export interface MessageThreadMember {
// readonly mid: number;
// readonly anon?: boolean;
// readonly readTo: number;
//}
//
//export interface MessageFolder {
// readonly id: string;
// readonly name: string;
//}

View File

@ -1,4 +1,4 @@
import { Client } from "./client"; import type { Client } from "./client";
export class Module { export class Module {
#client: Client; #client: Client;

33
src/types/index.ts 100644
View File

@ -0,0 +1,33 @@
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;
}