diff --git a/src/api/client.ts b/src/api/client.ts index b86cdc9..0b6f98a 100644 --- a/src/api/client.ts +++ b/src/api/client.ts @@ -68,9 +68,17 @@ export class client { const ws = await socket.connect({ ...opts, api_token: rest.api_token }); + const token = await new Promise((resolve) => { + ws.on('auth', (data) => { + resolve(data.token); + }); + }) as string; + + rest.api_token = token; + const u = new uploads({ base_url: opts.uploads_url, - token: rest.api_token, + token, }); return new client(rest, ws, u); diff --git a/src/api/rest.ts b/src/api/rest.ts index a3d831e..55b3d4c 100644 --- a/src/api/rest.ts +++ b/src/api/rest.ts @@ -305,7 +305,7 @@ export class rest_api { throw new Error('failed to login', { cause: data }); } - return new rest_api({ ...data, api_url }); + return new rest_api({ api_url, token: data.token, account: data.account }); } /** signup for an account on meower */ @@ -333,6 +333,6 @@ export class rest_api { throw new Error('failed to signup', { cause: data }); } - return new rest_api({ ...data, api_url }); + return new rest_api({ api_url, token: data.token, account: data.account }); } } diff --git a/src/api/socket.ts b/src/api/socket.ts index 2657ee1..c1093b4 100644 --- a/src/api/socket.ts +++ b/src/api/socket.ts @@ -1,5 +1,6 @@ -import { EventEmitter } from 'jsr:@denosaurs/event@2.0.2'; -import { type api_post, post } from '../interfaces/post.ts'; +import { EventEmitter } from "jsr:@denosaurs/event@2.0.2"; +import { type api_post, post } from "../interfaces/post.ts"; +import type { api_user } from "../interfaces/user.ts"; /** options used to connect to the meower socket */ export interface socket_connect_opts { @@ -7,6 +8,8 @@ export interface socket_connect_opts { api_url: string; /** the api token */ api_token: string; + /** the password */ + password?: string; /** the socket url */ socket_url: string; /** the username */ @@ -35,6 +38,14 @@ export interface socket_packet { listener?: string; } +/** auth information from the socket */ +export interface socket_auth_event { + /** api user */ + account: api_user; + /** api token */ + token: string; +} + /** access to the meower socket */ export class socket extends EventEmitter<{ socket_open: []; @@ -46,6 +57,7 @@ export class socket extends EventEmitter<{ create_message: [post]; edit_message: [post]; delete_message: [{ id: string }]; + auth: [socket_auth_event]; }> { private socket: WebSocket; private opts: socket_connect_opts; @@ -58,43 +70,41 @@ export class socket extends EventEmitter<{ } private setup() { - this.socket.onopen = () => { - 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.api_token, - }, - }); - - setInterval(() => { - if (this.socket.readyState === 1) { - this.send({ - 'cmd': 'ping', - 'val': '', - }); - } - }, 30000); - }; + this.emit("socket_open"); + + this.send({ + 'cmd': 'direct', + 'val': { + 'cmd': 'type', + 'val': 'js', + }, + }); - this.socket.onclose = () => this.emit('socket_close'); + 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({ + "cmd": "ping", + "val": "", + }); + } + }, 30000); + + this.socket.onclose = () => this.emit("socket_close"); this.socket.onmessage = (event) => { const packet = JSON.parse(event.data); if (!packet) return; - this.emit('packet', packet); + this.emit("packet", packet); this.emit(`cmd-${packet.cmd}`, packet); if (packet.listener) { @@ -102,19 +112,20 @@ export class socket extends EventEmitter<{ } }; - this.socket.onerror = (err) => this.emit('socket_error', err); + this.socket.onerror = (err) => this.emit("socket_error", err); - this.on('cmd-direct', (packet) => { + this.on("cmd-direct", (packet) => { if ( - !packet.val || typeof packet.val !== 'object' || + !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; + const event = "payload" in packet.val + ? "edit_message" + : "create_message"; + const api = + (packet.val.payload ?? packet.val) as unknown as api_post; const p = new post({ api_token: this.opts.api_token, api_url: this.opts.api_url, @@ -124,17 +135,28 @@ export class socket extends EventEmitter<{ this.emit(event, p); } - if (packet.val.mode === 'delete_post') { - this.emit('delete_message', { id: packet.val.id as string }); + if (packet.val.mode === "delete_post") { + this.emit("delete_message", { id: packet.val.id as string }); } }); + + this.on("cmd-direct", (packet) => { + const val = packet.val as Record; + + if (val.mode !== "auth") return; + + const auth_event = val.payload as socket_auth_event; + + this.opts.api_token = auth_event.token; + + this.emit("auth", auth_event) + }) } static async connect(opts: socket_connect_opts): Promise { - const ws = - new (globalThis.WebSocket ? WebSocket : ((await import('ws')).default))( - opts.socket_url, - ); + const ws = new WebSocket( + opts.socket_url, + ); await new Promise((resolve) => ws.onopen = resolve); return new socket(ws, opts); } @@ -147,10 +169,9 @@ export class socket extends EventEmitter<{ /** reconnect to the socket */ async reconnect() { this.disconnect(); - const socket = - new (globalThis.WebSocket ? WebSocket : ((await import('ws')).default))( - this.opts.socket_url, - ); + const socket = new WebSocket( + this.opts.socket_url, + ); await new Promise((resolve) => socket.onopen = resolve); this.socket = socket; this.setup(); diff --git a/src/interfaces/chat.ts b/src/interfaces/chat.ts index 55c884b..36e2037 100644 --- a/src/interfaces/chat.ts +++ b/src/interfaces/chat.ts @@ -95,7 +95,8 @@ export class chat { private api_url: string; private api_token: string; private api_username: string; - private raw: api_chat; + /** raw api data */ + raw: api_chat; /** chat id */ id!: string; /** whether pinning is allowed */ diff --git a/src/interfaces/post.ts b/src/interfaces/post.ts index b46350a..2c3817f 100644 --- a/src/interfaces/post.ts +++ b/src/interfaces/post.ts @@ -101,7 +101,8 @@ export class post { private api_url: string; private api_token: string; private api_username: string; - private raw: api_post; + /** raw api data */ + raw: api_post; /** attachments */ attachments?: api_attachment[]; /** post id */ diff --git a/src/interfaces/user.ts b/src/interfaces/user.ts index 601ae10..4732857 100644 --- a/src/interfaces/user.ts +++ b/src/interfaces/user.ts @@ -90,7 +90,8 @@ export class user { private api_url: string; private api_token: string; private api_username: string; - private raw: api_user; + /** raw user data */ + raw: api_user; /** user id */ id!: string; /** user avatar file id */