diff --git a/packages/skin-database/cli.ts b/packages/skin-database/cli.ts index d58e6faa..39fa126f 100755 --- a/packages/skin-database/cli.ts +++ b/packages/skin-database/cli.ts @@ -31,6 +31,7 @@ import Shooter from "./shooter"; import { program } from "commander"; import * as config from "./config"; import { setHashesForSkin } from "./skinHash"; +import * as S3 from "./s3"; async function withHandler( cb: (handler: DiscordEventHandler) => Promise @@ -330,18 +331,24 @@ program ) .option("--refresh-content-hash", "Refresh content hash") .option("--update-search-index", "Refresh content hash") - .action( - async ({ + .option("--configure-r2-cors", "Configure CORS for r2") + .action(async (arg) => { + const { uploadIaScreenshot, uploadMissingScreenshots, refreshArchiveFiles, refreshContentHash, updateSearchIndex, - }) => { - if (updateSearchIndex) { - const ctx = new UserContext(); - const rows = await knex.raw( - ` + configureR2Cors, + } = arg; + console.log(arg); + if (configureR2Cors) { + await S3.configureCors(); + } + if (updateSearchIndex) { + const ctx = new UserContext(); + const rows = await knex.raw( + ` SELECT md5, update_timestamp FROM skins LEFT JOIN algolia_field_updates ON skins.md5 = algolia_field_updates.skin_md5 @@ -350,59 +357,58 @@ program GROUP BY md5 ORDER BY update_timestamp LIMIT ?;`, - [5000] - ); - const md5s = rows.map((row) => row.md5); - console.log(await Skins.updateSearchIndexs(ctx, md5s)); + [5000] + ); + const md5s = rows.map((row) => row.md5); + console.log(await Skins.updateSearchIndexs(ctx, md5s)); + } + if (refreshContentHash) { + const ctx = new UserContext(); + const skinRows = await knex("skins").select(); + console.log(`Found ${skinRows.length} skins to update`); + const skins = skinRows.map((row) => new SkinModel(ctx, row)); + for (const skin of skins) { + await Skins.setContentHash(skin.getMd5()); + process.stdout.write("."); } - if (refreshContentHash) { - const ctx = new UserContext(); - const skinRows = await knex("skins").select(); - console.log(`Found ${skinRows.length} skins to update`); - const skins = skinRows.map((row) => new SkinModel(ctx, row)); - for (const skin of skins) { - await Skins.setContentHash(skin.getMd5()); - process.stdout.write("."); - } + } + if (uploadIaScreenshot) { + const md5 = uploadIaScreenshot; + if (!(await SyncToArchive.uploadScreenshotIfSafe(md5))) { + console.log("Did not upload screenshot"); } - if (uploadIaScreenshot) { - const md5 = uploadIaScreenshot; - if (!(await SyncToArchive.uploadScreenshotIfSafe(md5))) { - console.log("Did not upload screenshot"); - } + } + if (refreshArchiveFiles) { + const ctx = new UserContext(); + const skinRows = await knex("skins") + .leftJoin("archive_files", "skins.md5", "archive_files.skin_md5") + .leftJoin("file_info", "file_info.file_md5", "archive_files.file_md5") + .where("skin_type", 1) + .where((builder) => { + return builder.where("file_info.file_md5", null); + }) + .limit(90000) + .groupBy("skins.md5") + .select(); + console.log(`Found ${skinRows.length} skins to update`); + const skins = skinRows.map((row) => new SkinModel(ctx, row)); + for (const skin of skins) { + await setHashesForSkin(skin); + // await Skins.setContentHash(skin.getMd5()); + process.stdout.write("."); } - if (refreshArchiveFiles) { - const ctx = new UserContext(); - const skinRows = await knex("skins") - .leftJoin("archive_files", "skins.md5", "archive_files.skin_md5") - .leftJoin("file_info", "file_info.file_md5", "archive_files.file_md5") - .where("skin_type", 1) - .where((builder) => { - return builder.where("file_info.file_md5", null); - }) - .limit(90000) - .groupBy("skins.md5") - .select(); - console.log(`Found ${skinRows.length} skins to update`); - const skins = skinRows.map((row) => new SkinModel(ctx, row)); - for (const skin of skins) { - await setHashesForSkin(skin); - // await Skins.setContentHash(skin.getMd5()); - process.stdout.write("."); - } - } - if (uploadMissingScreenshots) { - const md5s = await SyncToArchive.findItemsMissingImages(); - for (const md5 of md5s) { - if (await SyncToArchive.uploadScreenshotIfSafe(md5)) { - console.log("Upladed screenshot for ", md5); - } else { - console.log("Did not upload screenshot for ", md5); - } + } + if (uploadMissingScreenshots) { + const md5s = await SyncToArchive.findItemsMissingImages(); + for (const md5 of md5s) { + if (await SyncToArchive.uploadScreenshotIfSafe(md5)) { + console.log("Upladed screenshot for ", md5); + } else { + console.log("Did not upload screenshot for ", md5); } } } - ); + }); async function main() { try { diff --git a/packages/skin-database/s3.js b/packages/skin-database/s3.js index 50aba7b5..d65a4b63 100644 --- a/packages/skin-database/s3.js +++ b/packages/skin-database/s3.js @@ -2,10 +2,47 @@ const AWS = require("aws-sdk"); AWS.config.update({ region: "us-west-2" }); const { MD5_REGEX } = require("./utils"); +// https://developers.cloudflare.com/r2/examples/aws-sdk-js/ +const s3 = new AWS.S3({ + endpoint: process.env.CLOUDFLARE_R2_ENDPOINT, + accessKeyId: process.env.CLOUDFLARE_R2_ACCESS_KEY, + secretAccessKey: process.env.CLOUDFLARE_R2_SECRET_ACCESS_KEY, + signatureVersion: "v4", + region: "auto", +}); + +const bucketName = "winamp-skins"; + +async function configureCors() { + console.log("Going to configure cors"); + const current = await s3.getBucketCors({ Bucket: bucketName }).promise(); + console.log("Current cors", JSON.stringify(current, null, 2)); + await s3 + .putBucketCors({ + Bucket: bucketName, + CORSConfiguration: { + CORSRules: [ + { + AllowedOrigins: ["*"], + // It looks like R2 treats these as case sensitive, which I suspect is a bug. + AllowedHeaders: ["content-type", "Content-Type"], + AllowedMethods: ["PUT", "GET"], + }, + ], + }, + }) + .promise(); + const newCors = await s3.getBucketCors({ Bucket: bucketName }).promise(); + console.log("New cors", JSON.stringify(newCors, null, 2)); + console.log("Done"); +} + +/* const s3 = new AWS.S3({ // https://stackoverflow.com/a/40772298/1263117 region: "us-east-1", }); +*/ function putSkin(md5, buffer, ext = "wsz") { return new Promise((resolve, rejectPromise) => { @@ -33,7 +70,6 @@ function getSkinUploadUrl(md5, id) { if (!MD5_REGEX.test(md5)) { throw new Error(`Invalid md5: "${md5}"`); } - const bucketName = "cdn.webampskins.org"; const key = `user_uploads/${id}`; return s3.getSignedUrl("putObject", { Bucket: bucketName, @@ -46,7 +82,6 @@ function getSkinUploadUrl(md5, id) { } function getUploadedSkin(id) { - const bucketName = "cdn.webampskins.org"; const key = `user_uploads/${id}`; return new Promise((resolve, reject) => { s3.getObject( @@ -67,7 +102,6 @@ function getUploadedSkin(id) { function deleteSkin(md5, ext = "wsz") { return new Promise((resolve, rejectPromise) => { - const bucketName = "cdn.webampskins.org"; const key = `skins/${md5}.${ext}`; s3.deleteObject( { @@ -87,7 +121,6 @@ function deleteSkin(md5, ext = "wsz") { function deleteScreenshot(md5) { return new Promise((resolve, rejectPromise) => { - const bucketName = "cdn.webampskins.org"; const key = `screenshots/${md5}.png`; s3.deleteObject( { @@ -107,7 +140,6 @@ function deleteScreenshot(md5) { function putScreenshot(md5, buffer) { return new Promise((resolve, rejectPromise) => { - const bucketName = "cdn.webampskins.org"; const key = `screenshots/${md5}.png`; s3.putObject( { @@ -129,7 +161,6 @@ function putScreenshot(md5, buffer) { function putTemp(fileName, buffer) { return new Promise((resolve, rejectPromise) => { - const bucketName = "cdn.webampskins.org"; const key = `temp/${fileName}`; s3.putObject( { @@ -152,7 +183,6 @@ function putTemp(fileName, buffer) { function deleteTemp(fileName) { return new Promise((resolve, rejectPromise) => { - const bucketName = "cdn.webampskins.org"; const key = `screenshots/${fileName}`; s3.deleteObject( { @@ -179,4 +209,5 @@ module.exports = { getUploadedSkin, deleteScreenshot, getSkinUploadUrl, + configureCors, };