Skip to content
This repository has been archived by the owner on Nov 13, 2024. It is now read-only.

Commit

Permalink
add socketv1
Browse files Browse the repository at this point in the history
  • Loading branch information
williamhorning committed Aug 6, 2024
1 parent a291db1 commit 4f5f06f
Show file tree
Hide file tree
Showing 7 changed files with 75 additions and 100 deletions.
6 changes: 6 additions & 0 deletions src/api/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,12 @@ export class client {
this.api = api;
this.socket = socket;
this.uploads = uploads;

socket.on("auth", (data) => {
for (const chat of data.chats) {
api._chat_cache.set(chat._id, chat);
}
})
}

/** signup for an account and login */
Expand Down
41 changes: 17 additions & 24 deletions src/api/rest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,21 +35,23 @@ export class rest_api {
api_url: string;
/** the api token */
api_token: string;
private chat_cache = new Map<string, api_chat>();
private post_cache = new Map<string, api_post>();
private user_cache = new Map<string, api_user>();
/** @internal chat cache */
_chat_cache = new Map<string, api_chat>();
/** @internal post cache */
_post_cache = new Map<string, api_post>();
/** @internal user cache */
_user_cache = new Map<string, api_user>();

constructor(opts: api_construction_opts) {
this.api_user = new user({
api_token: opts.token,
api_username: opts.account.lower_username,
api_url: opts.api_url,
data: opts.account,
});
this.api_url = opts.api_url;
this.api_token = opts.token;

this.chat_cache.set('home', {
this._chat_cache.set('home', {
_id: 'home',
allow_pinning: false,
created: 0,
Expand All @@ -65,7 +67,7 @@ export class rest_api {
stickers: [],
});

this.chat_cache.set('livechat', {
this._chat_cache.set('livechat', {
_id: 'livechat',
allow_pinning: false,
created: 0,
Expand All @@ -84,13 +86,12 @@ export class rest_api {

/** get a chat by id */
async get_chat(id: string): Promise<chat> {
const cached = this.chat_cache.get(id);
const cached = this._chat_cache.get(id);

if (cached) {
return new chat({
api_token: this.api_token,
api_url: this.api_url,
api_username: this.api_user.username,
data: cached,
});
}
Expand All @@ -107,12 +108,11 @@ export class rest_api {
throw new Error('failed to get chat', { cause: data });
}

this.chat_cache.set(id, data);
this._chat_cache.set(id, data);

return new chat({
api_token: this.api_token,
api_url: this.api_url,
api_username: this.api_user.username,
data,
});
}
Expand All @@ -132,15 +132,14 @@ export class rest_api {
}

data.autoget.push(
this.chat_cache.get('home'),
this.chat_cache.get('livechat'),
this._chat_cache.get('home'),
this._chat_cache.get('livechat'),
);

return data.autoget.map((i: api_chat) =>
new chat({
api_token: this.api_token,
api_url: this.api_url,
api_username: this.api_user.username,
data: i,
})
);
Expand All @@ -165,25 +164,23 @@ export class rest_api {
throw new Error('failed to create chat', { cause: data });
}

this.chat_cache.set(data._id, data);
this._chat_cache.set(data._id, data);

return new chat({
api_token: this.api_token,
api_url: this.api_url,
api_username: this.api_user.username,
data,
});
}

/** get a post by id */
async get_post(id: string): Promise<post> {
const cached = this.post_cache.get(id);
const cached = this._post_cache.get(id);

if (cached) {
return new post({
api_token: this.api_token,
api_url: this.api_url,
api_username: this.api_user.username,
data: cached,
});
}
Expand All @@ -200,25 +197,23 @@ export class rest_api {
throw new Error('failed to get post', { cause: data });
}

this.post_cache.set(id, data);
this._post_cache.set(id, data);

return new post({
api_token: this.api_token,
api_url: this.api_url,
api_username: this.api_user.username,
data,
});
}

/** get a user by id */
async get_user(id: string): Promise<user> {
const cached = this.user_cache.get(id);
const cached = this._user_cache.get(id);

if (cached) {
return new user({
api_token: this.api_token,
api_url: this.api_url,
api_username: this.api_user.username,
data: cached,
});
}
Expand All @@ -235,12 +230,11 @@ export class rest_api {
throw new Error('failed to get user', { cause: data });
}

this.user_cache.set(id, data);
this._user_cache.set(id, data);

return new user({
api_token: this.api_token,
api_url: this.api_url,
api_username: this.api_user.username,
data,
});
}
Expand All @@ -266,7 +260,6 @@ export class rest_api {
new user({
api_token: this.api_token,
api_url: this.api_url,
api_username: this.api_user.username,
data: i,
})
);
Expand Down
104 changes: 49 additions & 55 deletions src/api/socket.ts
Original file line number Diff line number Diff line change
@@ -1,39 +1,29 @@
import { EventEmitter } from 'jsr:@denosaurs/[email protected]';
import { type api_post, post } from '../interfaces/post.ts';
import type { api_user } from '../interfaces/user.ts';
import type { api_user, user_relationship_status } from '../interfaces/user.ts';
import type { api_chat } from '../interfaces/chat.ts';

/** options used to connect to the meower socket */
export interface socket_connect_opts {
/** the api url */
api_url: string;
/** the api token */
api_token: string;
/** the password */
password?: string;
/** the socket url */
socket_url: string;
/** the username */
username: string;
}

/** socket value types */
export type socket_value =
| string
| number
| boolean
| { [key: string]: socket_value }
| socket_value[];

/** a packet sent over the socket */
export interface socket_packet {
/** the packet command */
cmd: string;
/** the packet value */
val?: socket_value;
/** packet names */
name?: string;
/** packet id */
id?: string;
val: socket_value;
/** listener id */
listener?: string;
}
Expand All @@ -44,6 +34,15 @@ export interface socket_auth_event {
account: api_user;
/** api token */
token: string;
/** username */
username: string;
/** relationships */
relationships: {
username: string;
tyoe: user_relationship_status
}[];
/** chats */
chats: api_chat[];
}

/** access to the meower socket */
Expand All @@ -56,11 +55,13 @@ export class socket extends EventEmitter<{
[key: `listener-${string}`]: [socket_packet];
create_message: [post];
edit_message: [post];
delete_message: [{ id: string }];
delete_message: [{ post_id: string, chat_id: string }];
typing: [{ chat_id: string, username: string }];
auth: [socket_auth_event];
}> {
private socket: WebSocket;
private opts: socket_connect_opts;
ulist: string[] = [];

/** create a socket instance from a given websocket connection */
constructor(socket: WebSocket, opts: socket_connect_opts) {
Expand All @@ -73,22 +74,6 @@ export class socket extends EventEmitter<{
private setup() {
this.emit('socket_open');

this.send({
'cmd': 'direct',
'val': {
'cmd': 'type',
'val': 'js',
},
});

this.send({
'cmd': 'authpswd',
'val': {
'username': this.opts.username,
'pswd': this.opts.password ?? this.opts.api_token,
},
});

setInterval(() => {
if (this.socket.readyState === 1) {
this.send({
Expand All @@ -115,47 +100,56 @@ export class socket extends EventEmitter<{

this.socket.onerror = (err) => this.emit('socket_error', err);

this.on('cmd-direct', (packet) => {
if (
!packet.val || typeof packet.val !== 'object' ||
Array.isArray(packet.val)
) return;

if (packet.val.p) {
const event = 'payload' in packet.val
? 'edit_message'
: 'create_message';
const api = (packet.val.payload ?? packet.val) as unknown as api_post;
this.on('cmd-post', packet => {
try {
const api = packet.val as unknown as api_post;
const p = new post({
api_token: this.opts.api_token,
api_url: this.opts.api_url,
api_username: this.opts.username,
data: api,
});
this.emit(event, p);
this.emit('create_message', p);
} catch {
// ignore
}
})

if (packet.val.mode === 'delete_post') {
this.emit('delete_message', { id: packet.val.id as string });
this.on('cmd-update_post', packet => {
try {
const api = packet.val as unknown as api_post;
const p = new post({
api_token: this.opts.api_token,
api_url: this.opts.api_url,
data: api,
});
this.emit('edit_message', p);
} catch {
// ignore
}
});
})

this.on('cmd-direct', (packet) => {
const val = packet.val as Record<string, unknown>;
this.on('cmd-delete_post', packet => {
this.emit('delete_message', packet.val as { post_id: string, chat_id: string });
})

if (val.mode !== 'auth') return;
this.on('cmd-typing', packet => {
this.emit('typing', packet.val as { chat_id: string, username: string });
})

const auth_event = val.payload as socket_auth_event;
this.on('cmd-ulist', packet => {
this.ulist = (packet.val as string).split(';')
})

this.opts.api_token = auth_event.token;
this.on('cmd-auth', packet => {
this.emit('auth', packet.val as unknown as socket_auth_event);

this.emit('auth', auth_event);
});
this.opts.api_token = (packet.val as unknown as socket_auth_event).token;
})
}

static async connect(opts: socket_connect_opts): Promise<socket> {
const ws = new WebSocket(
opts.socket_url,
`${opts.socket_url}/?v=1&token=${opts.api_token}`,
);
await new Promise((resolve) => ws.onopen = resolve);
return new socket(ws, opts);
Expand All @@ -170,7 +164,7 @@ export class socket extends EventEmitter<{
async reconnect() {
this.disconnect();
const socket = new WebSocket(
this.opts.socket_url,
`${this.opts.socket_url}/?v=1&token=${this.opts.api_token}`,
);
await new Promise((resolve) => socket.onopen = resolve);
this.socket = socket;
Expand Down
Loading

0 comments on commit 4f5f06f

Please sign in to comment.