// Modify these to your own values.
let tinyPngApiKey = 'TINYPNG API KEY';
let airtableAttachmentSource = 'image';
let airtableAttachmentDestination = 'image';
let airtableColumnToLog = 'name';
// Don't change these unless you know what you're doing.
let table = base.getTable(cursor.activeTableId);
let view = table.getView(cursor.activeViewId);
let queryResult = await view.selectRecordsAsync();
for (let record of queryResult.records) {
let attachments = record.getCellValue(airtableAttachmentSource);
let compressedImageUrls = [];
if (attachments && attachments.length > 0) {
// Iterate through each attachment in the field.
for (let [i, attachment] of attachments.entries()) {
let recordAttachmentUrl = attachment['url'];
console.log(`Compressing ${record.getCellValue(airtableColumnToLog)} (Image ${i + 1})`);
let request = await remoteFetchAsync('https://api.tinify.com/shrink', {
body: JSON.stringify({'source': {'url': recordAttachmentUrl}}),
headers: {
Authorization: 'Basic ' + btoa('api:' + tinyPngApiKey),
'Content-Type': 'application/json'
},
method: 'POST'
})
const json = await request.json();
// Checks that the API didn't fail.
if (request.status == 201) {
let percentReduced = Math.round((1 - json.output.ratio) * 100);
let kbReduced = (json.input.size - json.output.size) / 1024;
console.log('Panda just saved you ' + percentReduced + '% (' + Math.round(kbReduced) + 'KB).');
// Add the compressed image URL to the array.
compressedImageUrls.push({ url: json['output']['url'] });
}
}
// Update the record with all the compressed image URLs.
await table.updateRecordAsync(record.id, {
[airtableAttachmentDestination]: compressedImageUrls,
});
}
}
I also modified this script to work in an Airtable automation for one single record only.
You need to make sure though that the automation doesn’t loop itself. I did it with two automations that update a helper field after to stop the loop.
// Modify these to your own values.
let tinyPngApiKey = '6dr6PF1tvsvJ6RP9q4Zbt55NK1RF9cNK';
//Table settings:
let airtableAttachmentSource = 'image';
let airtableAttachmentDestination = 'image';
let airtableColumnToLog = 'name';
// SCRIPT SETTINGS add Input variables on the left
const inputConfig = input.config();
let recordId = inputConfig.recordId;
let tableName = inputConfig.tableName;
// Custom btoa function
function btoa(input) {
let chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
let str = String(input);
let output = '';
for (let block = 0, charCode, i = 0, map = chars;
str.charAt(i | 0) || (map = '=', i % 1);
output += map.charAt(63 & block >> 8 - i % 1 * 8)) {
charCode = str.charCodeAt(i += 3/4);
if (charCode > 0xFF) {
throw new Error("'btoa' failed: The string to be encoded contains characters outside of the Latin1 range.");
}
block = block << 8 | charCode;
}
return output;
}
if (!recordId || !tableName) {
throw new Error("Missing recordId or tableName in input config.");
}
let table = base.getTable(tableName);
// Fetch the specific record by its ID.
let record = await table.selectRecordAsync(recordId);
if (record) {
let attachments = record.getCellValue(airtableAttachmentSource);
let compressedImageUrls = [];
if (attachments && attachments.length > 0) {
// Iterate through each attachment in the field.
for (let [i, attachment] of attachments.entries()) {
let recordAttachmentUrl = attachment['url'];
console.log(`Compressing ${record.getCellValue(airtableColumnToLog)} (Image ${i + 1})`);
let request = {
body: JSON.stringify({'source': {'url': recordAttachmentUrl}}),
headers: {
Authorization: 'Basic ' + btoa('api:' + tinyPngApiKey),
'Content-Type': 'application/json'
},
method: 'POST'
};
try {
let response = await fetch('https://api.tinify.com/shrink', request);
const json = await response.json();
// Checks that the API didn't fail.
if (response.status == 201) {
let percentReduced = Math.round((1 - json.output.ratio) * 100);
let kbReduced = (json.input.size - json.output.size) / 1024;
console.log('Panda just saved you ' + percentReduced + '% (' + Math.round(kbReduced) + 'KB).');
// Add the compressed image URL to the array.
compressedImageUrls.push({ url: json['output']['url'] });
}
} catch (error) {
console.error('Error during fetch:', error);
}
}
// Update the record with all the compressed image URLs.
await table.updateRecordAsync(record.id, {
[airtableAttachmentDestination]: compressedImageUrls,
});
}
} else {
console.log(`Record with ID ${recordId} not found.`);
}