fix: correct remaining 5 API issues from codex review

- meta-ads: use empty array for special_ad_categories (not ['NONE'])
- ahrefs: add --target validation to all 5 site-explorer commands
- wistia: read SRT file contents from disk for captions create
- tiktok-ads: use URLSearchParams for cleaner URL construction
- mixpanel: require --from-date/--to-date for retention, add --event filter for export

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Corey Haines 2026-02-17 14:38:36 -08:00
parent ebdf1dd2f1
commit 2349865acb
5 changed files with 23 additions and 10 deletions

View file

@ -58,6 +58,7 @@ async function main() {
case 'domain-rating': case 'domain-rating':
switch (sub) { switch (sub) {
case 'get': { case 'get': {
if (!args.target) { result = { error: '--target required (domain)' }; break }
const params = new URLSearchParams({ target: args.target }) const params = new URLSearchParams({ target: args.target })
result = await api('GET', `/site-explorer/domain-rating?${params}`) result = await api('GET', `/site-explorer/domain-rating?${params}`)
break break
@ -70,6 +71,7 @@ async function main() {
case 'backlinks': case 'backlinks':
switch (sub) { switch (sub) {
case 'list': { case 'list': {
if (!args.target) { result = { error: '--target required (domain or URL)' }; break }
const params = new URLSearchParams({ target: args.target, mode }) const params = new URLSearchParams({ target: args.target, mode })
if (args.limit) params.set('limit', args.limit) if (args.limit) params.set('limit', args.limit)
result = await api('GET', `/site-explorer/backlinks?${params}`) result = await api('GET', `/site-explorer/backlinks?${params}`)
@ -83,6 +85,7 @@ async function main() {
case 'refdomains': case 'refdomains':
switch (sub) { switch (sub) {
case 'list': { case 'list': {
if (!args.target) { result = { error: '--target required (domain or URL)' }; break }
const params = new URLSearchParams({ target: args.target, mode }) const params = new URLSearchParams({ target: args.target, mode })
if (args.limit) params.set('limit', args.limit) if (args.limit) params.set('limit', args.limit)
result = await api('GET', `/site-explorer/refdomains?${params}`) result = await api('GET', `/site-explorer/refdomains?${params}`)
@ -96,6 +99,7 @@ async function main() {
case 'keywords': case 'keywords':
switch (sub) { switch (sub) {
case 'organic': { case 'organic': {
if (!args.target) { result = { error: '--target required (domain or URL)' }; break }
const params = new URLSearchParams({ target: args.target, mode }) const params = new URLSearchParams({ target: args.target, mode })
if (args.country) params.set('country', args.country) if (args.country) params.set('country', args.country)
if (args.limit) params.set('limit', args.limit) if (args.limit) params.set('limit', args.limit)
@ -110,6 +114,7 @@ async function main() {
case 'top-pages': case 'top-pages':
switch (sub) { switch (sub) {
case 'list': { case 'list': {
if (!args.target) { result = { error: '--target required (domain or URL)' }; break }
const params = new URLSearchParams({ target: args.target, mode }) const params = new URLSearchParams({ target: args.target, mode })
if (args.country) params.set('country', args.country) if (args.country) params.set('country', args.country)
if (args.limit) params.set('limit', args.limit) if (args.limit) params.set('limit', args.limit)

View file

@ -93,7 +93,7 @@ async function main() {
name: args.name, name: args.name,
objective: args.objective, objective: args.objective,
status: args.status || 'PAUSED', status: args.status || 'PAUSED',
special_ad_categories: ['NONE'], special_ad_categories: [],
} }
result = await api('POST', `/act_${accountId}/campaigns`, body) result = await api('POST', `/act_${accountId}/campaigns`, body)
break break

View file

@ -187,9 +187,10 @@ async function main() {
case 'retention': case 'retention':
switch (sub) { switch (sub) {
case 'get': { case 'get': {
if (!args['from-date'] || !args['to-date']) { result = { error: '--from-date and --to-date required (YYYY-MM-DD)' }; break }
const params = new URLSearchParams() const params = new URLSearchParams()
if (args['from-date']) params.set('from_date', args['from-date']) params.set('from_date', args['from-date'])
if (args['to-date']) params.set('to_date', args['to-date']) params.set('to_date', args['to-date'])
params.set('retention_type', 'birth') params.set('retention_type', 'birth')
if (args['born-event']) params.set('born_event', args['born-event']) if (args['born-event']) params.set('born_event', args['born-event'])
result = await queryApi('GET', QUERY_URL, '/retention', params) result = await queryApi('GET', QUERY_URL, '/retention', params)
@ -208,6 +209,7 @@ async function main() {
const params = new URLSearchParams() const params = new URLSearchParams()
params.set('from_date', args['from-date']) params.set('from_date', args['from-date'])
params.set('to_date', args['to-date']) params.set('to_date', args['to-date'])
if (args.event) params.set('event', JSON.stringify([args.event]))
result = await queryApi('GET', EXPORT_URL, '/export', params) result = await queryApi('GET', EXPORT_URL, '/export', params)
break break
} }

View file

@ -68,7 +68,8 @@ async function main() {
case 'info': { case 'info': {
const advId = getAdvertiserId() const advId = getAdvertiserId()
if (!advId) { result = { error: 'TIKTOK_ADVERTISER_ID env or --advertiser-id required' }; break } if (!advId) { result = { error: 'TIKTOK_ADVERTISER_ID env or --advertiser-id required' }; break }
result = await api('GET', `/advertiser/info/?advertiser_ids=["${advId}"]`) const advParams = new URLSearchParams({ advertiser_ids: JSON.stringify([advId]) })
result = await api('GET', `/advertiser/info/?${advParams}`)
break break
} }
default: default:
@ -81,7 +82,8 @@ async function main() {
case 'list': { case 'list': {
const advId = getAdvertiserId() const advId = getAdvertiserId()
if (!advId) { result = { error: 'TIKTOK_ADVERTISER_ID env or --advertiser-id required' }; break } if (!advId) { result = { error: 'TIKTOK_ADVERTISER_ID env or --advertiser-id required' }; break }
result = await api('GET', `/campaign/get/?advertiser_id=${advId}&page=1&page_size=20`) const campParams = new URLSearchParams({ advertiser_id: advId, page: '1', page_size: '20' })
result = await api('GET', `/campaign/get/?${campParams}`)
break break
} }
case 'create': { case 'create': {
@ -119,9 +121,9 @@ async function main() {
case 'list': { case 'list': {
const advId = getAdvertiserId() const advId = getAdvertiserId()
if (!advId) { result = { error: 'TIKTOK_ADVERTISER_ID env or --advertiser-id required' }; break } if (!advId) { result = { error: 'TIKTOK_ADVERTISER_ID env or --advertiser-id required' }; break }
let path = `/adgroup/get/?advertiser_id=${advId}` const agParams = new URLSearchParams({ advertiser_id: advId })
if (args['campaign-id']) path += `&campaign_ids=["${args['campaign-id']}"]` if (args['campaign-id']) agParams.set('campaign_ids', JSON.stringify([args['campaign-id']]))
result = await api('GET', path) result = await api('GET', `/adgroup/get/?${agParams}`)
break break
} }
default: default:
@ -157,7 +159,8 @@ async function main() {
case 'list': { case 'list': {
const advId = getAdvertiserId() const advId = getAdvertiserId()
if (!advId) { result = { error: 'TIKTOK_ADVERTISER_ID env or --advertiser-id required' }; break } if (!advId) { result = { error: 'TIKTOK_ADVERTISER_ID env or --advertiser-id required' }; break }
result = await api('GET', `/dmp/custom_audience/list/?advertiser_id=${advId}`) const audParams = new URLSearchParams({ advertiser_id: advId })
result = await api('GET', `/dmp/custom_audience/list/?${audParams}`)
break break
} }
default: default:

View file

@ -221,7 +221,10 @@ async function main() {
if (!id) { result = { error: '--id required (media hashed ID)' }; break } if (!id) { result = { error: '--id required (media hashed ID)' }; break }
if (!language) { result = { error: '--language required (e.g. eng)' }; break } if (!language) { result = { error: '--language required (e.g. eng)' }; break }
const body = { language } const body = { language }
if (args['srt-file']) body.caption_file = args['srt-file'] if (args['srt-file']) {
const fs = require('fs')
body.caption_file = fs.readFileSync(args['srt-file'], 'utf8')
}
result = await api('POST', `/medias/${id}/captions.json`, body) result = await api('POST', `/medias/${id}/captions.json`, body)
break break
} }