From 42086c0d65cb07ef59b452ec68b91140c5864714 Mon Sep 17 00:00:00 2001 From: AuroraHuang22 Date: Wed, 1 Nov 2023 16:11:49 +0800 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20Add=20epubMetadata=20to=20thumbnail?= =?UTF-8?q?=20field?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/IscnRegisterForm.vue | 4 +- components/IscnUploadForm.vue | 189 +++++++++++++++++++------------- utils/cosmos/iscn/iscn.type.ts | 2 + 3 files changed, 119 insertions(+), 76 deletions(-) diff --git a/components/IscnRegisterForm.vue b/components/IscnRegisterForm.vue index fd8bb6e5..d818b144 100644 --- a/components/IscnRegisterForm.vue +++ b/components/IscnRegisterForm.vue @@ -1004,6 +1004,8 @@ export default class IscnRegisterForm extends Vue { likerIdsAddresses: this.likerIdsAddresses, authorDescriptions: this.authorDescriptions, contentFingerprints: this.customContentFingerprints, + inLanguage: this.language, + thumbnail: this.epubMetadata.thumbnail, } } @@ -1084,11 +1086,11 @@ export default class IscnRegisterForm extends Vue { } if (this.epubMetadata) { - console.log('epubMetadata', this.epubMetadata) this.name = this.epubMetadata.title; this.description = this.extractText(this.epubMetadata.description); this.author.name = this.epubMetadata.author; this.language = this.epubMetadata.language + this.tags = this.epubMetadata.tags if (this.author.name) { this.authors.push(this.author) } } diff --git a/components/IscnUploadForm.vue b/components/IscnUploadForm.vue index 8e89d4b7..bdc8c72e 100644 --- a/components/IscnUploadForm.vue +++ b/components/IscnUploadForm.vue @@ -264,7 +264,7 @@ import ePub from 'epubjs'; import { OfflineSigner } from '@cosmjs/proto-signing' -import { IS_CHAIN_UPGRADING, UPLOAD_FILESIZE_MAX } from '~/constant' +import { IS_CHAIN_UPGRADING, UPLOAD_FILESIZE_MAX, IPFS_VIEW_GATEWAY_URL } from '~/constant' import { logTrackerEvent } from '~/utils/logger' import { estimateBundlrFilePrice, uploadSingleFileToBundlr } from '~/utils/arweave/v2' import { @@ -485,7 +485,7 @@ export default class UploadForm extends Vue { } if (file.type === 'application/epub+zip') { // eslint-disable-next-line no-await-in-loop - await this.processEPub({ buffer:fileBytes }) + await this.processEPub({ buffer: fileBytes, file }) } } } else { @@ -496,83 +496,112 @@ export default class UploadForm extends Vue { } } - // eslint-disable-next-line class-methods-use-this - async processEPub({ buffer }: { buffer: ArrayBuffer }) { - try { - const Book = ePub(buffer); - await Book.ready; - const epubMetadata: any = {}; - - // Get metadata - const { metadata } = Book.packaging; - if (metadata) { - epubMetadata.title = metadata.title; - epubMetadata.author = metadata.creator; - epubMetadata.language = metadata.language; - epubMetadata.description = metadata.description; - } + async processEPub({ buffer, file }: { buffer: ArrayBuffer; file: File }) { + try { + const Book = ePub(buffer) + await Book.ready + const epubMetadata: any = {} + + // Get metadata + const { metadata } = Book.packaging + if (metadata) { + epubMetadata.epubFileName = file.name + epubMetadata.title = metadata.title + epubMetadata.author = metadata.creator + epubMetadata.language = this.formatLanguage(metadata.language) + epubMetadata.description = metadata.description + } - // Get tags - const opfFilePath = await (Book.path as any).path; - const opfContent = await Book.archive.getText(opfFilePath); - const parser = new DOMParser(); - const opfDocument = parser.parseFromString(opfContent, 'application/xml'); - const dcSubjectElements = opfDocument.querySelectorAll('dc\\:subject, subject'); - const subjects: string[] = []; - dcSubjectElements.forEach((element) => { - const subject = element.textContent; - subject && subjects.push(subject); - }); - epubMetadata.tags = subjects; + // Get tags + const opfFilePath = await (Book.path as any).path + const opfContent = await Book.archive.getText(opfFilePath) + const parser = new DOMParser() + const opfDocument = parser.parseFromString(opfContent, 'application/xml') + const dcSubjectElements = opfDocument.querySelectorAll( + 'dc\\:subject, subject', + ) + const subjects: string[] = [] + dcSubjectElements.forEach((element) => { + const subject = element.textContent + subject && subjects.push(subject) + }) + epubMetadata.tags = subjects + + // Get cover file + const coverUrl = (Book as any).cover + if (!coverUrl) { + this.epubMetadataList.push(epubMetadata) + return + } - // Get cover file - const coverUrl = (Book as any).cover; - if (!coverUrl) { - this.epubMetadataList.push(epubMetadata); - return; - } + const blobData = await Book.archive.getBlob(coverUrl) + if (blobData) { + const coverFile = new File([blobData], `${metadata.title}_cover.jpeg`, { + type: 'image/jpeg', + }) + + const fileBytes = (await fileToArrayBuffer( + coverFile, + )) as unknown as ArrayBuffer + if (fileBytes) { + const [ + fileSHA256, + imageType, + ipfsHash, + // eslint-disable-next-line no-await-in-loop + ] = await Promise.all([ + digestFileSHA256(fileBytes), + readImageType(fileBytes), + Hash.of(Buffer.from(fileBytes)), + ]) + + const fileRecord: any = { + fileName: coverFile.name, + fileSize: coverFile.size, + fileType: coverFile.type, + fileBlob: coverFile, + ipfsHash, + fileSHA256, + isFileImage: !!imageType, + } - const blobData = await Book.archive.getBlob(coverUrl); - if (blobData) { - const coverFile = new File([blobData], `${metadata.title}_cover.jpeg`, { - type: 'image/jpeg', - }); + epubMetadata.ipfsHash = ipfsHash + epubMetadata.thumbnail = { + "@type": "ImageObject", + url: `${IPFS_VIEW_GATEWAY_URL}${ipfsHash}`, + name: `${file.name}_cover`, + description: `${file.name}_cover`, + encodingFormat: "image/jpeg", + }; - const fileBytes = (await fileToArrayBuffer(coverFile)) as unknown as ArrayBuffer; - if (fileBytes) { - const [ - fileSHA256, - imageType, - ipfsHash, - // eslint-disable-next-line no-await-in-loop - ] = await Promise.all([ - digestFileSHA256(fileBytes), - readImageType(fileBytes), - Hash.of(Buffer.from(fileBytes)), - ]); - - const fileRecord: any = { - fileName: coverFile.name, - fileSize: coverFile.size, - fileType: coverFile.type, - fileBlob: coverFile, - fileData: coverFile, - ipfsHash, - fileSHA256, - isFileImage: !!imageType, - }; - - epubMetadata.fileSHA256 = fileSHA256; - this.epubMetadataList.push(epubMetadata); - this.fileRecords.push(fileRecord); + const reader = new FileReader() + reader.onload = (e) => { + if (!e.target) return + fileRecord.fileData = e.target.result as string + } + reader.readAsDataURL(coverFile) + this.epubMetadataList = [ + ...this.epubMetadataList, + epubMetadata, + ] + this.fileRecords.push(fileRecord) + } } - } else { - this.epubMetadataList.push(epubMetadata); + } catch (err) { + console.error(err) } - } catch (err) { - console.error(err); } -} + + // eslint-disable-next-line class-methods-use-this + formatLanguage(language: string) { + if (language && language.toLowerCase().startsWith('en')) { + return 'en' + } + if (language && language.toLowerCase().startsWith('zh')) { + return 'zh' + } + return language + } onEnterURL() { if ( @@ -595,7 +624,13 @@ export default class UploadForm extends Vue { } handleDeleteFile(index: number) { - this.fileRecords.splice(index, 1) + const deletedFile = this.fileRecords[index]; + this.fileRecords.splice(index, 1); + + const indexToDelete = this.epubMetadataList.findIndex(item => item.epubFileName === deletedFile.fileName); + if (indexToDelete !== -1) { + this.epubMetadataList.splice(indexToDelete, 1); + } } handleClickExifInfo(index: number) { @@ -633,6 +668,10 @@ export default class UploadForm extends Vue { } if (arweaveId) { this.sentArweaveTransactionHashes.set(ipfsHash, { transactionHash: '', arweaveId }); + const metadata = this.epubMetadataList.find((data: any) => data.ipfsHash === ipfsHash) + if (metadata) { + metadata.thumbnail.contentUrl = `https://arweave.net/${arweaveId}`; + } } if (!this.arweaveFeeTargetAddress) { this.arweaveFeeTargetAddress = address; @@ -709,8 +748,8 @@ export default class UploadForm extends Vue { const uploadedData = this.sentArweaveTransactionHashes.get(records.ipfsHash) || {}; this.sentArweaveTransactionHashes.set(records.ipfsHash, { ...uploadedData, arweaveId }); if (tempRecord.fileName === 'cover.jpeg') { - const metadata = this.epubMetadataList.find((file: any) => file.ipfsHash === records.ipfsHash) - metadata.arweaveId = arweaveId + const metadata = this.epubMetadataList.find((file: any) => file.ipfsHash === records.thumbnail.url) + metadata.thumbnail.contentUrl = `https://arweave.net/${arweaveId}` } this.$emit('arweaveUploaded', { arweaveId }) this.isOpenSignDialog = false diff --git a/utils/cosmos/iscn/iscn.type.ts b/utils/cosmos/iscn/iscn.type.ts index d450ead7..377bdffa 100644 --- a/utils/cosmos/iscn/iscn.type.ts +++ b/utils/cosmos/iscn/iscn.type.ts @@ -24,6 +24,8 @@ export interface ISCNRegisterPayload { stakeholders?: any[]; recordNotes?: string; memo?: string; + inLanguage?: string; + thumbnail?: any; } export interface ISCNRecordWithID extends ISCNRecord { id: string;