May 23, 2022 07:51 AM
Hello, i have a script in a button where if i click the button, airtable generates an image.
How can i somehow automate this using http request (Pabbly connect) so that i dont click it one by one?
May 23, 2022 05:45 PM
What kind of script does your button currently trigger? You didn’t provide many details about your setup, so I’m not sure if the current script already makes an HTTP request or if it’s using some other method.
I’ve not heard of Pabbly Connect before, but it looks like another automation service like Zapier or Integromat, designed to connect various online services together. Again there’s a lot of detail missing from your post, so I’m guessing that you’re using Pabbly Connect to call some other service to create and add the image to Airtable, but I don’t know where the HTTP request would fit into this setup.
If you could please provide a lot more detail about your current setup and what you’re hoping to achieve, we can guide you more effectively towards a solution.
May 23, 2022 06:57 PM
Sorry for the missing information.
Here is my table setup:
product:url is an airtable image url which is needed for the script;
template and size are the other parameters needed for the script,
image is the generated image when i click the Create button
Here is the scripting detail
let table = base.getTable(cursor.activeTableId)
let record = await input.recordAsync('Pick a record', table)
const { fields } = table;
const sizes = record?.getCellValueAsString("size");
const template = record?.getCellValueAsString("template");
const API_KEY = record?.getCellValueAsString("API Key");
var request = {
template,
"sizes": [],
"elements": {
}
};
if (sizes) {
const sizesParts = sizes.split(",").map((part) => part.trim());
sizesParts.forEach((size) => {
const sizeParts = size.split("x").map((part) => part.trim());
request.sizes.push({
"width": parseInt(sizeParts[0]),
"height": parseInt(sizeParts[1])
});
});
}
fields.forEach((field) => {
if (field.name.includes(":")) {
// split and add to the elements object
const parts = field.name.split(":");
const name = parts[0];
const property = parts[1];
if (!request.elements[name]) {
request.elements[name] = {};
}
request.elements[name][property] = record?.getCellValueAsString(field.name)
}
})
let response = await fetch('https://api.canvas.switchboard.ai', {
method: 'POST',
body: JSON.stringify(request),
headers: {
'Content-Type': 'application/json',
'X-API-Key': API_KEY
}
})
try {
let asJson = await response.json()
if (record && asJson?.success) {
await table.updateRecordAsync(record.id, {
image: asJson.sizes.map((result) => {
return { url: result.url };
})
});
} else {
console.log(asJson);
}
} catch(err) {
console.warn("Something went wrong");
console.error(err);
}
The problem here is that i have to click the Create button one by one and i have 5000 records. Is there any automation work around?
Thanks
May 25, 2022 08:22 PM
Instead of using input.recordAsync()
to get a single record, you can get all records in the table via a query and loop through them all by running the script once. Here’s a modified version of your script that does this, along with an optimization to add the images in batches after retrieving them all, rather than adding them one record at a time.
With 5000 records, it’s going to take some time to run the script, so I added a counter so that you can keep track of the progress. The downside is that any errors encountered will be erased as the counter progresses, but once the script is finished it will be obvious which records don’t have images added, so you’ll have that as an indicator of something likely amiss with the source data.
let table = base.getTable(cursor.activeTableId)
const { fields } = table;
const query = await table.selectRecordsAsync({fields})
const updates = []
for (let record of query.records) {
output.clear()
output.markdown("# Processing")
output.text(`Retrieving image ${query.records.indexOf(record) + 1} of ${query.records.length}`)
const sizes = record.getCellValueAsString("size");
const template = record.getCellValueAsString("template");
const API_KEY = record.getCellValueAsString("API Key");
var request = {
template,
"sizes": [],
"elements": {}
};
if (sizes) {
const sizesParts = sizes.split(",").map((part) => part.trim());
sizesParts.forEach((size) => {
const sizeParts = size.split("x").map((part) => part.trim());
request.sizes.push({
"width": parseInt(sizeParts[0]),
"height": parseInt(sizeParts[1])
});
});
}
fields.forEach((field) => {
if (field.name.includes(":")) {
// split and add to the elements object
const parts = field.name.split(":");
const name = parts[0];
const property = parts[1];
if (!request.elements[name]) {
request.elements[name] = {};
}
request.elements[name][property] = record.getCellValueAsString(field.name)
}
})
let response = await fetch('https://api.canvas.switchboard.ai', {
method: 'POST',
body: JSON.stringify(request),
headers: {
'Content-Type': 'application/json',
'X-API-Key': API_KEY
}
})
try {
let asJson = await response.json()
if (asJson?.success) {
updates.push({
id: record.id,
fields: {
image: asJson.sizes.map((result) => {
return { url: result.url };
})
}
})
} else {
console.log(asJson);
}
} catch(err) {
console.warn("Something went wrong");
console.error(err);
}
}
while (updates.length) {
await table.updateRecordsAsync(updates.splice(0, 50))
}
May 25, 2022 10:43 PM
@Justin_Barrett Thank you for your help. I have talked to the founder of Switchboard and we decided to use simpler approach which is generating images based on other images in an attachment field.
In my case, i have FOTO field which contains all raw images. I also have a field named “IMAGE” where it is an attachment type field.
I have a button script (“Create” Button in Options Field) where when i click it, Swithboard will generate watermarked images in “IMAGE” field. Both screenshot and script are as follows:
let table = base.getTable(cursor.activeTableId)
let record = await input.recordAsync('Pick a record', table)
const { fields } = table;
const sizes = record?.getCellValueAsString("size");
const template = record?.getCellValueAsString("template");
const API_KEY = record?.getCellValueAsString("API Key");
// make sure there's a record
if (record) {
const urls = record.getCellValue("Foto").map((row) => row.url);
const promises = urls.map((url) => {
return new Promise(async (res, rej) => {
// build an empty request
var request = {
template,
"sizes": [],
"elements": {
"product": {
url
}
}
};
if (sizes) {
const sizesParts = sizes.split(",").map((part) => part.trim());
sizesParts.forEach((size) => {
const sizeParts = size.split("x").map((part) => part.trim());
request.sizes.push({
"width": parseInt(sizeParts[0]),
"height": parseInt(sizeParts[1])
});
});
}
fields.forEach((field) => {
if (field.name.includes(":")) {
// split and add to the elements object
const parts = field.name.split(":");
const name = parts[0];
const property = parts[1];
if (!request.elements[name]) {
request.elements[name] = {};
}
request.elements[name][property] = record?.getCellValueAsString(field.name)
}
})
let response = await fetch('https://api.canvas.switchboard.ai', {
method: 'POST',
body: JSON.stringify(request),
headers: {
'Content-Type': 'application/json',
'X-API-Key': API_KEY
}
})
try {
let asJson = await response.json()
if (record && asJson?.success) {
const newResults = asJson.sizes.map((result) => {
return { url: result.url };
});
res(newResults);
} else {
console.log(asJson);
}
} catch (err) {
console.warn("Something went wrong");
console.error(err);
}
});
});
// run all the requests
const result = await Promise.all(promises);
const updateData = result.flatMap((r) => r);
await table.updateRecordAsync(record.id, {
image: updateData
});
console.log("Done.");
}
Can you help me tweak this code a little bit so that i can click RUN script in dashboard instead of clicking the button one by one for each record?
Your help is appreciated. Thank you so much!
May 26, 2022 06:52 PM
The basic change to make here is the same as in the modified script I included above. Notice how I wrapped the core of the code in a for...of
loop. You can apply that same technique here and run the resulting script once to process all records.