Files
bunq/ts/bunq.classes.attachment.ts
Juergen Kunz 596efa3f06 update
2025-07-18 10:43:39 +00:00

266 lines
7.1 KiB
TypeScript

import * as plugins from './bunq.plugins.js';
import { BunqAccount } from './bunq.classes.account.js';
export class BunqAttachment {
private bunqAccount: BunqAccount;
public id?: number;
public created?: string;
public updated?: string;
public uuid?: string;
constructor(bunqAccount: BunqAccount) {
this.bunqAccount = bunqAccount;
}
/**
* Upload a file attachment
*/
public async upload(options: {
contentType: string;
description?: string;
body: Buffer | string;
}): Promise<string> {
await this.bunqAccount.apiContext.ensureValidSession();
// First, create the attachment placeholder
const attachmentResponse = await this.bunqAccount.getHttpClient().post(
'/v1/attachment-public',
{
description: options.description
}
);
if (!attachmentResponse.Response || !attachmentResponse.Response[0]) {
throw new Error('Failed to create attachment');
}
const attachmentUuid = attachmentResponse.Response[0].Uuid.uuid;
this.uuid = attachmentUuid;
// Upload the actual content
const uploadUrl = `/v1/attachment-public/${attachmentUuid}/content`;
// For file uploads, we need to make a raw request
const headers = {
'Content-Type': options.contentType,
'X-Bunq-Client-Authentication': this.bunqAccount.apiContext.getSession().getContext().sessionToken
};
const requestOptions = {
method: 'PUT' as const,
headers: headers,
requestBody: options.body
};
await plugins.smartrequest.request(
`${this.bunqAccount.apiContext.getBaseUrl()}${uploadUrl}`,
requestOptions
);
return attachmentUuid;
}
/**
* Get attachment content
*/
public async getContent(attachmentUuid: string): Promise<Buffer> {
await this.bunqAccount.apiContext.ensureValidSession();
const response = await plugins.smartrequest.request(
`${this.bunqAccount.apiContext.getBaseUrl()}/v1/attachment-public/${attachmentUuid}/content`,
{
method: 'GET',
headers: {
'X-Bunq-Client-Authentication': this.bunqAccount.apiContext.getSession().getContext().sessionToken
}
}
);
return Buffer.from(response.body);
}
/**
* Create attachment for a specific monetary account
*/
public async createForAccount(
monetaryAccountId: number,
attachmentPublicUuid: string
): Promise<number> {
await this.bunqAccount.apiContext.ensureValidSession();
const response = await this.bunqAccount.getHttpClient().post(
`/v1/user/${this.bunqAccount.userId}/monetary-account/${monetaryAccountId}/attachment`,
{
attachment_public_uuid: attachmentPublicUuid
}
);
if (response.Response && response.Response[0] && response.Response[0].Id) {
this.id = response.Response[0].Id.id;
return this.id;
}
throw new Error('Failed to create account attachment');
}
/**
* List attachments for a monetary account
*/
public static async listForAccount(
bunqAccount: BunqAccount,
monetaryAccountId: number
): Promise<any[]> {
await bunqAccount.apiContext.ensureValidSession();
const response = await bunqAccount.getHttpClient().list(
`/v1/user/${bunqAccount.userId}/monetary-account/${monetaryAccountId}/attachment`
);
return response.Response || [];
}
/**
* Create attachment for a payment
*/
public async createForPayment(
monetaryAccountId: number,
paymentId: number,
attachmentId: number
): Promise<void> {
await this.bunqAccount.apiContext.ensureValidSession();
await this.bunqAccount.getHttpClient().post(
`/v1/user/${this.bunqAccount.userId}/monetary-account/${monetaryAccountId}/payment/${paymentId}/attachment`,
{
id: attachmentId
}
);
}
/**
* Upload image as avatar
*/
public async uploadAvatar(imageBuffer: Buffer, contentType: string = 'image/png'): Promise<string> {
return this.upload({
contentType,
description: 'Avatar image',
body: imageBuffer
});
}
/**
* Upload document
*/
public async uploadDocument(
documentBuffer: Buffer,
contentType: string,
description: string
): Promise<string> {
return this.upload({
contentType,
description,
body: documentBuffer
});
}
/**
* Helper to upload file from filesystem
*/
public async uploadFile(filePath: string, description?: string): Promise<string> {
const fileBuffer = await plugins.smartfile.fs.toBuffer(filePath);
const contentType = this.getContentType(filePath);
return this.upload({
contentType,
description: description || plugins.path.basename(filePath),
body: fileBuffer
});
}
/**
* Get content type from file extension
*/
private getContentType(filePath: string): string {
const ext = plugins.path.extname(filePath).toLowerCase();
const contentTypes: { [key: string]: string } = {
'.jpg': 'image/jpeg',
'.jpeg': 'image/jpeg',
'.png': 'image/png',
'.gif': 'image/gif',
'.pdf': 'application/pdf',
'.txt': 'text/plain',
'.csv': 'text/csv',
'.xml': 'application/xml',
'.json': 'application/json'
};
return contentTypes[ext] || 'application/octet-stream';
}
}
/**
* Tab attachment class for managing receipt attachments
*/
export class BunqTabAttachment {
private bunqAccount: BunqAccount;
private monetaryAccountId: number;
private tabUuid: string;
constructor(bunqAccount: BunqAccount, monetaryAccountId: number, tabUuid: string) {
this.bunqAccount = bunqAccount;
this.monetaryAccountId = monetaryAccountId;
this.tabUuid = tabUuid;
}
/**
* Upload attachment for a tab
*/
public async upload(attachmentPublicUuid: string): Promise<number> {
await this.bunqAccount.apiContext.ensureValidSession();
const response = await this.bunqAccount.getHttpClient().post(
`/v1/user/${this.bunqAccount.userId}/monetary-account/${this.monetaryAccountId}/tab/${this.tabUuid}/attachment`,
{
attachment_public_uuid: attachmentPublicUuid
}
);
if (response.Response && response.Response[0] && response.Response[0].Id) {
return response.Response[0].Id.id;
}
throw new Error('Failed to create tab attachment');
}
/**
* List attachments for a tab
*/
public async list(): Promise<any[]> {
await this.bunqAccount.apiContext.ensureValidSession();
const response = await this.bunqAccount.getHttpClient().list(
`/v1/user/${this.bunqAccount.userId}/monetary-account/${this.monetaryAccountId}/tab/${this.tabUuid}/attachment`
);
return response.Response || [];
}
/**
* Get specific attachment
*/
public async get(attachmentId: number): Promise<any> {
await this.bunqAccount.apiContext.ensureValidSession();
const response = await this.bunqAccount.getHttpClient().get(
`/v1/user/${this.bunqAccount.userId}/monetary-account/${this.monetaryAccountId}/tab/${this.tabUuid}/attachment/${attachmentId}`
);
if (response.Response && response.Response[0]) {
return response.Response[0].TabAttachment;
}
throw new Error('Tab attachment not found');
}
}