mirror of
https://github.com/captbaritone/webamp.git
synced 2026-01-23 02:15:01 +00:00
Typescript fixes
This commit is contained in:
parent
12ec93d2d2
commit
b794ca333c
6 changed files with 10 additions and 191 deletions
|
|
@ -35,7 +35,6 @@ import { setHashesForSkin } from "./skinHash";
|
|||
import * as S3 from "./s3";
|
||||
import { generateDescription } from "./services/openAi";
|
||||
import KeyValue from "./data/KeyValue";
|
||||
import detectRepacks from "./tasks/detectRepacks";
|
||||
|
||||
async function withHandler(
|
||||
cb: (handler: DiscordEventHandler) => Promise<void>
|
||||
|
|
@ -389,10 +388,6 @@ program
|
|||
"Compute the order in which skins should be displayed in the museum"
|
||||
)
|
||||
.option("--foo", "Learn about missing skins")
|
||||
.option(
|
||||
"--winampskinsinfo",
|
||||
"Detect skins that were broken by winampskins.info injecting an ad file"
|
||||
)
|
||||
.option("--test-cloudflare", "Try to upload to cloudflare")
|
||||
.action(async (arg) => {
|
||||
const {
|
||||
|
|
@ -404,16 +399,12 @@ program
|
|||
configureR2Cors,
|
||||
computeMuseumOrder,
|
||||
foo,
|
||||
winampskinsinfo,
|
||||
testCloudflare,
|
||||
} = arg;
|
||||
if (testCloudflare) {
|
||||
const buffer = new Buffer("testing", "utf8");
|
||||
await S3.putTemp("hello", buffer);
|
||||
}
|
||||
if (winampskinsinfo) {
|
||||
await detectRepacks();
|
||||
}
|
||||
if (computeMuseumOrder) {
|
||||
await Skins.computeMuseumOrder();
|
||||
console.log("Museum order updated.");
|
||||
|
|
@ -460,10 +451,12 @@ program
|
|||
}
|
||||
if (foo) {
|
||||
const ctx = new UserContext();
|
||||
const missingModernSkins = await KeyValue.get("missingModernSkins");
|
||||
const missingModernSkins = await KeyValue.get<string[]>(
|
||||
"missingModernSkins"
|
||||
);
|
||||
const missingModernSkinsSet = new Set(missingModernSkins);
|
||||
const skins = {};
|
||||
for (const md5 of missingModernSkins) {
|
||||
for (const md5 of missingModernSkins!) {
|
||||
const skin = await SkinModel.fromMd5(ctx, md5);
|
||||
if (skin == null) {
|
||||
continue;
|
||||
|
|
@ -489,7 +482,7 @@ program
|
|||
.select();
|
||||
console.log(`Found ${skinRows.length} skins to update`);
|
||||
const missingModernSkins = new Set(
|
||||
await KeyValue.get("missingModernSkins")
|
||||
await KeyValue.get<string[]>("missingModernSkins")
|
||||
);
|
||||
const skins = skinRows.map((row) => new SkinModel(ctx, row));
|
||||
for (const skin of skins) {
|
||||
|
|
|
|||
|
|
@ -249,7 +249,7 @@ export default class SkinModel {
|
|||
const response = await fetch(this.getSkinUrl());
|
||||
if (!response.ok) {
|
||||
const missingModernSkins =
|
||||
(await KeyValue.get("missingModernSkins")) ?? [];
|
||||
(await KeyValue.get<string[]>("missingModernSkins")) ?? [];
|
||||
const missingModernSkinsSet = new Set(missingModernSkins);
|
||||
missingModernSkinsSet.add(this.getMd5());
|
||||
await KeyValue.set(
|
||||
|
|
@ -410,6 +410,7 @@ export default class SkinModel {
|
|||
|
||||
getZip = mem(async (): Promise<JSZip> => {
|
||||
const buffer = await this.getBuffer();
|
||||
// @ts-ignore TODO: Is this typing correct?
|
||||
return JSZip.loadAsync(buffer);
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@
|
|||
"sync": "ts-node --transpile-only ./tasks/syncWithArchive.ts",
|
||||
"migrate": "knex migrate:latest",
|
||||
"grats": "grats",
|
||||
"typecheck": "tsc --noEmit",
|
||||
"dev:next": "next dev",
|
||||
"build:next": "next build",
|
||||
"start:next": "next start",
|
||||
|
|
|
|||
|
|
@ -1,8 +0,0 @@
|
|||
import Task from "./ITask";
|
||||
import * as Skins from "../data/skins";
|
||||
|
||||
export default class DeleteSkin extends Task {
|
||||
async run(): Promise<void> {
|
||||
await Skins.deleteSkin(md5);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,168 +0,0 @@
|
|||
import KeyValue from "../data/KeyValue";
|
||||
import SkinModel from "../data/SkinModel";
|
||||
import UserContext from "../data/UserContext";
|
||||
import { knex } from "../db";
|
||||
|
||||
export default async function detectRepacks() {
|
||||
const ctx = new UserContext();
|
||||
const stored = await KeyValue.get<{ [key: string]: string[] }>(
|
||||
"winampskins.info"
|
||||
);
|
||||
if (stored == null) {
|
||||
throw new Error("Expected kv");
|
||||
}
|
||||
|
||||
// console.log(stored);
|
||||
|
||||
let found = 0;
|
||||
let corrupt = 0;
|
||||
let identical = 0;
|
||||
|
||||
for (const [key, orignalCandidates] of Object.entries(stored)) {
|
||||
const repack = await SkinModel.fromMd5Assert(ctx, key);
|
||||
|
||||
for (const originalHash of orignalCandidates) {
|
||||
const original = await SkinModel.fromMd5Assert(ctx, originalHash);
|
||||
if (await isRepackOf(repack, original)) {
|
||||
console.log(`${key} is a repack of ${originalHash}`);
|
||||
found++;
|
||||
} else if (await areIdentical(repack, original)) {
|
||||
console.log(`${key} is an identical skin to ${originalHash}`);
|
||||
identical++;
|
||||
} else if (await isCorruptRepack(repack, original)) {
|
||||
console.log(`${key} is a CORRUPT repack of ${originalHash}`);
|
||||
corrupt++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
console.log(
|
||||
`Found ${found} originals out of ${Object.keys(stored).length} repacks`
|
||||
);
|
||||
console.log(
|
||||
`Found ${identical} twins out of ${Object.keys(stored).length} repacks`
|
||||
);
|
||||
console.log(
|
||||
`Found ${corrupt} corrupt repacks out of ${
|
||||
Object.keys(stored).length
|
||||
} repacks`
|
||||
);
|
||||
}
|
||||
|
||||
// A skin is a repack if it contains exactly the same files except for the addition of advertizing files
|
||||
async function isRepackOf(
|
||||
repack: SkinModel,
|
||||
original: SkinModel
|
||||
): Promise<boolean> {
|
||||
const nonAdHashesSet = await getSkinArchiveFileHashesSansAds(repack);
|
||||
const hashesSet = await getSkinArchiveFileHashes(original);
|
||||
return setsAreEqual(nonAdHashesSet, hashesSet);
|
||||
}
|
||||
|
||||
async function isCorruptRepack(
|
||||
repack: SkinModel,
|
||||
original: SkinModel
|
||||
): Promise<boolean> {
|
||||
const repackHashesSet = await getSkinArchiveFileHashes(repack);
|
||||
const hashesSet = await getSkinArchiveFileHashes(original);
|
||||
return setContains(repackHashesSet, hashesSet);
|
||||
}
|
||||
|
||||
async function areIdentical(
|
||||
repack: SkinModel,
|
||||
original: SkinModel
|
||||
): Promise<boolean> {
|
||||
const repackHashesSet = await getSkinArchiveFileHashes(repack);
|
||||
const hashesSet = await getSkinArchiveFileHashes(original);
|
||||
return setsAreEqual(repackHashesSet, hashesSet);
|
||||
}
|
||||
|
||||
async function getSkinArchiveFileHashes(skin: SkinModel): Promise<Set<string>> {
|
||||
const archiveFiles = await skin.getArchiveFiles();
|
||||
const nonAdHashes = archiveFiles.map((f) => f.getFileMd5());
|
||||
|
||||
return new Set(nonAdHashes);
|
||||
}
|
||||
|
||||
async function getSkinArchiveFileHashesSansAds(
|
||||
skin: SkinModel
|
||||
): Promise<Set<string>> {
|
||||
const archiveFiles = await skin.getArchiveFiles();
|
||||
const nonAdFiles = archiveFiles.filter(
|
||||
(f) => !f.getFileName().match(/winampskins\.info/)
|
||||
);
|
||||
|
||||
const nonAdHashes = nonAdFiles.map((f) => f.getFileMd5());
|
||||
|
||||
return new Set(nonAdHashes);
|
||||
}
|
||||
|
||||
// Get all the skins that have ad files in them
|
||||
async function getRepackSkins(ctx: UserContext) {
|
||||
const rows = await knex.raw(
|
||||
`SELECT DISTINCT(skin_md5) FROM archive_files WHERE file_name = "winampskins.info.txt";`
|
||||
);
|
||||
return Promise.all(
|
||||
rows.map((row) => {
|
||||
return SkinModel.fromMd5Assert(ctx, row.skin_md5);
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
function setsAreEqual(a: Set<string>, b: Set<string>): boolean {
|
||||
if (a === b) return true;
|
||||
if (a.size !== b.size) {
|
||||
return false;
|
||||
}
|
||||
for (const value of a) if (!b.has(value)) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Does a contain b?
|
||||
function setContains(a: Set<string>, b: Set<string>): boolean {
|
||||
if (a === b) return true;
|
||||
if (a.size < b.size) {
|
||||
return false;
|
||||
}
|
||||
for (const value of b) if (!a.has(value)) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
async function foo() {
|
||||
const repacks = await getRepackSkins(ctx);
|
||||
for (const skin of repacks) {
|
||||
const md5 = skin.getMd5();
|
||||
if (stored[md5] != null) {
|
||||
console.log(`Already computed ${md5}`);
|
||||
continue;
|
||||
}
|
||||
const archiveFiles = await skin.getArchiveFiles();
|
||||
const archiveFilesMd5 = archiveFiles.map((af) => af.getFileMd5());
|
||||
|
||||
const matches = await knex.raw(`
|
||||
SELECT
|
||||
skin_md5
|
||||
FROM
|
||||
(
|
||||
SELECT
|
||||
skin_md5,
|
||||
COUNT(*) as total_files,
|
||||
SUM(CASE WHEN file_md5 IN (${archiveFilesMd5
|
||||
.map((m) => `"${m}"`)
|
||||
.join(",")}) THEN 1 ELSE 0 END) as matching_files
|
||||
FROM
|
||||
archive_files
|
||||
GROUP BY
|
||||
skin_md5
|
||||
) AS t
|
||||
WHERE
|
||||
total_files = matching_files;
|
||||
`);
|
||||
const filtered = matches
|
||||
.map((r) => r.skin_md5)
|
||||
.filter((m) => m != skin_md5);
|
||||
stored[skin_md5] = filtered;
|
||||
await KeyValue.update("winampskins.info", stored);
|
||||
console.log(`Stored that ${skin_md5} matches ${JSON.stringify(filtered)}`);
|
||||
}
|
||||
}
|
||||
|
|
@ -103,8 +103,8 @@ export async function followerCount(handler: DiscordEventHandler) {
|
|||
const user = response.data;
|
||||
|
||||
const followerCount = user.followers_count;
|
||||
const current: { count: number } = await KeyValue.get(FOLLOW_COUNT_KEY);
|
||||
const currentNumber = current.count;
|
||||
const current = await KeyValue.get<{ count: number }>(FOLLOW_COUNT_KEY);
|
||||
const currentNumber = current!.count;
|
||||
|
||||
const nextMilestone = currentNumber + FOLLOW_COUNT_BRACKET_SIZE;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue