UNPKG

@kadam-net/n8n-nodes-kadam

Version:

Kadam node for n8n to manage campaigns, creatives, and more.

509 lines 26.5 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.createCampaign = createCampaign; exports.updateCampaign = updateCampaign; exports.deleteCampaign = deleteCampaign; exports.getCampaigns = getCampaigns; exports.getCampaignCategories = getCampaignCategories; exports.getAdFormats = getAdFormats; exports.updatePlacementMultiplier = updatePlacementMultiplier; const n8n_workflow_1 = require("n8n-workflow"); const utils_1 = require("./utils"); async function createCampaign() { var _a; this.logger.debug('Entered createCampaign function.'); const items = this.getInputData(); const returnData = []; const length = items.length; const credentials = await this.getCredentials('kadam'); const token = credentials.apiToken; const appId = credentials.appId; const baseUrl = 'https://api.kadam.net'; const headers = { 'Content-Type': 'application/json', Authorization: `Bearer ${token}`, }; for (let i = 0; i < length; i++) { try { this.logger.debug(`Attempting to get parameter: campaignName for item ${i}`); const campaignName = this.getNodeParameter('campaignName', i); this.logger.debug(`Got campaignName: ${campaignName}`); if (!campaignName) throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Missing required parameter 'campaignName' for item ${i}`); this.logger.debug(`Attempting to get parameter: adFormatId for item ${i}`); const adFormatId = this.getNodeParameter('adFormatId', i); this.logger.debug(`Got adFormatId: ${adFormatId}`); if (adFormatId === undefined || adFormatId === null) throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Missing required parameter 'adFormatId' for item ${i}`); this.logger.debug(`Attempting to get parameter: priceModel for item ${i}`); const priceModel = this.getNodeParameter('priceModel', i); this.logger.debug(`Got priceModel: ${priceModel}`); if (!priceModel) throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Missing required parameter 'priceModel' for item ${i}`); const costTypeMap = { cpc: 0, cpm: 2, cpa: 1 }; const costType = costTypeMap[priceModel.toLowerCase()]; this.logger.debug(`Derived costType: ${costType}`); if (costType === undefined) throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Invalid 'priceModel' value '${priceModel}' for item ${i}. Expected 'cpc', 'cpm', or 'cpa'.`); this.logger.debug(`Attempting to get parameter: targetUrl for item ${i}`); const targetUrl = this.getNodeParameter('targetUrl', i); this.logger.debug(`Got targetUrl: ${targetUrl}`); if (!targetUrl) throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Missing required parameter 'targetUrl' for item ${i}`); this.logger.debug(`Attempting to get parameter: countryTargetCollection for item ${i}`); const countryTargetCollection = this.getNodeParameter('countryTargetCollection', i, { countryTargetValues: [] }); this.logger.debug(`Got countryTargetCollection: ${JSON.stringify(countryTargetCollection)}`); const countryTarget = {}; for (const item of countryTargetCollection.countryTargetValues || []) { countryTarget[item.countryId] = { bid: item.bid }; } this.logger.debug(`Converted to countryTarget format: ${JSON.stringify(countryTarget)}`); this.logger.debug(`Attempting to get parameter: categories for item ${i}`); const categories = this.getNodeParameter('categories', i); this.logger.debug(`Got categories: ${JSON.stringify(categories)}`); if (!categories || !Array.isArray(categories) || categories.length === 0) throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Missing or invalid required parameter 'categories' for item ${i}. Expected a non-empty array of IDs.`); this.logger.debug(`Attempting to get parameter: status for item ${i}`); const statusInput = this.getNodeParameter('status', i, ''); this.logger.debug(`Got status input: ${statusInput}`); this.logger.debug(`Attempting to get parameter: additionalOptions for item ${i}`); const additionalOptions = this.getNodeParameter('additionalOptions', i, {}); this.logger.debug(`Got additionalOptions object: ${JSON.stringify(additionalOptions)}`); this.logger.debug(`Validating parameters for item ${i}`); if (!campaignName) throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Missing required parameter 'campaignName' for item ${i}.`); if (adFormatId === undefined || adFormatId === null) throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Missing required parameter 'adFormatId' for item ${i}.`); if (!priceModel) throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Missing required parameter 'priceModel' for item ${i}.`); if (!targetUrl) throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Missing required parameter 'targetUrl' for item ${i}.`); if (!countryTarget || typeof countryTarget !== 'object' || Object.keys(countryTarget).length === 0) { this.logger.error(`Validation failed: countryTarget is not a non-empty object. Type: ${typeof countryTarget}, Value: ${JSON.stringify(countryTarget)}`); throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Missing or invalid required parameter 'countryTarget' for item ${i}. Expected a non-empty JSON object.`); } if (!categories || categories.length === 0) throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Missing required parameter 'categories' for item ${i}.`); const data = { client_id: appId, ad_format: adFormatId, cost_type: costType, name: campaignName, link_url: targetUrl, sex: 3, age: '0', real_url: targetUrl, categories: categories, countryTarget: countryTarget, status: statusInput === 0 ? 0 : 1, }; if (additionalOptions.dayLimit !== undefined && additionalOptions.dayLimit !== null) data.day_limit = additionalOptions.dayLimit; if (additionalOptions.allLimit !== undefined && additionalOptions.allLimit !== null) data.all_limit = additionalOptions.allLimit; if (additionalOptions.clickLimit !== undefined && additionalOptions.clickLimit !== null) data.click_limit = additionalOptions.clickLimit; if (additionalOptions.langTarget) data.langTarget = additionalOptions.langTarget; if (additionalOptions.deviceTarget) data.deviceTarget = additionalOptions.deviceTarget; const optionalApiFields = [ 'pushType', 'regionTarget', 'cityTarget', 'cpa_mode', 'tags', 'conversion_limit', 'adult_content', 'adult_site', 'time_show', 'platforms', 'browsers', 'black_list', 'white_list', 'black_list_ip', 'unique_day_count', 'unique_days', ]; for (const fieldName of optionalApiFields) { if (additionalOptions[fieldName] !== undefined && additionalOptions[fieldName] !== null && additionalOptions[fieldName] !== '') { data[fieldName] = additionalOptions[fieldName]; } } const requestUrl = `${baseUrl}/ads.campaigns.put`; const campaignDataArrayString = JSON.stringify([data]); const queryParams = { app_id: appId, data: campaignDataArrayString, }; this.logger.debug(`Making GET request to ${requestUrl} with query params: ${JSON.stringify(queryParams)}`); const response = await utils_1.makeApiRequest.call(this, 'get', requestUrl, headers, queryParams); this.logger.debug(`API Response received for campaign create.`); if (Array.isArray(response) && ((_a = response[0]) === null || _a === void 0 ? void 0 : _a.error_code)) { const apiError = response[0]; this.logger.debug(`Kadam API Error Response: ${JSON.stringify(apiError)}`); const errorMessage = `Kadam API error (${apiError.error_code}): ${apiError.error_desc || 'Unknown error'}`; const error = new Error(errorMessage); error.kadamError = apiError; throw new n8n_workflow_1.NodeApiError(this.getNode(), { error: apiError }, error); } else { this.logger.debug(`Kadam API Success Response structure: ${JSON.stringify(response).substring(0, 100)}...`); } if ((0, utils_1.isContinueOnFailError)(response)) { returnData.push({ json: response }); } else { returnData.push({ json: response }); } } catch (error) { if (this.continueOnFail()) { const errorItem = { json: { error: error.message }, }; returnData.push(errorItem); continue; } throw error; } } return returnData; } async function updateCampaign() { const items = this.getInputData(); const returnData = []; const length = items.length; const credentials = await this.getCredentials('kadam'); const token = credentials.apiToken; const appId = credentials.appId; const baseUrl = 'https://api.kadam.net'; const headers = { 'Content-Type': 'application/json', Authorization: `Bearer ${token}`, }; for (let i = 0; i < length; i++) { try { const campaignId = this.getNodeParameter('campaignId', i); if (!campaignId) { throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Campaign ID is required for update operation.', { itemIndex: i }); } const additionalOptions = this.getNodeParameter('additionalOptions', i, {}); this.logger.info(`Reading additionalOptions for update: ${JSON.stringify(additionalOptions)}`); const allParams = this.getNode().parameters; this.logger.info(`Node parameters configuration: ${JSON.stringify(allParams)}`); const name = additionalOptions.name || ''; const targetUrl = additionalOptions.targetUrl || ''; const categories = additionalOptions.categories || []; const status = additionalOptions.status !== undefined ? additionalOptions.status : ''; this.logger.debug(`Getting countryTargetCollection for campaign update ${campaignId} (item ${i})`); const countryTargetCollection = additionalOptions.countryTargetCollection || { countryTargetValues: [] }; const countryTarget = {}; if (countryTargetCollection.countryTargetValues) { for (const item of countryTargetCollection.countryTargetValues) { countryTarget[item.countryId] = { bid: item.bid }; } } this.logger.debug(`Converted country targeting for update: ${JSON.stringify(countryTarget)}`); const data = { client_id: appId, campaign_id: campaignId, }; if (name) data.name = name; if (targetUrl) data.link_url = targetUrl; if (Object.keys(countryTarget).length > 0) { data.countryTarget = countryTarget; } if (categories && categories.length > 0) data.categories = categories; if (status !== '' && status !== undefined) data.status = status; if (additionalOptions.dayLimit) data.day_limit = additionalOptions.dayLimit; if (additionalOptions.allLimit) data.all_limit = additionalOptions.allLimit; if (additionalOptions.clickLimit) data.click_limit = additionalOptions.clickLimit; if (additionalOptions.conversionLimit) data.conversion_limit = additionalOptions.conversionLimit; if (additionalOptions.adult_content !== undefined) data.adult_content = additionalOptions.adult_content; if (additionalOptions.adult_site !== undefined) data.adult_site = additionalOptions.adult_site; if (additionalOptions.realUrl) data.real_url = additionalOptions.realUrl; if (additionalOptions.sex) data.sex = additionalOptions.sex; if (additionalOptions.age) data.age = additionalOptions.age; if (additionalOptions.regionTarget) data.regionTarget = additionalOptions.regionTarget.toString().split(',').map(Number); if (additionalOptions.cityTarget) data.cityTarget = additionalOptions.cityTarget.toString().split(',').map(Number); if (additionalOptions.deviceTarget) data.deviceTarget = additionalOptions.deviceTarget.toString().split(',').map(Number); if (additionalOptions.langTarget) data.langTarget = additionalOptions.langTarget.toString().split(',').map(Number); if (additionalOptions.platforms) data.platforms = additionalOptions.platforms.toString().split(',').map(Number); if (additionalOptions.browsers) data.browsers = additionalOptions.browsers.toString().split(',').map(Number); if (additionalOptions.tags) data.tags = additionalOptions.tags; if (additionalOptions.blackList) data.blackList = additionalOptions.blackList.toString().split(',').map(Number); if (additionalOptions.whiteList) data.whiteList = additionalOptions.whiteList.toString().split(',').map(Number); if (additionalOptions.blackListIp) data.blackListIp = additionalOptions.blackListIp.split(',').map((item) => item.trim()); if (Object.keys(data).length <= 2) { returnData.push({ json: { warning: 'No parameters provided to update.', campaignId: campaignId } }); continue; } this.logger.info(`Updating campaign ${campaignId} with data: ${JSON.stringify(data)}`); this.logger.info(`additionalOptions content: ${JSON.stringify(additionalOptions)}`); const requestUrl = `${baseUrl}/ads.campaigns.update`; const dataString = JSON.stringify(data); const queryParams = { app_id: appId, data: dataString, }; this.logger.info(`⚠️ DEBUG: Making GET request to ${requestUrl}`); this.logger.info(`⚠️ DEBUG: Query params: ${JSON.stringify(queryParams)}`); this.logger.info(`⚠️ DEBUG: Raw dataString: ${dataString}`); const response = await utils_1.makeApiRequest.call(this, 'get', requestUrl, headers, queryParams); if ((0, utils_1.isContinueOnFailError)(response)) { returnData.push({ json: response }); } else { returnData.push({ json: response }); } } catch (error) { if (this.continueOnFail()) { const errorItem = { json: { error: error.message }, }; returnData.push(errorItem); continue; } throw error; } } return returnData; } async function deleteCampaign() { const items = this.getInputData(); const returnData = []; const length = items.length; const credentials = await this.getCredentials('kadam'); const token = credentials.apiToken; const appId = credentials.appId; const baseUrl = 'https://api.kadam.net'; const headers = { 'Content-Type': 'application/json', Authorization: `Bearer ${token}`, }; for (let i = 0; i < length; i++) { const campaignIds = this.getNodeParameter('ids', i); if (!campaignIds || campaignIds.length === 0) { if (this.continueOnFail()) { const errorItem = { json: { error: 'Campaign IDs are required for delete operation.' }, }; returnData.push(errorItem); continue; } else { throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Campaign IDs are required for delete operation.', { itemIndex: i }); } } const queryParams = { app_id: appId, ids: campaignIds.join(','), }; try { const response = await utils_1.makeApiRequest.call(this, 'get', `${baseUrl}/ads.campaigns.delete`, headers, queryParams); if ((0, utils_1.isContinueOnFailError)(response)) { returnData.push({ json: response }); } else { returnData.push({ json: response || { success: true } }); } } catch (error) { if (this.continueOnFail()) { const errorItem = { json: { error: error.message }, }; returnData.push(errorItem); continue; } throw error; } } return returnData; } async function getCampaigns(i, baseUrl, headers, appId) { var _a, _b, _c, _d, _e, _f; const params = { app_id: appId, client_id: appId, campaign_ids: this.getNodeParameter('campaignIds', i, null), }; const includeDataOptions = this.getNodeParameter('includeDataOptions', i, []); const outputFieldsRaw = this.getNodeParameter('outputFields', i, ''); params.include_archive = includeDataOptions.includes('includeArchive'); params.with_bwlist = includeDataOptions.includes('withBwlist'); params.with_materials = includeDataOptions.includes('withCreatives'); const fullResponseArray = await utils_1.fetchAll.call(this, `${baseUrl}/ads.campaigns.get`, headers, params); console.log('--- Kadam GetCampaigns Debug ---'); console.log('Keys of fullResponseArray:', Object.keys(fullResponseArray || {})); if (fullResponseArray === null || fullResponseArray === void 0 ? void 0 : fullResponseArray.response) { console.log('Keys of fullResponseArray.response:', Object.keys(fullResponseArray.response)); if (fullResponseArray.response.items) { console.log('First item in fullResponseArray.response.items:', JSON.stringify((_b = (_a = fullResponseArray.response.items) === null || _a === void 0 ? void 0 : _a[0]) !== null && _b !== void 0 ? _b : 'items missing or empty', null, 2)); } else { console.log('fullResponseArray.response.items does not exist.'); } } else { console.log('fullResponseArray.response does not exist.'); } const campaignItems = (_d = (_c = fullResponseArray === null || fullResponseArray === void 0 ? void 0 : fullResponseArray.response) === null || _c === void 0 ? void 0 : _c.items) !== null && _d !== void 0 ? _d : []; const fieldsToKeep = outputFieldsRaw .split(',') .map((f) => f.trim()) .filter((f) => f); console.log('--- Kadam GetCampaigns Debug ---'); console.log('Output Fields Raw:', outputFieldsRaw); console.log('Fields to Keep:', fieldsToKeep); console.log('Applying filter:', fieldsToKeep.length > 0); console.log('Number of extracted campaignItems:', campaignItems.length); console.log('------------------------------'); if (campaignItems.length > 0) { if (fieldsToKeep.length > 0) { const filteredCampaigns = campaignItems.map((item) => { const filteredCampaign = {}; for (const path of fieldsToKeep) { const value = getValueByPath(item, path); if (value !== undefined) { setValueByPath(filteredCampaign, path, value); } } return filteredCampaign; }); console.log('--- Final Check Before Return (Filtering Applied) ---'); console.log('Returning filteredCampaigns (first item):', JSON.stringify((_e = filteredCampaigns === null || filteredCampaigns === void 0 ? void 0 : filteredCampaigns[0]) !== null && _e !== void 0 ? _e : 'Empty or undefined')); console.log('Total items in filteredCampaigns:', filteredCampaigns === null || filteredCampaigns === void 0 ? void 0 : filteredCampaigns.length); const executionData = filteredCampaigns.map((item) => ({ json: item })); return executionData; } } console.log('--- Final Check Before Return (No Filtering Applied or No Items) ---'); console.log('Returning campaignItems (first item):', JSON.stringify((_f = campaignItems === null || campaignItems === void 0 ? void 0 : campaignItems[0]) !== null && _f !== void 0 ? _f : 'Empty or undefined')); console.log('Total items in campaignItems:', campaignItems === null || campaignItems === void 0 ? void 0 : campaignItems.length); const executionData = campaignItems.map((item) => ({ json: item })); return executionData; } function getValueByPath(obj, path) { const keys = path.split('.'); let current = obj; for (const key of keys) { if (current === null || typeof current !== 'object' || !Object.prototype.hasOwnProperty.call(current, key)) { return undefined; } current = current[key]; } return current; } function setValueByPath(obj, path, value) { const keys = path.split('.'); let current = obj; for (let i = 0; i < keys.length - 1; i++) { const key = keys[i]; if (current[key] === undefined || typeof current[key] !== 'object' || current[key] === null) { current[key] = {}; } current = current[key]; } const finalKey = keys[keys.length - 1]; current[finalKey] = value; } async function getCampaignCategories(i, baseUrl, headers, appId) { const params = { app_id: appId, ad_format: this.getNodeParameter('adFormat', i), category_id: this.getNodeParameter('categoryId', i, null), }; const response = await utils_1.makeApiRequest.call(this, 'get', `${baseUrl}/ads.campaigns.categories.get`, headers, params); if ((0, utils_1.isContinueOnFailError)(response)) { return { json: response }; } else { return { json: response }; } } async function getAdFormats(i, baseUrl, headers, appId) { this.logger.debug(`Getting ad formats with app_id: ${appId}`); const response = await utils_1.makeApiRequest.call(this, 'get', `${baseUrl}/ads.campaigns.formats.get`, headers, { app_id: appId }); if ((0, utils_1.isContinueOnFailError)(response)) { return [{ json: response }]; } let responseData; if (response && typeof response === 'object' && 'response' in response && response.response && typeof response.response === 'object') { if ('items' in response.response) { responseData = response.response.items; } else if ('formats' in response.response) { responseData = response.response.formats; } else { responseData = response.response; } } else { responseData = response; } return [{ json: responseData }]; } async function updatePlacementMultiplier(i, baseUrl, headers, appId) { const campaignId = this.getNodeParameter('campaignId', i); const multiplier = this.getNodeParameter('multiplier', i, 1); const placement = this.getNodeParameter('placement', i); if (!campaignId || campaignId.trim() === '') { throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Campaign ID parameter cannot be empty for Update Placement Multiplier.', { itemIndex: i }); } if (!placement || placement.trim() === '') { throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Placement ID parameter cannot be empty for Update Placement Multiplier.', { itemIndex: i }); } const formattedMultiplier = `x${multiplier}`; const params = { app_id: appId, campaign_id: campaignId.trim(), multiplier: formattedMultiplier, placement: placement.trim(), }; const endpoint = `${baseUrl}/ads.stats.campaign.placement.put`; const urlWithParams = `${endpoint}?app_id=${encodeURIComponent(params.app_id)}&campaign_id=${encodeURIComponent(params.campaign_id)}&multiplier=${encodeURIComponent(params.multiplier)}&placement=${encodeURIComponent(params.placement)}`; this.logger.debug(`Calling makeApiRequest (GET) for updatePlacementMultiplier with URL: ${urlWithParams}`); this.logger.debug(`Headers being sent: ${JSON.stringify(headers)}`); const response = await utils_1.makeApiRequest.call(this, 'get', urlWithParams, headers, undefined); let requestData; if (response && typeof response === 'object' && 'response' in response && response.response && typeof response.response === 'object' && 'request' in response.response) { requestData = response.response.request; } else if (response && typeof response === 'object' && 'request' in response) { requestData = response.request; } else { requestData = response; } return [{ json: requestData }]; } //# sourceMappingURL=campaigns.js.map