implemented most message api functions
							parent
							
								
									bcf00e1cd7
								
							
						
					
					
						commit
						d275848536
					
				
								
									
									
										
											26
										
									
									README.md
									
									
									
									
								
								
							
							
										
											26
										
									
									README.md
									
									
									
									
								|  | @ -3,9 +3,14 @@ | |||
| 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). | ||||
| [jsii](https://github.com/aws/jsii). Requires node to be installed to use the | ||||
| language bindings. | ||||
| 
 | ||||
| ## Example | ||||
| ## Requirements | ||||
| 
 | ||||
| - `node` | ||||
| 
 | ||||
| ## Python Example | ||||
| 
 | ||||
| ```py | ||||
| from pewcans import Client | ||||
|  | @ -15,3 +20,20 @@ res = client.messages.folder_view() | |||
| for msg in res.messages: | ||||
|     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); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| ``` | ||||
|  |  | |||
|  | @ -1,13 +1,13 @@ | |||
| { | ||||
|   "name": "pewcans", | ||||
|   "name": "pecans", | ||||
|   "version": "1.0.0", | ||||
|   "lockfileVersion": 3, | ||||
|   "requires": true, | ||||
|   "packages": { | ||||
|     "": { | ||||
|       "name": "pewcans", | ||||
|       "name": "pecans", | ||||
|       "version": "1.0.0", | ||||
|       "license": "GPL-3.0", | ||||
|       "license": "GPL-3.0-only", | ||||
|       "devDependencies": { | ||||
|         "@types/node": "^20.8.4", | ||||
|         "jsii": "^5.2.14", | ||||
|  |  | |||
								
									
									
										
											12
										
									
									package.json
									
									
									
									
								
								
							
							
										
											12
										
									
									package.json
									
									
									
									
								|  | @ -1,7 +1,7 @@ | |||
| { | ||||
|   "name": "pewcans", | ||||
|   "name": "pecans", | ||||
|   "version": "1.0.0", | ||||
|   "description": "Pretty easy wrapper for Two Cans & String API", | ||||
|   "description": "Pretty easy Two Cans & String API wrapper", | ||||
|   "scripts": { | ||||
|     "build": "jsii --strict", | ||||
|     "dist": "jsii --strict && jsii-pacmak", | ||||
|  | @ -29,8 +29,12 @@ | |||
|     }, | ||||
|     "targets": { | ||||
|       "python": { | ||||
|         "distName": "pewcans", | ||||
|         "module": "pewcans" | ||||
|         "distName": "pecans", | ||||
|         "module": "pecans" | ||||
|       }, | ||||
|       "dotnet": { | ||||
|         "namespace": "Pecans", | ||||
|         "packageId": "Pecans" | ||||
|       } | ||||
|     } | ||||
|   }, | ||||
|  |  | |||
|  | @ -1,37 +1,5 @@ | |||
| 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; | ||||
| } | ||||
| import { MethodCall, TCJSONResponse, TCResponse } from "./types"; | ||||
| 
 | ||||
| /** | ||||
|  * Client for Two Cans & String API. | ||||
|  | @ -64,50 +32,41 @@ export class Client { | |||
|         methodName: string, args: { [key: string]: any } | ||||
|     ): Promise<T> | ||||
|     { | ||||
|         let methodCall: MethodCall = { | ||||
|         const methodCall: MethodCall = { | ||||
|             fn: methodName, | ||||
|             payload: args, | ||||
|         }; | ||||
| 
 | ||||
|         let body = { | ||||
|         const 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; | ||||
|         } | ||||
|         const res = await this.fetch(body); | ||||
| 
 | ||||
|         return { | ||||
|             ok: false, | ||||
|             ok: res?.ok ?? false, | ||||
|             ...res?.responses[0], | ||||
|         } as T; | ||||
|     } | ||||
| 
 | ||||
|     private async fetch(body: any): Promise<TCJSONResponse | undefined> { | ||||
|         let req = { | ||||
|         const req = { | ||||
|             method: "POST", | ||||
|             headers: { | ||||
|                 "Content-Type": "application/json", | ||||
|                 "Cookie": "twocansandstring_com_auth2=" + this.auth, | ||||
|                 "User-Agent": "pewcans", | ||||
|                 "User-Agent": "pecans", | ||||
|             }, | ||||
|             body: JSON.stringify(body), | ||||
|         }; | ||||
| 
 | ||||
|         let res = await fetch(Client.BASE_URI, req); | ||||
|         const res = await fetch(Client.BASE_URI, req); | ||||
| 
 | ||||
|         if (!res.ok) { | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         let json: TCJSONResponse = await res.json() as TCJSONResponse; | ||||
| 
 | ||||
|         return json; | ||||
|         return await res.json() as TCJSONResponse; | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -1,6 +1,5 @@ | |||
| // hi
 | ||||
| 
 | ||||
| //export * from "./test";
 | ||||
| export * from "./messages"; | ||||
| export * from "./module"; | ||||
| export * from "./client"; | ||||
| export * as types from "./types"; | ||||
| export * from "./messages"; | ||||
| export * as messages from "./messages/types"; | ||||
|  |  | |||
|  | @ -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; | ||||
|     } | ||||
| } | ||||
|  | @ -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", | ||||
|             { } | ||||
|         ); | ||||
|     } | ||||
| } | ||||
|  | @ -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;
 | ||||
| //}
 | ||||
|  | @ -1,4 +1,4 @@ | |||
| import { Client } from "./client"; | ||||
| import type { Client } from "./client"; | ||||
| 
 | ||||
| export class Module { | ||||
|     #client: Client; | ||||
|  |  | |||
|  | @ -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; | ||||
| } | ||||
| 
 | ||||
		Loading…
	
		Reference in New Issue