From f4e25a7bb21541061daf072c1659dee48e408e4b Mon Sep 17 00:00:00 2001 From: Jordan Eldredge Date: Fri, 24 Apr 2020 21:28:15 -0700 Subject: [PATCH] Start adopting types --- .../skin-database/data/{skins.js => skins.ts} | 131 +++++++++--------- experiments/skin-database/types.ts | 33 +++++ 2 files changed, 102 insertions(+), 62 deletions(-) rename experiments/skin-database/data/{skins.js => skins.ts} (66%) create mode 100644 experiments/skin-database/types.ts diff --git a/experiments/skin-database/data/skins.js b/experiments/skin-database/data/skins.ts similarity index 66% rename from experiments/skin-database/data/skins.js rename to experiments/skin-database/data/skins.ts index d94fbf5a..0441eaf4 100644 --- a/experiments/skin-database/data/skins.js +++ b/experiments/skin-database/data/skins.ts @@ -1,9 +1,11 @@ -const db = require("../db"); -const path = require("path"); +import db from "../db"; +import path from "path"; +import S3 from "../s3"; +import logger from "../logger"; +import { DBSkinRecord, SkinRecord, DBIARecord, TweetStatus } from "../types"; + const skins = db.get("skins"); const iaItems = db.get("internetArchiveItems"); -const S3 = require("../s3"); -const logger = require("../logger"); const CLASSIC_QUERY = { type: "CLASSIC", @@ -22,7 +24,7 @@ const REVIEWABLE_QUERY = { rejected: { $ne: true }, type: "CLASSIC", }; -function getSkinRecord(skin) { +function getSkinRecord(skin: DBSkinRecord): SkinRecord { const { md5, averageColor, @@ -34,7 +36,7 @@ function getSkinRecord(skin) { imageHash, uploader, } = skin; - const fileNames = filePaths.map(p => path.basename(p)); + const fileNames = filePaths.map((p) => path.basename(p)); const skinUrl = `https://s3.amazonaws.com/webamp-uploaded-skins/skins/${md5}.wsz`; return { skinUrl, @@ -53,20 +55,31 @@ function getSkinRecord(skin) { }; } -async function getProp(md5, prop) { +async function getProp( + md5: string, + prop: T +): Promise { const skin = await skins.findOne({ md5, type: "CLASSIC" }); const value = skin && skin[prop]; return value == null ? null : value; } -async function addSkin({ md5, filePath, uploader }) { - skins.insert({ md5, type: "CLASSIC", filePaths: [filePath], uploader }); +export async function addSkin({ md5, filePath, uploader, averageColor }) { + skins.insert({ + md5, + type: "CLASSIC", + filePaths: [filePath], + uploader, + averageColor, + }); } const IA_URL = /^(https:\/\/)?archive.org\/details\/([^\/]+)\/?/; const MD5 = /([a-fA-F0-9]{32})/; -async function getMd5ByAnything(anything) { +export async function getMd5ByAnything( + anything: string +): Promise { const md5Match = anything.match(MD5); if (md5Match != null) { const md5 = md5Match[1]; @@ -93,15 +106,15 @@ async function getMd5ByAnything(anything) { return imageHashMd5; } -async function getSkinByMd5(md5) { +export async function getSkinByMd5(md5: string) { const skin = await skins.findOne({ md5, type: "CLASSIC" }); if (skin == null) { logger.warn("Could not find skin in database", { md5, alert: true }); return null; } const internetArchiveItem = await getInternetArchiveItem(md5); - let internetArchiveUrl = null; - let internetArchiveItemName = null; + let internetArchiveUrl: string | null = null; + let internetArchiveItemName: string | null = null; if (internetArchiveItem != null) { internetArchiveItemName = internetArchiveItem.identifier; internetArchiveUrl = getInternetArchiveUrl(internetArchiveItemName); @@ -115,55 +128,59 @@ async function getSkinByMd5(md5) { }; } -async function getReadme(md5) { +export async function getReadme(md5: string) { return getProp(md5, "readmeText"); } -async function getScreenshotUrl(md5) { +export async function getScreenshotUrl(md5: string): Promise { + // @ts-ignore return getProp(md5, "screenshotUrl"); } -async function getSkinUrl(md5) { +export async function getSkinUrl(md5: string): Promise { + // @ts-ignore return getProp(md5, "skinUrl"); } -async function getInternetArchiveItem(md5) { +export async function getInternetArchiveItem(md5: string): Promise { return iaItems.findOne({ md5: md5 }); } -async function getMd5FromInternetArchvieItemName(itemName) { +async function getMd5FromInternetArchvieItemName(itemName: string) { const item = await iaItems.findOne({ identifier: itemName }, { md5: 1 }); return item == null ? null : item.md5; } -async function getMd5FromImageHash(imageHash) { - const item = await skins.findOne({ imageHash }, { md5: 1 }); - console.log(item); +async function getMd5FromImageHash(imageHash: string): Promise { + const item: { md5: string } | null = await skins.findOne( + { imageHash }, + { md5: 1 } + ); return item == null ? null : item.md5; } -async function getMd5sMatchingImageHash(imageHash) { +export async function getMd5sMatchingImageHash(imageHash: string) { return skins.find({ imageHash }, { md5: 1 }); } -function getInternetArchiveUrl(itemName) { +export function getInternetArchiveUrl(itemName: string | null): string | null { return itemName == null ? null : `https://archive.org/details/${itemName}`; } -function getTweetableSkinCount() { +export function getTweetableSkinCount(): Promise { return skins.count(TWEETABLE_QUERY); } -function getClassicSkinCount() { +export function getClassicSkinCount(): Promise { return skins.count(CLASSIC_QUERY); } -async function markAsTweeted(md5) { +export async function markAsTweeted(md5: string): Promise { await skins.findOneAndUpdate({ md5 }, { $set: { tweeted: true } }); return S3.markAsTweeted(md5); } -async function getStatus(md5) { +export async function getStatus(md5: string): Promise { const skin = await skins.findOne({ md5 }); if (skin.tweeted) { return "TWEETED"; @@ -177,17 +194,20 @@ async function getStatus(md5) { return "UNREVIEWED"; } -async function approve(md5) { +export async function approve(md5: string): Promise { await skins.findOneAndUpdate({ md5 }, { $set: { approved: true } }); return S3.approve(md5); } -async function reject(md5) { +export async function reject(md5: string): Promise { await skins.findOneAndUpdate({ md5 }, { $set: { rejected: true } }); return S3.reject(md5); } -async function getSkinToReview() { +export async function getSkinToReview(): Promise<{ + filename: string | null; + md5: string; +}> { const reviewable = await skins.aggregate([ { $match: REVIEWABLE_QUERY }, { $sample: { size: 1 } }, @@ -197,7 +217,10 @@ async function getSkinToReview() { return { filename: canonicalFilename, md5 }; } -async function getSkinToTweet() { +export async function getSkinToTweet(): Promise<{ + filename: string | null; + md5: string; +} | null> { const tweetables = await skins.aggregate([ { $match: TWEETABLE_QUERY }, { $sample: { size: 1 } }, @@ -210,7 +233,12 @@ async function getSkinToTweet() { return { filename: canonicalFilename, md5 }; } -async function getStats() { +export async function getStats(): Promise<{ + approved: number; + rejected: number; + tweeted: number; + tweetable: number; +}> { const approved = await skins.count({ approved: true }); const rejected = await skins.count({ rejected: true }); const tweeted = await skins.count({ tweeted: true }); @@ -218,30 +246,33 @@ async function getStats() { return { approved, rejected, tweeted, tweetable }; } -async function reconcile() { +export async function reconcile(): Promise { const [approved, rejected, tweeted] = await Promise.all([ S3.getAllApproved(), S3.getAllRejected(), S3.getAllTweeted(), ]); await Promise.all([ - ...approved.map(md5 => + ...approved.map((md5) => skins.findOneAndUpdate({ md5 }, { $set: { approved: true } }) ), - ...rejected.map(md5 => + ...rejected.map((md5) => skins.findOneAndUpdate({ md5 }, { $set: { rejected: true } }) ), - ...tweeted.map(md5 => + ...tweeted.map((md5) => skins.findOneAndUpdate({ md5 }, { $set: { tweeted: true } }) ), ]); } -async function setImageHash(md5, imageHash) { +export async function setImageHash( + md5: string, + imageHash: string +): Promise { await skins.findOneAndUpdate({ md5 }, { $set: { imageHash } }); } -async function getRandomClassicSkinMd5() { +export async function getRandomClassicSkinMd5() { const random = await skins.aggregate([ { $match: CLASSIC_QUERY }, { $sample: { size: 1 } }, @@ -251,27 +282,3 @@ async function getRandomClassicSkinMd5() { } return random[0].md5; } - -module.exports = { - addSkin, - getMd5sMatchingImageHash, - getInternetArchiveItem, - getMd5ByAnything, - getReadme, - getScreenshotUrl, - getSkinUrl, - getInternetArchiveUrl, - getSkinByMd5, - markAsTweeted, - getStatus, - approve, - reject, - getSkinToReview, - getStats, - getTweetableSkinCount, - reconcile, - getSkinToTweet, - setImageHash, - getClassicSkinCount, - getRandomClassicSkinMd5, -}; diff --git a/experiments/skin-database/types.ts b/experiments/skin-database/types.ts new file mode 100644 index 00000000..82049ea2 --- /dev/null +++ b/experiments/skin-database/types.ts @@ -0,0 +1,33 @@ +export type TweetStatus = "APPROVED" | "REJECTED" | "TWEETED" | "UNREVIEWED"; + +export type DBSkinRecord = { + md5: string; + averageColor?: string; + emails?: string[]; + tweetUrl?: string; + twitterLikes?: number; + readmeText?: string; + filePaths: string[]; + imageHash?: string; + uploader?: string; +}; + +export type DBIARecord = { + identifier: string; +}; + +export type SkinRecord = { + md5: string; + averageColor?: string; + emails?: string[]; + tweetUrl?: string; + twitterLikes?: number; + readmeText?: string; + fileNames: string[]; + imageHash?: string; + uploader?: string; + screenshotUrl: string; + skinUrl: string; + canonicalFilename: string | null; + webampUrl: string; +};