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

Commit

Permalink
uploads
Browse files Browse the repository at this point in the history
  • Loading branch information
williamhorning committed Jul 8, 2024
1 parent c32b8e1 commit ec2beee
Show file tree
Hide file tree
Showing 5 changed files with 143 additions and 23 deletions.
1 change: 1 addition & 0 deletions src/api/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@
export * from './client.ts';
export * from './rest.ts';
export * from './socket.ts';
export * from './uploads.ts';
12 changes: 7 additions & 5 deletions src/api/socket.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ export class socket extends EventEmitter<{
[key: `listener-${string}`]: [socket_packet];
create_message: [post];
edit_message: [post];
delete_message: [{ id: string}];
delete_message: [{ id: string }];
}> {
private socket: WebSocket;
private opts: socket_connect_opts;
Expand All @@ -68,15 +68,15 @@ export class socket extends EventEmitter<{
'val': 'js',
},
});

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

setInterval(() => {
if (this.socket.readyState === 1) {
this.send({
Expand All @@ -85,7 +85,7 @@ export class socket extends EventEmitter<{
});
}
}, 30000);
}
};

this.socket.onclose = () => this.emit('socket_close');

Expand All @@ -111,7 +111,9 @@ export class socket extends EventEmitter<{
) return;

if (packet.val.p) {
const event = 'payload' in packet.val ? 'edit_message' : 'create_message';
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,
Expand Down
68 changes: 68 additions & 0 deletions src/api/uploads.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/** api attachment */
export interface api_attachment {
/** filename */
filename: string;
/** file type */
mime: string;
/** file size */
size: number;
/** image height */
height?: number;
/** image width */
width?: number;
/** file id */
id: string;
}

/** uploads class construction options */
export interface uploads_opts {
/** base url for uploads */
base_url: string;
/** an api token */
token: string;
}

/** upload types */
export enum upload_types {
attachment = 'attachments',
icon = 'icons',
}

/** access to meower uploads */
export class uploads {
private opts: uploads_opts;

constructor(opts: uploads_opts) {
this.opts = opts;
}

/** upload a file */
async upload_file(
file: Blob,
upload_type: upload_types = upload_types.attachment,
): Promise<api_attachment> {
const form = new FormData();
form.append('file', file);
const res = await fetch(`${this.opts.base_url}/${upload_type}`, {
method: 'POST',
headers: {
Authorization: `Bearer ${this.opts.token}`,
},
body: form,
});
if (!res.ok) {
throw new Error('failed to upload file', {
cause: await res.json(),
});
}
return await res.json();
}

/** get the url for an attachment */
get_file_url(
file: api_attachment,
upload_type: upload_types = upload_types.attachment,
): string {
return `${this.opts.base_url}/${upload_type}/${file.id}/${file.filename}`;
}
}
21 changes: 3 additions & 18 deletions src/interfaces/post.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import type { api_attachment } from '../api/uploads.ts';
import type { message_send_opts } from './chat.ts';

/** types of posts */
Expand All @@ -11,26 +12,10 @@ export enum post_type {
/** bridge users */
export const bridge_users = ['Discord', 'boltcanary', 'bolt'];

/** api attachment */
export interface api_attachment {
/** filename */
filename: string;
/** file type */
mime: string;
/** file size */
size: number;
/** image height */
height?: number;
/** image width */
width?: number;
/** file id */
id: string;
}

/** raw post data */
export interface api_post {
/** attachments */
attachments?: string[];
attachments?: api_attachment[];
/** is the post pinned */
pinned: boolean;
/** bridged post */
Expand Down Expand Up @@ -118,7 +103,7 @@ export class post {
private api_username: string;
private raw: api_post;
/** attachments */
attachments?: string[];
attachments?: api_attachment[];
/** post id */
id!: string;
/** whether the post in pinned */
Expand Down
64 changes: 64 additions & 0 deletions tests/uploads.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { uploads } from '../src/api/uploads.ts';
import { assertEquals, assertRejects, mockFetch } from './internal/deps.ts';

Deno.test('attachment file url', () => {
const u = new uploads({
base_url: 'http://localhost:8080',
token: 'test',
});

assertEquals(
u.get_file_url({
filename: 'test.txt',
id: '1234',
mime: 'text/plain',
size: 1234,
}),
'http://localhost:8080/attachments/1234/test.txt',
);
});

Deno.test('attachment upload', async (i) => {
const u = new uploads({
base_url: 'http://localhost:8080',
token: 'test',
});

await i.step('successful', async () => {
mockFetch('http://localhost:8080/attachments', {
body: JSON.stringify({
filename: 'string',
mime: 'string',
size: 1,
id: 'string',
}),
});

const file = new Blob(['test'], { type: 'text/plain' });

const res = await u.upload_file(file);

assertEquals(res, {
filename: 'string',
mime: 'string',
size: 1,
id: 'string',
});
});

await i.step('failure', async () => {
mockFetch('http://localhost:8080/attachment', {
status: 500,
body: JSON.stringify({
error: true,
message: 'notFound',
}),
});

const file = new Blob(['test'], { type: 'text/plain' });

await assertRejects(async () => {
await u.upload_file(file);
});
});
});

0 comments on commit ec2beee

Please sign in to comment.