pl-api: basic support for pleroma shoutbox

Signed-off-by: Nicole Mikołajczyk <git@mkljczk.pl>
This commit is contained in:
Nicole Mikołajczyk
2025-03-28 21:12:42 +01:00
parent 42c5e6a151
commit e211dad0be
8 changed files with 156 additions and 1 deletions

View File

@ -251,6 +251,7 @@ import type {
GetTrendingTags,
} from './params/trends';
import type { PaginatedResponse } from './responses';
import { ShoutMessage, shoutMessageSchema } from './entities/shout-message';
const GROUPED_TYPES = ['favourite', 'reblog', 'emoji_reaction', 'event_reminder', 'participation_accepted', 'participation_request'];
@ -285,6 +286,10 @@ class PlApiClient {
unsubscribe: (stream: string, params?: { list?: string; tag?: string }) => void;
close: () => void;
};
#shoutSocket?: {
message: (text: string) => void;
close: () => void;
}
/**
*
@ -2765,6 +2770,45 @@ class PlApiClient {
},
};
public readonly shoutbox = {
connect: (token: string, { onMessage, onMessages }: {
onMessages: (messages: Array<ShoutMessage>) => void;
onMessage: (message: ShoutMessage) => void;
}) => {
if (this.#shoutSocket) return this.#shoutSocket;
const path = buildFullPath('/socket/websocket', this.baseURL, { token, vsn: '2.0.0' });
const ws = new WebSocket(path);
ws.onmessage = (event) => {
// @eslint-disable-next-line @typescript-eslint/no-unused-vars
const [_, __, ___, type, payload] = JSON.parse(event.data as string);
if (type === 'new_msg') {
const message = v.parse(payload, shoutMessageSchema);
onMessage(message);
} else if (type === 'messages') {
const messages = v.parse(filteredArray(shoutMessageSchema), payload.messages);
onMessages(messages);
}
};
ws.onopen = () => {
ws.send(JSON.stringify(['3', '3', 'chat:public', 'phx_join', {}]));
};
this.#shoutSocket = {
message: (text: string) => {
ws.send(JSON.stringify({ type: 'message', text }));
},
close: () => {
ws.close();
this.#shoutSocket = undefined;
},
};
},
}
public readonly notifications = {
/**
* Get all notifications

View File

@ -67,6 +67,7 @@ export * from './rule';
export * from './scheduled-status';
export * from './scrobble';
export * from './search';
export * from './shout-message';
export * from './status';
export * from './status-edit';
export * from './status-source';

View File

@ -0,0 +1,19 @@
import * as v from 'valibot';
import { accountSchema } from './account';
/**
* @category Schemas
*/
const shoutMessageSchema = v.object({
id: v.number(),
text: v.string(),
author: accountSchema,
});
/**
* @category Entity types
*/
type ShoutMessage = v.InferOutput<typeof shoutMessageSchema>;
export { shoutMessageSchema, type ShoutMessage };