Mailchimp - Delete all products - e-commerce

I'm trying to clean up old products from a mailchimp database using API v3.0.
Mailchimp's E-commerce documentation explains how to delete a single product using:
DELETE /ecommerce/stores/{store_id}/products/{product_id}
Is there a way to delete all products at once? I cannot do it manually since I have thousands of records to remove.

I couldn't find a way to delete all products at once, so I wrote a NodeJS script to delete products in batches :
// delete-script.js
const request = require('request')
const headers = { 'Authorization': 'Basic XXX-usX' }
const productsUri = 'https://usX.api.mailchimp.com/3.0/ecommerce/stores/XX/products'
const erasePage = request.bind(this, {
uri: `${productsUri}?count=1000`,
method: "GET",
headers
}, (err, res, body) => {
const products = JSON.parse(body).products
const length = products.length
if (length === 0) return
let resolvedDeletions = 0
products.forEach(({ id }) => {
request({
uri: `${productsUri}/${id}`,
method: 'DELETE',
headers
}, err => {
if (err) return console.error(err)
console.log('deleted ', id)
if (++resolvedDeletions === length) erasePage()
})
})
})
erasePage()
Simply npm install request then execute script with node delete-script.js

Related

Struggling to correctly make use of returned values from functions that are being called Asynchronously by Axios

I have an Express server which serves as an API Request forwarding tool (i.e my client calls the express server, and the express server forwards that call to another API).
The way this server is supposed to work is that there is a single entry point which makes a request, and then based on the response makes further API requests and returns a result based on the combo of API request responses.
To be clearer, the main logic is as follows:
Single entry point, which makes an async axios call to get an ID value
Within this function, we call an async function, getPartnerDetails (passing that ID as the parameter)
getPartnerDetailscalls a 3rd async function, '''getRawJson''' which is supposed to return the final required result, passing it back to '''getPartnerDetails''' which then passes it to the main entry point.
Whats going wrong is that the results are being recieved but are not being pass back correctly. The console logs within the '''.then(()=>{})''' of my async functions are coming back as '''undefined'''.
Code below:
app.post('/checkuser', async (req, res, next) => {
const { man, bfn, bln, bsn, bc, bs, bz, bco } = req.body;
const bodyContent = {
man: man,
bfn: bfn,
bln: bln,
bsn: bsn,
bc: bc,
bs: bs,
bz: bz,
bco: bco,
profile: 'DEFAULT',
};
try {
await axios
.post('https://host.com/im/account/consumer', bodyContent, { headers })
.then((response) => {
const addressValidResult = response.data.score.etr.filter(
(result) => result.test === '19:2'
)[0];
// console.log(res.json(result.details));
const requestId = response.data.mtid;
const currentValidAddress = getPartnerDetails(requestId).then(
(result) => {
console.log('this is currentvalidaddress ' + result);
res.json({
validationMessage: addressValidResult,
currentValidAddress: result,
});
}
);
})
.catch((err) => next(err));
} catch {}
});
async function getPartnerDetails(appId) {
let config = {
headers: {
'Content-Type': 'application/json',
Authorization: 'Basic M2QzMsdfsslkfglkdjfglkdjflkgd',
},
params: {
partner: 19,
},
};
const res = await axios
.get(
`https://host.com/im/account/consumer/${appId}/partner/requests`,
config
)
.then((response) => {
const requestId = response.data.requests[0].request_id;
console.log('this is request id ' + JSON.stringify(requestId));
const raw = getRawJson(appId, requestId).then((result) => {
console.log('this is getRawJson result ' + JSON.stringify(result));
return JSON.stringify(result);
});
// https://host.com/im/account/consumer/:appId/partner/request/:requestId
})
.catch((err) => console.log('err2' + err));
}
async function getRawJson(appId, requestId) {
const res = await axios
.get(`host.com/im/account/consumer/${appId}/partner/request/${requestId}`, {
headers,
})
.then((response) => {
console.log('this is response ' + JSON.stringify(response.data));
return JSON.stringify(response.data);
})
.catch((err) => console.log('err1 ' + err));
}
It might have something to do with how I'm using async and await, I'm new to it so I'm hoping that I'll learn a thing or 2 more about it by solving this project.
I'm also aware that maybe I should split the entry point out into 3 different entry points, and have the client manage the chaining of the requests and responses instead.
Thanks!!
Probably an error due to incorrect async await usage.
Try to change your code like this:
app.post('/checkuser', async (req, res, next) => {
const { man, bfn, bln, bsn, bc, bs, bz, bco } = req.body;
const bodyContent = {
man: man,
bfn: bfn,
bln: bln,
bsn: bsn,
bc: bc,
bs: bs,
bz: bz,
bco: bco,
profile: 'DEFAULT',
};
try {
const { data } = await axios.post(
'https://host.com/im/account/consumer',
bodyContent,
{ headers }
);
const addressValidResult = data.score.etr.filter(
(result) => result.test === '19:2'
)[0];
const requestId = data.mtid;
const currentValidAddress = await getPartnerDetails(requestId);
console.log('this is currentvalidaddress ' + currentValidAddress);
res.json({
validationMessage: addressValidResult,
currentValidAddress: currentValidAddress,
});
} catch (err) {
next(err);
}
});
async function getPartnerDetails(appId) {
let config = {
headers: {
'Content-Type': 'application/json',
Authorization: 'Basic M2QzMsdfsslkfglkdjfglkdjflkgd',
},
params: {
partner: 19,
},
};
const { data } = await axios.get(
`https://host.com/im/account/consumer/${appId}/partner/requests`,
config
);
const requestId = data.requests[0].request_id;
console.log('this is request id ' + JSON.stringify(requestId));
return getRawJson(appId, requestId);
}
function getRawJson(appId, requestId) {
return axios
.get(`host.com/im/account/consumer/${appId}/partner/request/${requestId}`, {
headers,
})
}

How to fetch data from an API using express.js

API
(https://api.mosmarts.com/truck/v0/api.php)
The API is scripted in PHP and accepts GET & POST commands and in return it responds back with a JSON response data.
To retrieve data the API requires “functionality” and “action” among other params as show below.
Command for retrieving all truck
Command for retrieving all truck
Payloads
{
"functionality" : "get",
"action" : "get_all_truck"
}
Command to retrieving truck inspection details by id
Payloads
{
"functionality" : "get",
"action" : "get_inspection_history",
"truckId" : "1"
}
NB: you will get truckId from command "get_all_truck" above
What’s expected from you
As the software developer you are tasked to design and develop a web-based backend solution that will have:
Dashboard: -
• Retrieve and indicate total number of trucks
• Retrieve and indicate number of inspection repairs requested 2. List all Trucks: -
• Implement search option
Inspection List: -
• Implement filter by truck
i have some code using express.js bt i get is a 404 error, no data retrieved.
app.js
const apiCallFromRequest = require('./Request')
const apiCallFromNode = require('./NodeJsCall')
const http = require('http')
http.createServer((req, res) => {
if(req.url === "/request"){
apiCallFromRequest.callApi(function(response){
//console.log(JSON.stringify(response));
res.write(JSON.stringify(response));
res.end();
});
}
else if(req.url === "/node"){
apiCallFromNode.callApi(function(response){
res.write(response);
res.end();
});
}
// res.end();
}).listen(3000);
console.log("service running on 3000 port....");
NodeJsCall.js
const https = require('https');
_EXTERNAL_URL = 'https://api.mosmarts.com/truck/v0/api.php';
const callExternalApiUsingHttp = (callback) => {
https.get(_EXTERNAL_URL, (resp) => {
let data = '';
// A chunk of data has been recieved.
resp.on('data', (chunk) => {
data += chunk;
});
// The whole response has been received. Print out the result.
resp.on('end', () => {
return callback(data);
// console.log(JSON.stringify(data));
});
}).on("error", (err) => {
console.log("Error: " + err.message);
});
}
module.exports.callApi = callExternalApiUsingHttp;
Request.js
const request = require('request');
_EXTERNAL_URL = 'https://api.mosmarts.com/truck/v0/api.php';
const callExternalApiUsingRequest = (callback) => {
request(_EXTERNAL_URL, { json: true }, (err, res, body) => {
if (err) {
return callback(err);
}
return callback(body);
});
}
module.exports.callApi = callExternalApiUsingRequest;
Hey Gerald you can find a simple response for this kind of question on google.
if you are a real beginner I would propose you the Axios npm.
here is an example of a really simple GET request with axios.
axios.get('https://api.github.com/users/mapbox')
.then(response => {
console.log(response.data.created_at);
});

filter query param not working through axios get from my vue js application?

whenever a user types anything into the textfield, an axios get request to the url
http://sandbox4.wootz.io:8080/api/data/1/action/?filter={id}like'%TE%' is made and it is supposed to return back all the filtered results based on the search(what user has typed) as a response. But currently rather than returning the filtered results as a response it is giving out all results(non-filtered results).
NOTE: I have tested the above mentioned URL through postman by making a get request and it gave out the filtered results perfectly.Why is the same not happening through my application code?plz help
getAsyncDataAction: debounce(function(name) {
if (!name.length) {
this.dataAction = [];
return;
}
this.isFetching = true;
api
.getSearchData(this.sessionData.key,`/action/?filter={id}like'%${name}%'`)
.then(response => {
this.dataAction = [];
response.forEach(item => {
this.dataAction.push(item);
});
console.log('action results are'+JSON.stringify(this.dataAction)) //displays all the results(non-filtered)
})
.catch(error => {
this.dataAction = [];
throw error;
})
.finally(() => {
this.isFetching = false;
});
}, 500),
api.js
import axios from 'axios';
const props = {
base_url: '/api/store',
search_url: '/api/entity/search',
cors_url: 'http://localhost',
oper_url: '/api'
};
axios.defaults.headers.get['Access-Control-Allow-Origin'] = props.cors_url;
axios.defaults.headers.post['Access-Control-Allow-Origin'] = props.cors_url;
axios.defaults.headers.patch['Access-Control-Allow-Origin'] = props.cors_url;
async function getSearchData(key, path) {
try {
console.log('inside getSearchData path value is'+path)
console.log('inside getSearchData and url for axios get is '+props.base_url + '/data' + path)
let response = await axios({
method: 'get',
url: props.base_url + '/data' + path,
headers: {'session_id': key}
});
if (response.status == 200) {
console.log(response.status);
}
return response.data;
} catch (err) {
console.error(err);
}
}
The problem is that you're not encoding the query string correctly. In particular, your % signs need to become %25
To do this, I highly recommend using the params options in Axios.
For example
async function getSearchData(key, path, params) { // 👈 added "params"
// snip
let response = await axios({
method: 'get',
url: `${props.base_url}/data${path}`,
params, // 👈 use "params" here
headers: {'session_id': key}
});
and call your function with
const params = {}
// check for empty or blank "name"
if (name.trim().length > 0) {
params.filter = `{id}like'%${name}%'`
}
api
.getSearchData(this.sessionData.key, '/action/', params)
Alternatively, encode the query parameter manually
const filter = encodeURIComponent(`{id}like'%${name}%'`)
const path = `/action/?filter=${filter}`
Which should produce something like
/action/?filter=%7Bid%7Dlike'%25TE%25'

How to not insert two of the same values

I'm using an input to allow user's to select files from their computer and add it to a list. I'm doing this by using a promise to load the files and creating an array of promises and adding that to my state
React JS
this.state = {
files: [],
};
const readFile = (file) => {
const fileReader = new FileReader();
return new Promise((resolve, reject) => {
fileReader.onerror = (error) => {
reject({ error })
}
fileReader.onload = (e) => {
resolve({
name: file.name.replace( /_|\.mp3/gi, " "),
link: e.target.result,
id: id++,
})
}
fileReader.readAsDataURL(file);
})
}
const allReaders = Array.from(event.target.files).map(readFile)
Promise.all(allReaders)
.then(fileList => {
console.log(this.state.files)
this.setState({ files: fileList });
})
.catch(error => {
console.error(error)
});
}
I'm then mapping through my files array to add those files to a list of text inputs. They're also able to reorder the list as well as change the text for each list item.
After that they will be able to save the list information to a database using a button.
React JS
save(event) {
event.preventDefault();
let files = this.state.files;
let data = files.map(( { name } , index) => ({ name, index : index }));
let request = new Request('http://localhost:3000/songs', {
method: 'POST',
headers: new Headers({ 'Content-Type': 'application/json' }),
body: JSON.stringify(data)
});
fetch(request)
.then((response) =>
response.json())
.then((data) => {
})
.catch((error) => {
console.log(error)
})
}
Node JS
*queries.js*
const addSong = (request, response) => {
const id = parseInt(request.params.id)
const { name, link, index } = request.body;
for (var i = 0; i < request.body.length; i++) {
pool.query('INSERT INTO songs (name, link, index) VALUES ($1, $2, $3) RETURNING *', [request.body[i].name, request.body[i].link, request.body[i].index], (error, results) => {
if (error) {
throw error
console.log(error)
} else {
console.log("Rows " + JSON.stringify(results.rows));
}
});
}
}
*index.js*
const app = express();
const db = require('./queries');
app.post('/songs', db.addSong)
It works but if I click save twice it saves the same data to the database. I guess what I want to be able to do is not save the object if it contains the same index as another object.
If you want to prevent duplicates on column index (which, by the way, is not a well-chosen column name since it is a reserved workd in almost all RDBMS), you can simply add a unique constraint on that column:
ALTER TABLE songs ADD CONSTRAINT song_unique_index UNIQUE ("index");
If an attempt is made to create a duplicate, the database will raise an error. In Postgres, you can even manage that error in your query, using handy clause ON CONFLICT.
For example, you can simply ignore duplicate errors on this specific column like this:
INSERT INTO songs (name, link, index)
VALUES ($1, $2, $3)
ON CONFLICT (song_unique_index) DO NOTHING
RETURNING *
Duplicates will not be inserted, and no error will be raised.

Shopify get Customer Metafields

UPDATE: I have this Private API request to get a customer metafield data that sends a request to the shopify admin.
const {getAccessToken} = require('./auth')
const request = require('request')
const {shopFromPermanentDomain} = require('./helpers')
const getCustomerMetafields = ({accessToken, id, shop}) => new Promise((resolve, reject) => {
request({
url:`https://${shop}.myshopify.com/admin/customers/${id}/metafields.json',
headers: {
'X-Shopify-Access-Token': accessToken
}
}, (error, response, body) => {
const {errors} = JSON.parse(body)
if (response.statusCode === 200) {
const { metafields } = JSON.parse(body)
resolve(metafields)
}
reject({error: errors, status: 500})
})
})
const getCustomerMetafieldsResponse = (req, res) => {
const {id, permanentDomain} = req.body
if (id && permanentDomain) {
const shop = shopFromPermanentDomain(permanentDomain)
getAccessToken({shop})
.then(accessToken => getCustomerMetafields({accessToken, id, shop})
.then(meta => res.json({
meta,
status: 200
}))
)
.catch(({error, status}) => res.json({error, status}))
} else {
res.json({error: 'Missing params', status: 500})
}
}
module.exports = getCustomerMetafieldsResponse
I make this request from the front-end to my API with the following request.
const getCustomerMeta = ({
id,
permanentDomain
}) => new Promise((resolve, reject) => {
post({
params: { email, permanentDomain, task: 'get-customer-meta' },
then: ({ error, id, state, status }) => {
if (status === 200) {
resolve({ id, state })
}
reject(error)
},
url: '/apps/spoke'
})
})
getCustomerMeta({
id, // 98303739294 (Customer ID)
permanentDomain // "store.myshopify.com"
})
When making this request, I get the following request error:
500 (Internal Server Error)
VM706781:8 Uncaught SyntaxError: Unexpected token < in JSON at position 7
at JSON.parse (<anonymous>)
at XMLHttpRequest.l.onload
I then want to GET the customer metafields data so that I can populate the front-end with the data gathered.
Thanks!
You cannot call the back-end, ie) /admin, from the front-end, without using an App Proxy. On the front-end, the code you'd write would make a Proxy XHR call to your App, with the Customer ID. Using that ID, you'd then get the Metafields for the Customer resource, not the Shop as per your example. With the Metafields resource for the customer, you could then look for the ones that interest you, and draw them on the front-end.
Or just render the metafields for the logged in customer, using Liquid, as that is much simpler.
The api has probably changed drastically since you asked this question in 2018, but now you can get the metafields for the customer via the customers or metafields endpoints.
e.g.
/admin/api/{api-version-number}/customers/{shopify-customer-id}/metafields.json
directy to the metafields endpoint would be:
/admin/api/{api-version-number}/metafields.json?metafield[owner_id]={shopify-customer-id}&metafield[owner_resource]=customers