← Back
β˜†
import 'dotenv/config';

const API_KEY = process.env.POPADS_API_KEY;
const BASE_V1 = 'https://www.popads.net/api';
const BASE_V2 = 'https://www.popads.net/apiv2';

if (!API_KEY) {
  console.error('❌ POPADS_API_KEY not set in .env');
  process.exit(1);
}

// ─── API v1 ────────────────────────────────────────────

const v1 = async (action, params = {}, method = 'GET') => {
  const url = new URL(`${BASE_V1}/${action}`);
  url.searchParams.set('key', API_KEY);

  const opts = { method, headers: { Accept: 'application/json' } };

  if (method === 'POST') {
    Object.entries(params).forEach(([k, v]) => url.searchParams.set(k, v));
  } else {
    Object.entries(params).forEach(([k, v]) => url.searchParams.set(k, v));
  }

  const res = await fetch(url, opts);
  if (!res.ok && res.status !== 406) {
    const text = await res.text();
    throw new Error(`PopAds v1 ${res.status}: ${text}`);
  }
  return res.json();
};

// ─── API v2 ────────────────────────────────────────────

const v2 = async (method, path, body = null) => {
  const url = `${BASE_V2}${path}?key=${API_KEY}`;
  const opts = {
    method,
    headers: { Accept: 'application/json', 'Content-Type': 'application/json' },
  };
  if (body) opts.body = JSON.stringify(body);

  const res = await fetch(url, opts);
  const data = await res.json();
  return data;
};

// ─── v1 Commands ───────────────────────────────────────

const userStatus = () => v1('user_status');
const campaignList = () => v1('campaign_list');
const campaignStart = (id) => v1('campaign_start', { campaign_id: id }, 'POST');
const campaignPause = (id) => v1('campaign_pause', { campaign_id: id }, 'POST');
const campaignTopUp = (id, amount) => v1('campaign_top_up', { campaign_id: id, amount }, 'POST');
const campaignEmptyBudget = (id, amount) => v1('campaign_empty_budget', { campaign_id: id, amount }, 'POST');
const campaignRunout = () => v1('campaign_runout');
const websiteDetails = (id) => v1(`website_details/${id}`);

const reportAdvertiser = (params = {}) => {
  const defaults = {
    zone: 'America/Vancouver',
    quick: 'today',
    groups: 'campaigns',
  };
  return v1('report_advertiser', { ...defaults, ...params }, 'POST');
};

// ─── v2 Commands ───────────────────────────────────────

const getCampaignDetails = (id) => v2('GET', `/campaign/details/${id}`);

const createCampaign = (config) => v2('POST', '/campaign/add', config);

const updateCampaign = (id, config) => v2('PUT', `/campaign/update/${id}`, config);

const patchCampaign = (id, config) => v2('PATCH', `/campaign/update/${id}`, config);

const getOptions = (name, country = null) => {
  const path = country ? `/options/${name}/${country}` : `/options/${name}`;
  return v2('GET', path);
};

// ─── CLI ───────────────────────────────────────────────

const [cmd, ...args] = process.argv.slice(2);

const commands = {
  async status() {
    console.log('\nπŸ‘€ PopAds Account\n');
    const data = await userStatus();
    console.log(JSON.stringify(data, null, 2));
  },

  async campaigns() {
    console.log('\nπŸ“’ Campaigns\n');
    const data = await campaignList();
    if (Array.isArray(data)) {
      data.forEach((c) => {
        console.log(`  β€’ [${c.id}] ${c.name} β€” ${c.status} | budget: $${c.budget || '?'} | bid: $${c.max_bid || '?'}`);
      });
    } else {
      console.log(JSON.stringify(data, null, 2));
    }
  },

  async start() {
    const [id] = args;
    if (!id) { console.log('Usage: node popads.js start <campaign_id>'); return; }
    const r = await campaignStart(id);
    console.log('βœ… Started:', JSON.stringify(r));
  },

  async pause() {
    const [id] = args;
    if (!id) { console.log('Usage: node popads.js pause <campaign_id>'); return; }
    const r = await campaignPause(id);
    console.log('⏸️ Paused:', JSON.stringify(r));
  },

  async topup() {
    const [id, amount] = args;
    if (!id || !amount) { console.log('Usage: node popads.js topup <campaign_id> <amount>'); return; }
    const r = await campaignTopUp(id, amount);
    console.log('πŸ’° Topped up:', JSON.stringify(r));
  },

  async report() {
    const [quick, group] = args;
    console.log(`\nπŸ“Š Report (${quick || 'today'}, group: ${group || 'campaigns'})\n`);
    const data = await reportAdvertiser({
      quick: quick || 'today',
      groups: group || 'campaigns',
    });
    console.log(JSON.stringify(data, null, 2));
  },

  async details() {
    const [id] = args;
    if (!id) { console.log('Usage: node popads.js details <campaign_id>'); return; }
    const data = await getCampaignDetails(id);
    console.log(JSON.stringify(data, null, 2));
  },

  async options() {
    const [name, country] = args;
    if (!name) {
      console.log(`
Options: ad-block-values, advertise-type, browsers, categories,
  connection-speeds, connection-types, countries, devices,
  form-factors, frequency-cap-days, languages, operating-systems,
  quality, resolutions, timezones, regions/{country}`);
      return;
    }
    const data = await getOptions(name, country);
    console.log(JSON.stringify(data, null, 2));
  },

  async create() {
    console.log('⚠️ Use node popads.js create-cpi or create-mainstream');
  },

  // Quick campaign creator β€” CPI SmartLink via BeMob
  async 'create-cpi'() {
    const [geo, budget, bid] = args;
    if (!geo) { console.log('Usage: node popads.js create-cpi <GEO> [budget] [bid]'); return; }

    const BEMOB_CPI_URL = 'https://27zff.bemobtrcks.com/go/06b83d41-b52e-443d-a1a3-c52adf4bb40c';
    console.log(`Creating CPI campaign for ${geo.toUpperCase()}...`);
    const r = await createCampaign(buildCampaignConfig(
      `CPI Direct - ${geo.toUpperCase()}`, BEMOB_CPI_URL, geo, budget, bid
    ));
    console.log(JSON.stringify(r, null, 2));
  },

  // Quick campaign creator β€” Mainstream SmartLink via BeMob
  async 'create-mainstream'() {
    const [geo, budget, bid] = args;
    if (!geo) { console.log('Usage: node popads.js create-mainstream <GEO> [budget] [bid]'); return; }

    const BEMOB_MS_URL = 'https://27zff.bemobtrcks.com/go/8fb53f2a-e310-4aa3-b573-9ba53a7664a8';
    console.log(`Creating Mainstream campaign for ${geo.toUpperCase()}...`);
    const r = await createCampaign(buildCampaignConfig(
      `Mainstream Direct - ${geo.toUpperCase()}`, BEMOB_MS_URL, geo, budget, bid
    ));
    console.log(JSON.stringify(r, null, 2));
  },

  async help() {
    console.log(`
πŸ”§ PopAds CLI

Аккаунт:
  node popads.js status               β€” Баланс, ΠΈΠ½Ρ„ΠΎ
  node popads.js campaigns            β€” Бписок ΠΊΠ°ΠΌΠΏΠ°Π½ΠΈΠΉ

Π£ΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅:
  node popads.js start <id>           β€” Π—Π°ΠΏΡƒΡΡ‚ΠΈΡ‚ΡŒ кампанию
  node popads.js pause <id>           β€” ΠŸΠΎΡΡ‚Π°Π²ΠΈΡ‚ΡŒ Π½Π° ΠΏΠ°ΡƒΠ·Ρƒ
  node popads.js topup <id> <amount>  β€” ΠŸΠΎΠΏΠΎΠ»Π½ΠΈΡ‚ΡŒ кампанию
  node popads.js details <id>         β€” Π”Π΅Ρ‚Π°Π»ΠΈ ΠΊΠ°ΠΌΠΏΠ°Π½ΠΈΠΈ (v2)

Π‘ΠΎΠ·Π΄Π°Π½ΠΈΠ΅:
  node popads.js create-cpi <GEO> [budget] [bid]
  node popads.js create-mainstream <GEO> [budget] [bid]

  ΠŸΡ€ΠΈΠΌΠ΅Ρ€: node popads.js create-cpi PH 10 0.001

ΠžΡ‚Ρ‡Ρ‘Ρ‚Ρ‹:
  node popads.js report [quick] [group]
    quick: today, yesterday, last7days, last30days, thismonth
    group: campaigns, websites, countries, hours

Π‘ΠΏΡ€Π°Π²ΠΎΡ‡Π½ΠΈΠΊΠΈ:
  node popads.js options                    β€” Бписок справочников
  node popads.js options countries          β€” Π‘Ρ‚Ρ€Π°Π½Ρ‹
  node popads.js options operating-systems  β€” ОБ
`);
  },
};

const run = commands[cmd] || commands.help;
run().catch((err) => {
  console.error(`❌ ${err.message}`);
  process.exit(1);
});

export {
  userStatus, campaignList, campaignStart, campaignPause, campaignTopUp,
  reportAdvertiser, getCampaignDetails, createCampaign, updateCampaign,
  patchCampaign, getOptions,
};

πŸ“œ Git History

71dd65fchore: initial commit β€” version control setup5 weeks ago
Show last diff
Loading...