import { DeleteObjectCommand, GetObjectCommand, ListObjectsCommand, S3Client, } from "@aws-sdk/client-s3"; import { getSignedUrl } from "@aws-sdk/s3-request-presigner"; const BUCKET = "repertory"; const oldItems = []; const s3 = new S3Client({ region: "any", endpoint: "https://gateway.storjshare.io", forcePathStyle: true, credentials: { accessKeyId: process.env.R_AWS_KEY, secretAccessKey: process.env.R_AWS_SECRET, }, }); const cleanOldItems = async () => { console.log(`cleaning|count|${oldItems.length}`); while (oldItems.length > 0) { try { const key = oldItems.pop(); console.log(`cleaning|key|${key}`); await s3.send( new DeleteObjectCommand({ Bucket: BUCKET, Key: key, }), ); } catch (err) { console.error(err); } } }; const createDownloadLink = async (key) => { let filename = key.split("/"); filename = filename[filename.length - 1]; return await getSignedUrl( s3, new GetObjectCommand({ Bucket: BUCKET, Key: key, ResponseContentDisposition: `attachment; filename="${filename}"`, }), { expiresIn: 3600 }, ); }; const getBucketFiles = async (folderName) => { try { folderName = folderName.toLowerCase(); const folderKey = encodeURIComponent(folderName) + "/"; const data = await s3.send( new ListObjectsCommand({ Bucket: BUCKET, Prefix: folderKey, }), ); const ret = data.Contents.filter((item) => item.Key !== folderKey) .map((item) => { return { date: item.LastModified.toLocaleDateString("en-US", { year: "numeric", month: "2-digit", day: "2-digit", hour: "2-digit", minute: "2-digit", second: "2-digit", }).replace(/,/g, ""), sort: item.LastModified.getTime(), name: item.Key.replace(folderKey, ""), key: item.Key, }; }) .sort((a, b) => { return a.sort > b.sort ? -1 : a.sort < b.sort ? 1 : 0; }); const itemCount = {}; const ext = ".tar.gz"; const filteredItems = ret .filter((item) => item.name.endsWith(ext)) .filter((item) => { if (folderName === "nightly") { const parts = item.name.split("_"); const groupId = `${parts[0]}_${parts[3]}_${parts[4]}`; itemCount[groupId] = itemCount[groupId] || 0; if (++itemCount[groupId] <= 3) { return true; } if (!oldItems.find((key) => key === item.key)) { oldItems.push(item.key); oldItems.push(item.key + ".sha256"); oldItems.push(item.key + ".sig"); if (parts[3] === "windows") { const setup_key = item.key.substring(0, item.key.length - ext.length) + "_setup.exe"; const setup_item = ret.find((item) => item.key == setup_key); if (setup_item) { oldItems.push(setup_key); oldItems.push(setup_key + ".sha256"); oldItems.push(setup_key + ".sig"); } } } return false; } return true; }); const totalCount = filteredItems.length * 3; const setup_items = []; let setup_offset = 0; for (let i = 0; i < totalCount && i < filteredItems.length; i += 3) { const parts = filteredItems[i].name.split("_"); let item = ret.filter( (item) => item.name === filteredItems[i].name + ".sha256", ); filteredItems.splice(i + 1, 0, ...item); item = ret.filter((item) => item.name === filteredItems[i].name + ".sig"); filteredItems.splice(i + 2, 0, ...item); if (parts[3] === "windows") { const setup_key = filteredItems[i].key.substring( 0, filteredItems[i].key.length - ext.length, ) + "_setup.exe"; const setup_item = ret.find((item) => item.key == setup_key); if (setup_item) { const setup_item2 = ret.find( (item) => item.key == setup_key + ".sha256", ); const setup_item3 = ret.find( (item) => item.key == setup_key + ".sig", ); setup_items.push([ { idx: i + 3 + setup_offset }, setup_item, setup_item2, setup_item3, ]); setup_offset += 3; } } } if (setup_items.length > 0) { setup_items.forEach((items) => { filteredItems.splice(items[0].idx, 0, items[1]); filteredItems.splice(items[0].idx + 1, 0, items[2]); filteredItems.splice(items[0].idx + 2, 0, items[3]); }); } return filteredItems; } catch (err) { console.error(err); } return []; }; export { cleanOldItems, createDownloadLink, getBucketFiles };