Clean up cache and add command to delete skin locally only

This commit is contained in:
Jordan Eldredge 2022-03-15 22:50:40 -07:00
parent 8997049e18
commit 87aa794312
4 changed files with 58 additions and 24 deletions

View file

@ -31,32 +31,41 @@ export async function addSkinFromBuffer(
const ctx = new UserContext();
const md5 = md5Buffer(buffer);
if (await SkinModel.exists(ctx, md5)) {
console.log("Skin found.")
return { md5, status: "FOUND" };
}
// Note: This will thrown on invalid skins.
console.log("Getting zip...")
const zip = await JSZip.loadAsync(buffer);
console.log("Getting skin type...")
const skinType = await getSkinType(zip);
switch (skinType) {
case "CLASSIC":
console.log("Adding classic skin...")
return addClassicSkinFromBuffer(ctx, buffer, md5, filePath, uploader);
case "MODERN":
return addModernSkinFromBuffer(buffer, md5, filePath, uploader);
return addModernSkinFromBuffer(ctx, buffer, md5, filePath, uploader);
}
}
async function addModernSkinFromBuffer(
ctx: UserContext,
buffer: Buffer,
md5: string,
filePath: string,
uploader: string
): Promise<Result> {
console.log("Write temporarty file.")
const tempFile = temp.path({ suffix: ".wal" });
fs.writeFileSync(tempFile, buffer);
console.log("Put skin to S3.")
await S3.putSkin(md5, buffer, "wal");
console.log("Add skin to DB")
await Skins.addSkin({
ctx,
md5,
filePath,
uploader,
@ -97,6 +106,7 @@ async function addClassicSkinFromBuffer(
await S3.putSkin(md5, buffer, "wsz");
await Skins.addSkin({
ctx,
md5,
filePath,
uploader,

View file

@ -73,7 +73,7 @@ program
.command("share")
.description(
"Share a skin on Twitter and Instagram. If no md5 is " +
"given, random approved skins are shared."
"given, random approved skins are shared."
)
.argument("[md5]", "md5 of the skin to share")
.option("-t, --twitter", "Share on Twitter")
@ -102,7 +102,12 @@ program
.option(
"--delete",
"Delete a skin from the database, including its S3 files " +
"CloudFlare cache and seach index entries."
"CloudFlare cache and seach index entries."
)
.option(
"--delete-local",
"Delete a skin from the database only, NOT including its S3 files " +
"CloudFlare cache and seach index entries."
)
.option("--index", "Update the seach index for a skin.")
.option(
@ -111,11 +116,14 @@ program
)
.option("--reject", 'Give a skin a "rejected" review.')
.option("--metadata", "Push metadata to the archive.")
.action(async (md5, { delete: del, index, refresh, reject, metadata }) => {
.action(async (md5, { delete: del, deleteLocal, index, refresh, reject, metadata }) => {
const ctx = new UserContext("CLI");
if (del) {
await Skins.deleteSkin(md5);
}
if (deleteLocal) {
await Skins.deleteLocalSkin(md5);
}
if (index) {
console.log(await Skins.updateSearchIndex(ctx, md5));
}
@ -170,18 +178,18 @@ program
.option(
"--fetch-metadata <count>",
"Fetch missing metadata for <count> items from the Internet " +
"Archive. Currently it only fetches missing metadata. In the " +
"future it could refresh stale metadata."
"Archive. Currently it only fetches missing metadata. In the " +
"future it could refresh stale metadata."
)
.option(
"--fetch-items",
"Seach the Internet Archive for items that we don't know about" +
"and add them to our database."
"and add them to our database."
)
.option(
"--update-metadata <count>",
"Find <count> items in our database that have incorrect or incomplete " +
"metadata, and update the Internet Archive"
"metadata, and update the Internet Archive"
)
.option(
"--upload-new",
@ -215,7 +223,7 @@ program
.command("stats")
.description(
"Report information about skins in the database. " +
"Identical to `!stats` in Discord."
"Identical to `!stats` in Discord."
)
.action(async () => {
console.table([await Skins.getStats()]);
@ -261,17 +269,17 @@ program
.option(
"--likes",
"Scrape @winampskins tweets for like and retweet counts, " +
"and update the database."
"and update the database."
)
.option(
"--milestones",
"Check the most recent @winampskins tweets to see if they have " +
"passed a milestone. If so, notify the Discord channel."
"passed a milestone. If so, notify the Discord channel."
)
.option(
"--followers",
"Check if @winampskins has passed a follower count milestone. " +
"If so, notify the Discord channel."
"If so, notify the Discord channel."
)
.action(async ({ likes, milestones, followers }) => {
if (likes) {
@ -299,7 +307,7 @@ program
.option(
"--upload-ia-screenshot <md5>",
"Upload a screenshot of a skin to the skin's Internet Archive itme. " +
"[[Warning!]] This might result in multiple screenshots on the item."
"[[Warning!]] This might result in multiple screenshots on the item."
)
.option(
"--upload-missing-screenshots",

View file

@ -27,7 +27,7 @@ export const IS_NOT_README =
/(genex\.txt)|(genexinfo\.txt)|(gen_gslyrics\.txt)|(region\.txt)|(pledit\.txt)|(viscolor\.txt)|(winampmb\.txt)|("gen_ex help\.txt)|(mbinner\.txt)$/i;
export default class SkinModel {
constructor(readonly ctx: UserContext, readonly row: SkinRow) {}
constructor(readonly ctx: UserContext, readonly row: SkinRow) { }
static async fromMd5(
ctx: UserContext,
@ -37,6 +37,13 @@ export default class SkinModel {
return row == null ? null : new SkinModel(ctx, row);
}
static clearMd5(
ctx: UserContext,
md5: string
): void {
getSkinLoader(ctx).clear(md5);
}
static async fromMd5Assert(
ctx: UserContext,
md5: string

View file

@ -26,11 +26,13 @@ export function getScreenshotUrl(md5: string): string {
}
export async function addSkin({
ctx,
md5,
filePath,
uploader,
modern,
}: {
ctx: UserContext,
md5: string;
filePath: string;
uploader: string;
@ -51,6 +53,7 @@ export async function addSkin({
},
[]
);
SkinModel.clearMd5(ctx, md5);
}
const CRUFT_FILENAME = /winampskins\.info\.(html)|(txt)$/;
@ -210,7 +213,21 @@ export async function updateSearchIndex(
// Note: This might leave behind some files in file_info.
export async function deleteSkin(md5: string): Promise<void> {
console.log(`Deleting skin ${md5}...`);
await deleteLocalSkin(md5);
console.log(`Deleting skin ${md5} from external sources...`);
console.log(`... removing from Algolia index`);
await searchIndex.deleteObjects([md5]);
console.log(`... removing skin from S3`);
await S3.deleteSkin(md5);
console.log(`... removing screenshot from S3`);
await S3.deleteScreenshot(md5);
console.log(`... purging screenshot and skin from CloudFlare`);
await CloudFlare.purgeFiles([getScreenshotUrl(md5), getSkinUrl(md5)]);
console.log(`Done deleting skin ${md5} from external sources.`);
}
export async function deleteLocalSkin(md5: string): Promise<void> {
console.log(`Deleting skin ${md5} locally...`);
console.log(`... sqlite "skins"`);
await knex("skins").where({ md5 }).limit(1).delete();
console.log(`... sqlite "refreshes"`);
@ -231,15 +248,7 @@ export async function deleteSkin(md5: string): Promise<void> {
await knex("skin_uploads").where({ skin_md5: md5 }).delete();
console.log(`... sqlite "screenshot_updates"`);
await knex("screenshot_updates").where({ skin_md5: md5 }).delete();
console.log(`... removing from Algolia index`);
await searchIndex.deleteObjects([md5]);
console.log(`... removing skin from S3`);
await S3.deleteSkin(md5);
console.log(`... removing screenshot from S3`);
await S3.deleteScreenshot(md5);
console.log(`... purging screenshot and skin from CloudFlare`);
await CloudFlare.purgeFiles([getScreenshotUrl(md5), getSkinUrl(md5)]);
console.log(`Done deleting skin ${md5}.`);
console.log(`Done deleting skin ${md5} locally.`);
}
export async function recordScreenshotUpdate(