diff --git a/src/LegacySocket/business.ts b/src/LegacySocket/business.ts new file mode 100644 index 0000000..e061f1b --- /dev/null +++ b/src/LegacySocket/business.ts @@ -0,0 +1,154 @@ +import { LegacySocketConfig } from '../Types' +import { CatalogResult, Product, ProductCreate, ProductCreateResult, ProductUpdate } from '../Types' +import makeGroupsSocket from './groups' + +const makeBusinessSocket = (config: LegacySocketConfig) => { + const sock = makeGroupsSocket(config) + const { + query, + generateMessageTag, + state + } = sock + + const getCatalog = async(jid?: string, limit = 10) => { + jid = jid || state.legacy?.user?.id + + const result: CatalogResult = await query({ + expect200: true, + json: [ + 'query', + 'bizCatalog', + { + allowShopSource: false, + catalogWid: jid, + height: 100, + width: 100, + limit, + stanza_id: generateMessageTag(true), + type: 'get_product_catalog_reh', + } + ] + }) + + const products = result.data.data.map( + mapProduct + ) + + return { + beforeCursor: result.data.paging.cursors.before, + products + } + } + + const productCreate = async(product: ProductCreate) => { + const result: ProductCreateResult = await query({ + expect200: true, + json: [ + 'action', + 'addProduct_reh', + mapProductCreate(product) + ] + }) + + return mapProduct(result.data.product) + } + + const productDelete = async(productIds: string[]) => { + const result = await query({ + expect200: true, + json: [ + 'action', + 'deleteProduct_reh', + { + product_ids: productIds, + stanza_id: generateMessageTag(true), + } + ] + }) + + return { + deleted: result.data.deleted_count + } + } + + const productUpdate = async(productId: string, update: ProductUpdate) => { + const result: ProductCreateResult = await query({ + expect200: true, + json: [ + 'action', + 'editProduct_reh', + { + product_id: productId, + ...mapProductCreate( + { ...update, originCountryCode: undefined }, + false + ) + } + ] + }) + + return mapProduct(result.data.product) + } + + // maps product create to send to WA + const mapProductCreate = (product: ProductCreate, mapCompliance = true) => { + const result: any = { + name: product.name, + description: product.description, + image_url: product.imageUrls[0], + url: product.url || '', + additional_image_urls: product.imageUrls.slice(1), + retailer_id: product.retailerId || '', + width: '100', + height: '100', + stanza_id: generateMessageTag(true), + price: product.price.toString(), + currency: product.currency + } + if(mapCompliance) { + Object.assign(result, { + compliance_category: product.originCountryCode + ? undefined : + 'COUNTRY_ORIGIN_EXEMPT', + compliance_info: product.originCountryCode + ? { country_code_origin: product.originCountryCode } + : undefined + }) + } + + return result + } + + return { + ...sock, + getCatalog, + productCreate, + productDelete, + productUpdate + } +} + +const mapProduct = (item: any): Product => ({ + id: item.id, + name: item.name, + retailerId: item.retailer_id, + price: +item.price, + description: item.description, + currency: item.currency, + imageUrls: item.image_cdn_urls.reduce( + (dict, { key, value }) => { + dict[key] = value + return dict + }, { } + ), + reviewStatus: item.capability_to_review_status.reduce( + (dict, { key, value }) => { + dict[key] = value + return dict + }, { } + ), + isHidden: item.is_hidden, + availability: item.availability +}) + +export default makeBusinessSocket \ No newline at end of file diff --git a/src/LegacySocket/index.ts b/src/LegacySocket/index.ts index 78caed4..93bb492 100644 --- a/src/LegacySocket/index.ts +++ b/src/LegacySocket/index.ts @@ -1,6 +1,6 @@ import { DEFAULT_LEGACY_CONNECTION_CONFIG } from '../Defaults' import { LegacySocketConfig } from '../Types' -import _makeLegacySocket from './groups' +import _makeLegacySocket from './business' // export the last socket layer const makeLegacySocket = (config: Partial) => ( _makeLegacySocket({ diff --git a/src/Types/Product.ts b/src/Types/Product.ts new file mode 100644 index 0000000..7c15c80 --- /dev/null +++ b/src/Types/Product.ts @@ -0,0 +1,39 @@ + +export type CatalogResult = { + data: { + paging: { cursors: { before: string, after: string } }, + data: any[] + } +} + +export type ProductCreateResult = { + data: { product: any } +} + +export type ProductAvailability = 'in stock' + +export type ProductBase = { + name: string + retailerId?: string + url?: string + description: string + price: number + currency: string + isHidden?: boolean +} + +export type ProductCreate = ProductBase & { + /** ISO country code for product origin. Set to undefined for no country */ + originCountryCode: string | undefined + + imageUrls: string[] +} + +export type ProductUpdate = Omit + +export type Product = ProductBase & { + id: string + imageUrls: { [_: string]: string } + reviewStatus: { [_: string]: string } + availability: ProductAvailability +} \ No newline at end of file diff --git a/src/Types/index.ts b/src/Types/index.ts index c0c0a11..624721e 100644 --- a/src/Types/index.ts +++ b/src/Types/index.ts @@ -7,6 +7,7 @@ export * from './Message' export * from './Legacy' export * from './Socket' export * from './Events' +export * from './Product' import type NodeCache from 'node-cache' import { proto } from '../../WAProto'