UNPKG

onix-gen-funstory

Version:

onix generator

397 lines (365 loc) 14.6 kB
import { promises as fs } from 'fs'; import * as path from 'path'; import * as xml2js from 'xml2js'; import moment from 'moment'; const readFile = fs.readFile; // const writeFile = fs.writeFile; // const readdir = fs.readdir; // const copyFile = fs.copyFile; // const mkdir = fs.mkdir; export declare type TCurrencyCode = 'USD' | 'CAD' | 'GBP'; export declare type TCountriesIncluded = 'CA' | 'GB' | 'AT' | 'BE' | 'CY' | 'DE' | 'EE' | 'ES' | 'FI' | 'FR' | 'GR' | 'IE' | 'IT' | 'LT' | 'LU' | 'LV' | 'MT' | 'NL' | 'PT' | 'SI' | 'SK'; export declare type TTranslator = 'Babel Novel' | 'Lemon Novel' | 'Fancy Novel'; export declare interface IBookPrice { currencyCode: TCurrencyCode; priceAmount: number; countriesIncluded: TCountriesIncluded[] | ['WORLD']; } export declare interface IBookOnixInfo { bookName: string; description: string; author: string; volume: number; translator: TTranslator; isbn: string; subjectCode: string; price: IBookPrice[]; keywords: string[]; subTitle?: string; publicationDate?: string; preOrderDate?: string; salesRestriction?: 'ALL' | 'TOP_FIVE' | 'KINDLE_ONLY'; pageCount?: number; takedown?: boolean; } export declare interface IBookChapter { title: string; content: string[]; } export declare interface IinitOption { senderName: string; contactName: string; emailAddress: string; cityOfPublication: string; countryOfManufacture: TCountriesIncluded | 'CN'; publisherName: string; websiteLink: string; } export const xml2jsParser = async (text: string): Promise<any> => { const parser = new xml2js.Parser(); return new Promise((resolve, reject) => { parser.parseString(text, (err: any, result: any) => { if (err) { reject(err); } else { resolve(result); } }); }); }; export class ONIXGenerator { private initOption: IinitOption = { senderName: 'Funstory', contactName: 'Funstory', emailAddress: 'email@email.com', cityOfPublication: 'BeiJing', countryOfManufacture: 'CN', publisherName: 'Funstory', websiteLink: 'https://funstory.ai', }; private tempObj: any; constructor(initOption: IinitOption) { if (initOption) { this.initOption = initOption; } this.tempObj = ''; } public async init(initOption?: IinitOption) { if (initOption) { this.initOption = initOption; } // 读取ONIX模板xml const onixTmp = await readFile(path.join(__dirname, `./onixTmp.xml`)); // ONIX模板xml2js this.tempObj = await xml2jsParser(onixTmp.toString('utf8')); } public getTemp() { return this.tempObj; } public genONIX(bookinfo: IBookOnixInfo): string { if (this.tempObj === '') { throw new Error('please run init() first'); } const onixObj = {...this.tempObj}; onixObj.ONIXMessage.Header[0].Sender[0].SenderName = this.initOption.senderName; onixObj.ONIXMessage.Header[0].Sender[0].ContactName = this.initOption.contactName; onixObj.ONIXMessage.Header[0].Sender[0].EmailAddress = this.initOption.emailAddress; // onixObj.ONIXMessage.Product[0].DescriptiveDetail[0] // .CountryOfManufacture = this.initOption.countryOfManufacture; onixObj.ONIXMessage.Product[0].PublishingDetail[0] .Publisher[0].PublisherName = this.initOption.publisherName; onixObj.ONIXMessage.Product[0].PublishingDetail[0] .Publisher[0].Website[0].WebsiteLink = this.initOption.websiteLink; onixObj.ONIXMessage.Product[0].PublishingDetail[0] .CityOfPublication = this.initOption.cityOfPublication; onixObj.ONIXMessage.Product[0].PublishingDetail[0] .CountryOfPublication = this.initOption.countryOfManufacture; onixObj.ONIXMessage.Product[0].ProductSupply[0] .SupplyDetail[0].Supplier[0].SupplierName = this.initOption.publisherName; // ISBN const isbnNum = bookinfo.isbn; onixObj.ONIXMessage.Product[0].RecordReference = isbnNum; onixObj.ONIXMessage.Product[0].ProductIdentifier[0].IDValue = isbnNum; // 书名 const bookTitle = bookinfo.bookName; const volumeNum = bookinfo.volume; const subTitle = bookinfo.subTitle; onixObj.ONIXMessage.Product[0].DescriptiveDetail[0].TitleDetail[0] .TitleElement[0].TitleText = `${bookTitle}`; // 副标题 onixObj.ONIXMessage.Product[0].DescriptiveDetail[0].TitleDetail[0] .TitleElement[0].Subtitle = subTitle ? subTitle : `Book ${volumeNum}`; // 第几卷(系列号) onixObj.ONIXMessage.Product[0].DescriptiveDetail[0].Collection[0] .CollectionSequence[0].CollectionSequenceNumber = volumeNum; onixObj.ONIXMessage.Product[0].DescriptiveDetail[0].Collection[0] .TitleDetail[0].TitleElement[0].TitleText = `Book ${volumeNum}`; // 作者 const bookAuthor = bookinfo.author.split(' '); const familyName1 = bookAuthor.shift() || ''; const familyName = familyName1[0] ? `${familyName1[0].toUpperCase()}${familyName1.slice(1)}` : ''; const authorName1 = bookAuthor.join(''); const authorName = authorName1[0] ? `${authorName1[0].toUpperCase()}${authorName1.slice(1)}` : ''; // onixObj.ONIXMessage.Product[0].DescriptiveDetail[0].Contributor[0].KeyNames = bookAuthor; onixObj.ONIXMessage.Product[0].DescriptiveDetail[0].Contributor[0].PersonName = `${familyName} ${authorName}`; onixObj.ONIXMessage.Product[0].DescriptiveDetail[0].Contributor[0].PersonNameInverted = `${authorName}, ${familyName}`; // 译者 const bookTranslator = bookinfo.translator.split(' '); if (bookTranslator.length > 0) { onixObj.ONIXMessage.Product[0].DescriptiveDetail[0].Contributor[1].PersonName = `${bookTranslator[0]} ${bookTranslator[1]}`; onixObj.ONIXMessage.Product[0].DescriptiveDetail[0].Contributor[1].PersonNameInverted = `${bookTranslator[1]}, ${bookTranslator[0]}`; } const bookPageCount = bookinfo.pageCount; if (bookPageCount) { // onixObj.ONIXMessage.Product[0].DescriptiveDetail[0].Extent = [{}]; onixObj.ONIXMessage.Product[0].DescriptiveDetail[0].Extent[0].ExtentType = '00'; onixObj.ONIXMessage.Product[0].DescriptiveDetail[0].Extent[0].ExtentValue = bookPageCount; onixObj.ONIXMessage.Product[0].DescriptiveDetail[0].Extent[0].ExtentUnit = '03'; } else { delete onixObj.ONIXMessage.Product[0].DescriptiveDetail[0].Extent; } // 小说类型 详见https://bisg.org/page/Fiction ['FIC008000', 'FIC009000', 'FIC028000'] const aBISACEdition = bookinfo.subjectCode; onixObj.ONIXMessage.Product[0].DescriptiveDetail[0].Subject[0].SubjectCode = aBISACEdition; // 关键词 const bookKeywords = bookinfo.keywords; if (bookKeywords.length > 0) { onixObj.ONIXMessage.Product[0].DescriptiveDetail[0].Subject[1] = {}; onixObj.ONIXMessage.Product[0].DescriptiveDetail[0].Subject[1].SubjectSchemeIdentifier = 20; onixObj.ONIXMessage.Product[0].DescriptiveDetail[0] .Subject[1].SubjectHeadingText = bookKeywords.join('; '); } // 小说简介 const description = bookinfo.description.replace(/(\r|\n)+/g, '').trim(); onixObj.ONIXMessage.Product[0].CollateralDetail[0].TextContent[0].Text[0]._ = description; const nowdate = moment(); const publicationDate = bookinfo.publicationDate ? moment(bookinfo.publicationDate) : nowdate; const preOrderDate = bookinfo.preOrderDate ? moment(bookinfo.preOrderDate) : undefined; const publicationDateTime = parseInt(publicationDate.format('x'), 10); const nowDateTime = parseInt(nowdate.format('x'), 10); // 是否未发布 根据发布日期是否大于当前日期对比 const noPublushed: boolean = publicationDateTime > nowDateTime; // 发送日期 onixObj.ONIXMessage.Header[0].SentDateTime = nowdate.format('YYYYMMDDTHHmm'); // 出版日期 onixObj.ONIXMessage.Product[0].PublishingDetail[0].PublishingDate[0] = { PublishingDateRole: ['01'], Date: [{ $: { dateformat: '00' }, _: publicationDate.format('YYYYMMDD'), }], }; // 解禁日期 onixObj.ONIXMessage.Product[0].PublishingDetail[0].PublishingDate[1] = { PublishingDateRole: ['02'], Date: [{ $: { dateformat: '00' }, _: publicationDate.format('YYYYMMDD'), }], }; // 上市日期 onixObj.ONIXMessage.Product[0].ProductSupply[0]. MarketPublishingDetail[0].MarketDate[0].Date[0]._ = publicationDate.format('YYYYMMDD'); // 是否可用 10 Not yet available, 20 Available onixObj.ONIXMessage.Product[0].ProductSupply[0].SupplyDetail[0] .ProductAvailability[0] = noPublushed ? '10' : '20'; // 出版状态 04 Active, 02 Forthcoming onixObj.ONIXMessage.Product[0].PublishingDetail[0].PublishingStatus[0] = noPublushed ? '02' : '04'; onixObj.ONIXMessage.Product[0].ProductSupply[0].MarketPublishingDetail[0].MarketPublishingStatus[0] = noPublushed ? '02' : '04'; // 预售信息 if (preOrderDate && (parseInt(preOrderDate.format('x'), 10) < publicationDateTime)) { // 预售日期 onixObj.ONIXMessage.Product[0].PublishingDetail[0].PublishingDate[2] = { PublishingDateRole: ['09'], Date: [{ $: { dateformat: '00' }, _: preOrderDate.format('YYYYMMDD'), }], }; } // if (noPublushed) { // onixObj.ONIXMessage.Product[0].ProductSupply[0].SupplyDetail[0].SupplyDate = []; // onixObj.ONIXMessage.Product[0].ProductSupply[0].SupplyDetail[0].SupplyDate[0] = { // SupplyDateRole: '02', // Date: [{ // $: { dateformat: '00' }, // _: publicationDate.format('YYYYMMDD'), // }], // }; // onixObj.ONIXMessage.Product[0].ProductSupply[0].SupplyDetail[0].SupplyDate[1] = { // SupplyDateRole: '08', // Date: [{ // $: { dateformat: '00' }, // _: publicationDate.format('YYYYMMDD'), // }], // }; // } const salesRestriction = bookinfo.salesRestriction || 'KINDLE_ONLY'; switch (salesRestriction) { case 'KINDLE_ONLY': onixObj.ONIXMessage.Product[0].PublishingDetail[0].SalesRestriction = []; onixObj.ONIXMessage.Product[0].PublishingDetail[0].SalesRestriction[0] = { SalesRestrictionType: ['04'], SalesOutlet: [ { SalesOutletIdentifier: [{ SalesOutletIDType: ['03'], IDValue: ['AMZ'] }], SalesOutletName: ['Amazon eBookBase'] }, ], }; break; case 'TOP_FIVE': onixObj.ONIXMessage.Product[0].PublishingDetail[0].SalesRestriction = []; onixObj.ONIXMessage.Product[0].PublishingDetail[0].SalesRestriction[0] = { SalesRestrictionType: ['04'], SalesOutlet: [ { SalesOutletIdentifier: [{ SalesOutletIDType: ['03'], IDValue: ['AMZ'] }], SalesOutletName: ['Amazon eBookBase'] }, // { // SalesOutletIdentifier: [{ // SalesOutletIDType: ['03'], // IDValue: ['BNO'] // }], // SalesOutletName: ['Barnes And Noble'] // }, { SalesOutletIdentifier: [{ SalesOutletIDType: ['03'], IDValue: ['GOO'] }], SalesOutletName: ['Google Books'] }, { SalesOutletIdentifier: [{ SalesOutletIDType: ['03'], IDValue: ['APC'] }], SalesOutletName: ['iBookstore'] }, { SalesOutletIdentifier: [{ SalesOutletIDType: ['03'], IDValue: ['KBO'] }], SalesOutletName: ['Kobo'] }, ], }; break; default: onixObj.ONIXMessage.Product[0].PublishingDetail[0].SalesRestriction = []; onixObj.ONIXMessage.Product[0].PublishingDetail[0].SalesRestriction[0] = { SalesRestrictionType: ['04'], SalesOutlet: [ { SalesOutletIdentifier: [{ SalesOutletIDType: ['03'], IDValue: ['AMZ'] }], SalesOutletName: ['Amazon eBookBase'] }, // { // SalesOutletIdentifier: [{ // SalesOutletIDType: ['03'], // IDValue: ['BNO'] // }], // SalesOutletName: ['Barnes And Noble'] // }, { SalesOutletIdentifier: [{ SalesOutletIDType: ['03'], IDValue: ['GOO'] }], SalesOutletName: ['Google Books'] }, { SalesOutletIdentifier: [{ SalesOutletIDType: ['03'], IDValue: ['APC'] }], SalesOutletName: ['iBookstore'] }, { SalesOutletIdentifier: [{ SalesOutletIDType: ['03'], IDValue: ['KBO'] }], SalesOutletName: ['Kobo'] }, ], }; break; } // 地区及当地价格 const priceInfo = bookinfo.price; onixObj.ONIXMessage.Product[0].ProductSupply[0] .SupplyDetail[0].Price = priceInfo.map((price: any) => ({ PriceType: '01', PriceStatus: '01', PriceAmount: price.priceAmount, CurrencyCode: price.currencyCode, Territory: [ (price.countriesIncluded.length === 1 && price.countriesIncluded[0] === 'WORLD') ? ( { RegionsIncluded: price.countriesIncluded[0], CountriesExcluded: 'CN', } ) : ( { CountriesIncluded: price.countriesIncluded.join(' '), } ) ] })); // 返回ONIX xml // 下架ONIX if (bookinfo.takedown){ onixObj.ONIXMessage.Product[0].NotificationType[0] = '04'; onixObj.ONIXMessage.Product[0].ProductSupply[0].SupplyDetail[0] .ProductAvailability[0] = '51'; onixObj.ONIXMessage.Product[0].PublishingDetail[0].PublishingStatus[0] = '07'; onixObj.ONIXMessage.Product[0].ProductSupply[0].MarketPublishingDetail[0] .MarketPublishingStatus[0] = '07'; } const js2xmlBuilder2 = new xml2js.Builder({ renderOpts: { pretty: true } }); return js2xmlBuilder2.buildObject(onixObj); } }