webamp/packages/skin-database/api/graphql/resolvers/RootResolver.ts
Jordan Eldredge 612c7eea9a Remove log
2022-03-24 21:07:50 -07:00

160 lines
5.1 KiB
TypeScript

import IaItemModel from "../../../data/IaItemModel";
import SkinModel from "../../../data/SkinModel";
import TweetModel from "../../../data/TweetModel";
import SkinResolver from "../resolvers/SkinResolver";
import TweetResolver from "../resolvers/TweetResolver";
import UserResolver from "../resolvers/UserResolver";
import SkinsConnection from "../SkinsConnection";
import TweetsConnection from "../TweetsConnection";
import InternetArchiveItemResolver from "./InternetArchiveItemResolver";
import * as Skins from "../../../data/skins";
import algoliasearch from "algoliasearch";
import MutationResolver from "./MutationResolver";
import { knex } from "../../../db";
import ArchiveFileModel from "../../../data/ArchiveFileModel";
import ArchiveFileResolver from "./ArchiveFileResolver";
import DatabaseStatisticsResolver from "./DatabaseStatisticsResolver";
import { fromId } from "./NodeResolver";
import ModernSkinsConnection from "../ModernSkinsConnection";
import ModernSkinResolver from "./ModernSkinResolver";
// These keys are already in the web client, so they are not secret at all.
const client = algoliasearch("HQ9I5Z6IM5", "6466695ec3f624a5fccf46ec49680e51");
const index = client.initIndex("Skins");
class RootResolver extends MutationResolver {
async node({ id }, { ctx }) {
const { graphqlType, id: localId } = fromId(id);
// TODO Use typeResolver
switch (graphqlType) {
case "ClassicSkin":
case "ModernSkin": {
const skin = await SkinModel.fromMd5(ctx, localId);
if (skin == null) {
return null;
}
return SkinResolver.fromModel(skin);
}
}
return null;
}
async fetch_skin_by_md5({ md5 }, { ctx }) {
const skin = await SkinModel.fromMd5(ctx, md5);
if (skin == null) {
return null;
}
if (skin.getSkinType() === "MODERN") {
return new ModernSkinResolver(skin);
} else {
return SkinResolver.fromModel(skin);
}
}
async fetch_tweet_by_url({ url }, { ctx }) {
const tweet = await TweetModel.fromAnything(ctx, url);
if (tweet == null) {
return null;
}
return new TweetResolver(tweet);
}
async fetch_internet_archive_item_by_identifier({ identifier }, { ctx }) {
const iaItem = await IaItemModel.fromIdentifier(ctx, identifier);
if (iaItem == null) {
return null;
}
return new InternetArchiveItemResolver(iaItem);
}
async fetch_archive_file_by_md5({ md5 }, { ctx }) {
const archiveFile = await ArchiveFileModel.fromFileMd5(ctx, md5);
if (archiveFile == null) {
return null;
}
return new ArchiveFileResolver(archiveFile);
}
async search_skins({ query, first, offset }, { ctx }) {
if (first > 1000) {
throw new Error("Can only query 1000 records via search.");
}
const results: { hits: { md5: string }[] } = await index.search(query, {
attributesToRetrieve: ["md5"],
length: first,
offset,
});
return Promise.all(
results.hits.map(async (hit) => {
const model = await SkinModel.fromMd5Assert(ctx, hit.md5);
return SkinResolver.fromModel(model);
})
);
}
async skins({ first, offset, sort, filter }) {
if (first > 1000) {
throw new Error("Maximum limit is 1000");
}
return new SkinsConnection(first, offset, sort, filter);
}
async modern_skins({ first, offset }) {
if (first > 1000) {
throw new Error("Maximum limit is 1000");
}
return new ModernSkinsConnection(first, offset);
}
async skin_to_review(_args, { ctx }) {
if (!ctx.authed()) {
return null;
}
const { md5 } = await Skins.getSkinToReview();
const model = await SkinModel.fromMd5Assert(ctx, md5);
return SkinResolver.fromModel(model);
}
async tweets({ first, offset, sort }) {
if (first > 1000) {
throw new Error("Maximum limit is 1000");
}
return new TweetsConnection(first, offset, sort);
}
me() {
return new UserResolver();
}
async upload_statuses_by_md5({ md5s }, { ctx }) {
return this._upload_statuses({ keyName: "skin_md5", keys: md5s }, ctx);
}
async upload_statuses({ ids }, { ctx }) {
return this._upload_statuses({ keyName: "id", keys: ids }, ctx);
}
// Shared implementation for upload_statuses and upload_statuses_by_md5
async _upload_statuses({ keyName, keys }, ctx) {
const skins = await knex("skin_uploads")
.whereIn(keyName, keys)
.orderBy("id", "desc")
.select("id", "skin_md5", "status");
return Promise.all(
skins.map(async ({ id, skin_md5, status }) => {
// TODO: Could we avoid fetching the skin if it's not read?
const skinModel = await SkinModel.fromMd5(ctx, skin_md5);
const skin =
skinModel == null ? null : SkinResolver.fromModel(skinModel);
// Most of the time when a skin fails to process, it's due to some infa
// issue on our side, and we can recover. For now, we'll always tell the user
// That processing is just delayed.
status = status === "ERRORED" ? "DELAYED" : status;
return { id, skin, status, upload_md5: skin_md5 };
})
);
}
statistics() {
return new DatabaseStatisticsResolver();
}
}
export default RootResolver;