fix: attachment

This commit is contained in:
abdou6666 2025-04-11 16:40:50 +01:00
parent 33cc3f713d
commit 8bd778db52
5 changed files with 59 additions and 57 deletions

View File

@ -6,74 +6,27 @@
* 2. All derivative works must include clear attribution to the original creator and software, Hexastack and Hexabot, in a prominent location (e.g., in the software's "About" section, documentation, and README file).
*/
import fs from 'fs';
import path from 'path';
import { Readable, Stream } from 'stream';
import {
Injectable,
OnApplicationBootstrap,
Optional,
StreamableFile,
} from '@nestjs/common';
import { Injectable, Optional, StreamableFile } from '@nestjs/common';
import { HelperService } from '@/helper/helper.service';
import { HelperType } from '@/helper/types';
import { SettingService } from '@/setting/services/setting.service';
import { BaseService } from '@/utils/generics/base-service';
import { AttachmentMetadataDto } from '../dto/attachment.dto';
import { AttachmentRepository } from '../repositories/attachment.repository';
import { Attachment } from '../schemas/attachment.schema';
import {
AttachmentAccess,
AttachmentCreatedByRef,
AttachmentResourceRef,
} from '../types';
@Injectable()
export class AttachmentService
extends BaseService<Attachment>
implements OnApplicationBootstrap
{
export class AttachmentService extends BaseService<Attachment> {
constructor(
readonly repository: AttachmentRepository,
@Optional() private readonly helperService: HelperService,
private settingService: SettingService,
) {
super(repository);
}
async onApplicationBootstrap() {
debugger;
const defaultAttachment = await this.repository.findOne({
createdByRef: AttachmentCreatedByRef.System,
});
if (!defaultAttachment) {
const imagePath = path.join(process.cwd(), 'assets', 'hexavatar.png');
// console.log({ imagePath });
const imageBuffer = fs.readFileSync(imagePath);
const result = await this.store(imageBuffer, {
access: AttachmentAccess.Public,
name: 'hexavatar.png',
createdBy: 'system',
size: imageBuffer.length,
type: 'png',
createdByRef: AttachmentCreatedByRef.System,
resourceRef: AttachmentResourceRef.SettingAttachment,
channel: {
'web-channel': '',
'console-channel': '',
'discord-channel': '',
'whatsapp-channel': '',
},
});
console.log({ result });
console.log({ result });
}
//
}
/**
* Stores a file using the default storage helper and creates an attachment record.
*

View File

@ -1,5 +1,5 @@
/*
* Copyright © 2024 Hexastack. All rights reserved.
* Copyright © 2025 Hexastack. All rights reserved.
*
* Licensed under the GNU Affero General Public License v3.0 (AGPLv3) with the following additional terms:
* 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission.
@ -11,6 +11,9 @@ import { EventEmitter2 } from '@nestjs/event-emitter';
import { MongooseModule } from '@nestjs/mongoose';
import { AttachmentModule } from '@/attachment/attachment.module';
import { AttachmentRepository } from '@/attachment/repositories/attachment.repository';
import { AttachmentModel } from '@/attachment/schemas/attachment.schema';
import { AttachmentService } from '@/attachment/services/attachment.service';
import { ChannelModule } from '@/channel/channel.module';
import { CmsModule } from '@/cms/cms.module';
import { UserModule } from '@/user/user.module';
@ -58,8 +61,10 @@ import { SubscriberService } from './services/subscriber.service';
SubscriberModel,
ConversationModel,
SubscriberModel,
AttachmentModel,
]),
forwardRef(() => ChannelModule),
AttachmentModule,
CmsModule,
AttachmentModule,
EventEmitter2,
@ -92,6 +97,8 @@ import { SubscriberService } from './services/subscriber.service';
ConversationService,
ChatService,
BotService,
AttachmentService,
AttachmentRepository,
],
exports: [
SubscriberService,

View File

@ -11,8 +11,14 @@ import {
InternalServerErrorException,
Optional,
} from '@nestjs/common';
import { OnEvent } from '@nestjs/event-emitter';
import { Document, Query } from 'mongoose';
import { Attachment } from '@/attachment/schemas/attachment.schema';
import { AttachmentService } from '@/attachment/services/attachment.service';
import { DeleteResult } from '@/utils/generics/base-repository';
import { BaseService } from '@/utils/generics/base-service';
import { TFilterQuery } from '@/utils/types/filter.types';
import {
SocketGet,
SocketPost,
@ -39,6 +45,7 @@ export class MessageService extends BaseService<
constructor(
private readonly messageRepository: MessageRepository,
private attachmentService: AttachmentService,
@Optional() gateway?: WebsocketGateway,
) {
super(messageRepository);
@ -127,4 +134,41 @@ export class MessageService extends BaseService<
return lastMessages.reverse();
}
@OnEvent('hook:attachment:preDelete')
async handleDeleteImage(
_query: Query<
DeleteResult,
Document<Attachment, any, any>,
unknown,
Attachment,
'deleteOne' | 'deleteMany'
>,
criteria: TFilterQuery<Attachment>,
) {
// todo: handle deleteMany
try {
this.logger.log(
'deleting attachment messages containing deleted images',
criteria,
);
const foundAttachment = await this.attachmentService.findOne(criteria);
if (!foundAttachment) {
return;
}
await this.updateMany(
{
'message.attachment.payload.id': criteria._id,
},
{
['message.attachment.payload.id' as any]: null,
},
);
} catch (error) {
this.logger.error(
'Unable to cleanup old messages with attachment ids',
error,
);
}
}
}

View File

@ -33,7 +33,7 @@ const componentMap: { [key in FileType]: FC<AttachmentInterface> } = {
const [imageErrored, setImageErrored] = useState(false);
const { t } = useTranslate();
if (imageErrored) {
if (imageErrored || !url) {
return <p>{t("message.image_error")}</p>;
}
if (url)
@ -68,8 +68,8 @@ const componentMap: { [key in FileType]: FC<AttachmentInterface> } = {
const [audioErrored, setAudioErrored] = useState(false);
const { t } = useTranslate();
if (audioErrored) {
return <p>{t("message.video_error")}</p>;
if (audioErrored || !props.url) {
return <p>{t("message.audio_error")}</p>;
}
return (

View File

@ -1,5 +1,5 @@
/*
* Copyright © 2024 Hexastack. All rights reserved.
* Copyright © 2025 Hexastack. All rights reserved.
*
* Licensed under the GNU Affero General Public License v3.0 (AGPLv3) with the following additional terms:
* 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission.
@ -24,7 +24,6 @@ const FileMessage: React.FC<FileMessageProps> = ({ message }) => {
const colors = allColors[message.direction || Direction.received];
const [videoErrored, setVideoErrored] = useState(false);
const [audioErrored, setAudioErrored] = useState(false);
const [fileErrored, setFileErrored] = useState(false);
const [imageErrored, setImageErrored] = useState(false);
if (!("type" in message.data)) {
@ -117,8 +116,7 @@ const FileMessage: React.FC<FileMessageProps> = ({ message }) => {
backgroundColor: colors.bg,
}}
>
{!message?.data?.url ||
message?.data?.url?.includes("webhook/download/not-found") ? (
{!message?.data?.url ? (
<p className="error-message" style={{ padding: 0 }}>
{t("messages.file_message.file_error")}
</p>