Skip to main content
Glama

Microservice Control Panel (MCP)

by battyht
oceanengine.service.js15 kB
const axios = require('axios'); const { getAccessToken, getDateString } = require('../utils/auth'); const logger = require('../utils/logger'); // 巨量引擎API基础URL const BASE_URL = 'https://ad.oceanengine.com/open_api'; /** * 获取广告账户信息 * @param {String} accountId - 广告账户ID * @param {String} accessToken - 访问令牌 * @returns {Promise<Object>} 账户信息 */ exports.getAccountInfo = async (accountId, accessToken) => { try { if (!accessToken) { throw new Error('缺少必要的访问令牌'); } const response = await axios({ method: 'GET', url: `${BASE_URL}/2/advertiser/info/`, params: { advertiser_ids: JSON.stringify([accountId]), fields: JSON.stringify(['id', 'name', 'status', 'balance', 'currency', 'role', 'address']) }, headers: { 'Access-Token': accessToken }, transformResponse: [ // 添加自定义转换响应函数,确保ID被作为字符串处理 (data) => { const parsedData = JSON.parse(data); // 如果有大整数ID,确保它们被作为字符串处理 if (parsedData.data && parsedData.data.list) { parsedData.data.list.forEach(item => { if (item.id) item.id = String(item.id); }); } return parsedData; } ] }); return response.data; } catch (error) { logger.error(`Error fetching account info: ${error.response?.data || error.message}`); throw new Error('获取账户信息失败: ' + (error.response?.data?.message || error.message)); } }; /** * 获取账户列表 * @param {Object} options - 查询选项 * @param {Number} options.page - 页码 * @param {Number} options.page_size - 每页数量 * @param {String} accessToken - 访问令牌 * @returns {Promise<Object>} 账户列表及分页信息 */ exports.getAccountList = async (options, accessToken) => { try { if (!accessToken) { throw new Error('缺少必要的访问令牌'); } const { page, page_size, ...filters } = options; const response = await axios({ method: 'GET', url: `${BASE_URL}/2/advertiser/select/`, params: { page, page_size, ...filters }, headers: { 'Access-Token': accessToken }, transformResponse: [ // 添加自定义转换响应函数,确保ID被作为字符串处理 (data) => { const parsedData = JSON.parse(data); // 转换账户ID为字符串 if (parsedData.data && parsedData.data.list) { parsedData.data.list.forEach(account => { if (account.advertiser_id) account.advertiser_id = String(account.advertiser_id); if (account.account_id) account.account_id = String(account.account_id); if (account.id) account.id = String(account.id); }); } return parsedData; } ] }); return response.data; } catch (error) { logger.error(`Error fetching account list: ${error.response?.data || error.message}`); throw new Error('获取账户列表失败: ' + (error.response?.data?.message || error.message)); } }; /** * 获取引流电商相关的广告数据 * @param {String} accountId - 广告账户ID * @param {Object} options - 查询选项 * @param {String} accessToken - 访问令牌 * @returns {Promise<Object>} 广告数据 */ exports.getAdPerformance = async (accountId, options = {}, accessToken) => { try { if (!accessToken) { throw new Error('缺少必要的访问令牌'); } const { start_date = getDateString(-7), end_date = getDateString(0), group_by = 'STAT_GROUP_BY_FIELD_STAT_TIME', // 默认按日期分组 ...filters } = options; // 电商引流相关的关键指标 const metrics = [ // 曝光和点击 'show', // 展示数 'click', // 点击数 'ctr', // 点击率 'cost', // 总消耗 'conversion', // 转化数 'conversion_rate', // 转化率 'conversion_cost', // 转化成本 // 电商相关 'total_play', // 播放数 'valid_play', // 有效播放数 'play_duration_3s', // 3秒播放数 'form_submit_count', // 表单提交数 'form_submit_cost', // 表单提交成本 'form_submit_rate', // 表单提交率 // 电商直接指标 'shopping_action', // 商品点击量 'shopping_action_cost', // 商品点击单价 'shopping_action_rate', // 商品点击率 'pay_count', // 支付订单数 'pay_amount', // 支付金额 'roi' // 投资回报率(ROI) ]; const response = await axios({ method: 'GET', url: `${BASE_URL}/2/report/ad/get/`, params: { advertiser_id: accountId, start_date, end_date, group_by, metrics: JSON.stringify(metrics), ...filters }, headers: { 'Access-Token': accessToken }, transformResponse: [ // 添加自定义转换响应函数,确保ID被作为字符串处理 (data) => { const parsedData = JSON.parse(data); // 转换报表数据中的ID为字符串 if (parsedData.data && parsedData.data.list) { parsedData.data.list.forEach(item => { if (item.ad_id) item.ad_id = String(item.ad_id); if (item.campaign_id) item.campaign_id = String(item.campaign_id); if (item.advertiser_id) item.advertiser_id = String(item.advertiser_id); }); } return parsedData; } ] }); return response.data; } catch (error) { logger.error(`Error fetching ad performance: ${error.response?.data || error.message}`); throw new Error('获取广告数据失败: ' + (error.response?.data?.message || error.message)); } }; /** * 获取小时级别的广告报表数据 * @param {String} accountId - 广告账户ID * @param {Object} options - 查询选项 * @param {String} accessToken - 访问令牌 * @returns {Promise<Object>} 小时报表数据 */ exports.getHourlyReport = async (accountId, options = {}, accessToken) => { try { if (!accessToken) { throw new Error('缺少必要的访问令牌'); } const params = { advertiser_id: accountId, start_date: options.start_date || getDateString(0), end_date: options.end_date || getDateString(0), group_by: ["STAT_GROUP_BY_FIELD_STAT_TIME", "STAT_GROUP_BY_FIELD_HOUR"], time_granularity: "STAT_TIME_GRANULARITY_HOURLY" }; // 可选的过滤条件 if (options.filtering) { params.filtering = options.filtering; } logger.info(`Hourly report request params: ${JSON.stringify(params)}`); const response = await axios({ method: 'GET', url: `${BASE_URL}/2/report/advertiser/get/`, params, headers: { 'Access-Token': accessToken }, transformResponse: [ // 添加自定义转换响应函数,确保ID被作为字符串处理 (data) => { const parsedData = JSON.parse(data); // 转换报表数据中的ID为字符串 if (parsedData.data && parsedData.data.list) { parsedData.data.list.forEach(item => { if (item.advertiser_id) item.advertiser_id = String(item.advertiser_id); if (item.campaign_id) item.campaign_id = String(item.campaign_id); if (item.ad_id) item.ad_id = String(item.ad_id); // 处理其他可能的ID字段 Object.keys(item).forEach(key => { if (key.includes('_id') && typeof item[key] === 'number' && String(item[key]).length > 15) { item[key] = String(item[key]); } }); }); } return parsedData; } ] }); return response.data; } catch (error) { logger.error(`Error fetching hourly report: ${error.response?.data || error.message}`); throw new Error('获取小时报表失败: ' + (error.response?.data?.message || error.message)); } }; /** * 获取自定义报表数据 * @param {Object} reportData - 报表请求数据 * @param {String} accessToken - 访问令牌 * @returns {Promise<Object>} 报表数据 */ exports.getCustomReport = async (reportData, accessToken) => { try { if (!accessToken) { throw new Error('缺少必要的访问令牌'); } // 处理请求数据 const requestData = { ...reportData }; // 确保有时间范围 if (!requestData.start_date) { requestData.start_date = getDateString(0); } if (!requestData.end_date) { requestData.end_date = getDateString(0); } // 确保有必要的字段 if (!requestData.advertiser_id) { throw new Error('缺少必要的advertiser_id字段'); } if (!requestData.metrics) { throw new Error('缺少必要的metrics字段'); } // 设置默认值 if (!requestData.time_granularity) { requestData.time_granularity = 'STAT_TIME_GRANULARITY_DAILY'; } if (!requestData.group_by) { requestData.group_by = ['STAT_GROUP_BY_FIELD_STAT_TIME']; } logger.info(`Custom report request params: ${JSON.stringify(requestData)}`); const response = await axios({ method: 'GET', url: 'https://api.oceanengine.com/open_api/v3.0/report/custom/get/', params: requestData, headers: { 'Access-Token': accessToken }, transformResponse: [ // 添加自定义转换响应函数,确保ID被作为字符串处理 (data) => { const parsedData = JSON.parse(data); // 转换自定义报表中的ID为字符串 if (parsedData.data && parsedData.data.list) { parsedData.data.list.forEach(item => { // 处理常见的ID字段 if (item.cdp_promotion_id) item.cdp_promotion_id = String(item.cdp_promotion_id); if (item.promotion_id) item.promotion_id = String(item.promotion_id); if (item.project_id) item.project_id = String(item.project_id); if (item.advertiser_id) item.advertiser_id = String(item.advertiser_id); // 遍历所有字段,将可能的ID字段都转为字符串 Object.keys(item).forEach(key => { if (key.includes('_id') && typeof item[key] === 'number' && String(item[key]).length > 15) { item[key] = String(item[key]); } }); }); } return parsedData; } ] }); return response.data; } catch (error) { logger.error(`Error fetching custom report: ${error.response?.data || error.message}`); throw new Error('获取自定义报表失败: ' + (error.response?.data?.message || error.message)); } }; /** * 获取项目列表 * @param {String} accountId - 广告账户ID * @param {Object} options - 查询选项 * @param {String} accessToken - 访问令牌 * @returns {Promise<Object>} 项目列表数据 */ exports.getProjectList = async (accountId, options = {}, accessToken) => { try { if (!accessToken) { throw new Error('缺少必要的访问令牌'); } // 构建请求参数 const params = { advertiser_id: accountId, ...options }; logger.info(`Project list request params: ${JSON.stringify(params)}`); const response = await axios({ method: 'GET', url: 'https://api.oceanengine.com/open_api/v3.0/project/list/', params, headers: { 'Access-Token': accessToken }, transformResponse: [ // 添加自定义转换响应函数,确保ID被作为字符串处理 (data) => { const parsedData = JSON.parse(data); // 如果有项目数据,转换项目ID为字符串 if (parsedData.data && parsedData.data.list) { parsedData.data.list.forEach(project => { if (project.project_id) project.project_id = String(project.project_id); // 其他可能的大整数ID if (project.advertiser_id) project.advertiser_id = String(project.advertiser_id); }); } return parsedData; } ] }); return response.data; } catch (error) { logger.error(`Error fetching project list: ${error.response?.data || error.message}`); throw new Error('获取项目列表失败: ' + (error.response?.data?.message || error.message)); } }; /** * 获取广告列表 * @param {String} accountId - 广告账户ID * @param {Object} options - 查询选项 * @param {String} accessToken - 访问令牌 * @returns {Promise<Object>} 广告列表数据 */ exports.getAdList = async (accountId, options = {}, accessToken) => { try { if (!accessToken) { throw new Error('缺少必要的访问令牌'); } // 构建请求参数 const params = { advertiser_id: accountId, ...options }; logger.info(`Ad list request params: ${JSON.stringify(params)}`); const response = await axios({ method: 'GET', url: 'https://api.oceanengine.com/open_api/v1.0/qianchuan/promotion/get/', params, headers: { 'Access-Token': accessToken }, transformResponse: [ // 添加自定义转换响应函数,确保ID被作为字符串处理 (data) => { const parsedData = JSON.parse(data); // 如果有广告数据,转换广告ID为字符串 if (parsedData.data && parsedData.data.list) { parsedData.data.list.forEach(ad => { // 转换所有可能的ID字段为字符串 if (ad.promotion_id) ad.promotion_id = String(ad.promotion_id); if (ad.project_id) ad.project_id = String(ad.project_id); if (ad.advertiser_id) ad.advertiser_id = String(ad.advertiser_id); // 其他可能的大整数ID }); } return parsedData; } ] }); return response.data; } catch (error) { logger.error(`Error fetching ad list: ${error.response?.data || error.message}`); throw new Error('获取广告列表失败: ' + (error.response?.data?.message || error.message)); } };

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/battyht/AD_MCP'

If you have feedback or need assistance with the MCP directory API, please join our Discord server