fix: more eslint stuff
This commit is contained in:
@@ -1,5 +1,4 @@
|
||||
import { APITokenMode, User } from "@prisma/client";
|
||||
import { H3Context, H3Event } from "h3";
|
||||
import { APITokenMode } from "@prisma/client";
|
||||
import prisma from "../db/database";
|
||||
import sessionHandler from "../session";
|
||||
import type { MinimumRequestObject } from "~/server/h3";
|
||||
@@ -98,7 +97,7 @@ class ACLManager {
|
||||
if (!token) return undefined;
|
||||
if (!token.userId)
|
||||
throw new Error(
|
||||
"No userId on user or client token - is something broken?"
|
||||
"No userId on user or client token - is something broken?",
|
||||
);
|
||||
|
||||
for (const acl of acls) {
|
||||
@@ -124,7 +123,7 @@ class ACLManager {
|
||||
|
||||
async allowSystemACL(
|
||||
request: MinimumRequestObject | undefined,
|
||||
acls: SystemACL
|
||||
acls: SystemACL,
|
||||
) {
|
||||
if (!request)
|
||||
throw new Error("Native web requests not available - weird deployment?");
|
||||
@@ -157,13 +156,17 @@ class ACLManager {
|
||||
for (const acl of acls) {
|
||||
if (acl.startsWith(userACLPrefix)) {
|
||||
const rawACL = acl.substring(userACLPrefix.length);
|
||||
const userId = await this.getUserIdACL(request, [rawACL as any]);
|
||||
const userId = await this.getUserIdACL(request, [
|
||||
rawACL as UserACL[number],
|
||||
]);
|
||||
if (!userId) return false;
|
||||
}
|
||||
|
||||
if (acl.startsWith(systemACLPrefix)) {
|
||||
const rawACL = acl.substring(systemACLPrefix.length);
|
||||
const allowed = await this.allowSystemACL(request, [rawACL as any]);
|
||||
const allowed = await this.allowSystemACL(request, [
|
||||
rawACL as SystemACL[number],
|
||||
]);
|
||||
if (!allowed) return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
import path from "path";
|
||||
import fs from "fs";
|
||||
import droplet from "@drop-oss/droplet";
|
||||
import type { CertificateStore} from "./ca-store";
|
||||
import { fsCertificateStore } from "./ca-store";
|
||||
import type { CertificateStore } from "./ca-store";
|
||||
|
||||
export type CertificateBundle = {
|
||||
priv: string;
|
||||
@@ -50,7 +47,7 @@ export class CertificateAuthority {
|
||||
clientId,
|
||||
clientName,
|
||||
caCertificate.cert,
|
||||
caCertificate.priv
|
||||
caCertificate.priv,
|
||||
);
|
||||
const certBundle: CertificateBundle = {
|
||||
priv,
|
||||
@@ -65,7 +62,7 @@ export class CertificateAuthority {
|
||||
|
||||
async fetchClientCertificate(clientId: string) {
|
||||
const isBlacklist = await this.certificateStore.checkBlacklistCertificate(
|
||||
`client:${clientId}`
|
||||
`client:${clientId}`,
|
||||
);
|
||||
if (isBlacklist) return undefined;
|
||||
return await this.certificateStore.fetch(`client:${clientId}`);
|
||||
|
||||
@@ -18,8 +18,8 @@ export const validCapabilities = Object.values(InternalClientCapability);
|
||||
|
||||
export type CapabilityConfiguration = {
|
||||
[InternalClientCapability.PeerAPI]: { endpoints: string[] };
|
||||
[InternalClientCapability.UserStatus]: {};
|
||||
[InternalClientCapability.CloudSaves]: {};
|
||||
[InternalClientCapability.UserStatus]: object;
|
||||
[InternalClientCapability.CloudSaves]: object;
|
||||
};
|
||||
|
||||
class CapabilityManager {
|
||||
@@ -53,7 +53,7 @@ class CapabilityManager {
|
||||
const serverCertificate = await ca.fetchClientCertificate("server");
|
||||
if (!serverCertificate)
|
||||
throw new Error(
|
||||
"CA not initialised properly - server mTLS certificate not present"
|
||||
"CA not initialised properly - server mTLS certificate not present",
|
||||
);
|
||||
const httpsAgent = new https.Agent({
|
||||
key: serverCertificate.priv,
|
||||
@@ -70,7 +70,9 @@ class CapabilityManager {
|
||||
});
|
||||
valid = true;
|
||||
break;
|
||||
} catch {}
|
||||
} catch {
|
||||
/* empty */
|
||||
}
|
||||
}
|
||||
|
||||
return valid;
|
||||
@@ -81,7 +83,7 @@ class CapabilityManager {
|
||||
|
||||
async validateCapabilityConfiguration(
|
||||
capability: InternalClientCapability,
|
||||
configuration: object
|
||||
configuration: object,
|
||||
) {
|
||||
const validationFunction = this.validationFunctions[capability];
|
||||
if (!validationFunction) return false;
|
||||
@@ -91,7 +93,7 @@ class CapabilityManager {
|
||||
async upsertClientCapability(
|
||||
capability: InternalClientCapability,
|
||||
rawCapability: object,
|
||||
clientId: string
|
||||
clientId: string,
|
||||
) {
|
||||
const upsertFunctions: EnumDictionary<
|
||||
InternalClientCapability,
|
||||
|
||||
@@ -6,7 +6,7 @@ import { useCertificateAuthority } from "~/server/plugins/ca";
|
||||
|
||||
export type EventHandlerFunction<T> = (
|
||||
h3: H3Event<EventHandlerRequest>,
|
||||
utils: ClientUtils
|
||||
utils: ClientUtils,
|
||||
) => Promise<T> | T;
|
||||
|
||||
type ClientUtils = {
|
||||
@@ -25,7 +25,7 @@ export function defineClientEventHandler<T>(handler: EventHandlerFunction<T>) {
|
||||
|
||||
let clientId: string;
|
||||
switch (method) {
|
||||
case "Debug":
|
||||
case "Debug": {
|
||||
if (!import.meta.dev) throw createError({ statusCode: 403 });
|
||||
const client = await prisma.client.findFirst({ select: { id: true } });
|
||||
if (!client)
|
||||
@@ -35,7 +35,8 @@ export function defineClientEventHandler<T>(handler: EventHandlerFunction<T>) {
|
||||
});
|
||||
clientId = client.id;
|
||||
break;
|
||||
case "Nonce":
|
||||
}
|
||||
case "Nonce": {
|
||||
clientId = parts[0];
|
||||
const nonce = parts[1];
|
||||
const signature = parts[2];
|
||||
@@ -59,9 +60,8 @@ export function defineClientEventHandler<T>(handler: EventHandlerFunction<T>) {
|
||||
}
|
||||
|
||||
const certificateAuthority = useCertificateAuthority();
|
||||
const certBundle = await certificateAuthority.fetchClientCertificate(
|
||||
clientId
|
||||
);
|
||||
const certBundle =
|
||||
await certificateAuthority.fetchClientCertificate(clientId);
|
||||
// This does the blacklist check already
|
||||
if (!certBundle)
|
||||
throw createError({
|
||||
@@ -76,11 +76,13 @@ export function defineClientEventHandler<T>(handler: EventHandlerFunction<T>) {
|
||||
statusMessage: "Invalid nonce signature.",
|
||||
});
|
||||
break;
|
||||
default:
|
||||
}
|
||||
default: {
|
||||
throw createError({
|
||||
statusCode: 403,
|
||||
statusMessage: "No authentication",
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (clientId === undefined)
|
||||
@@ -95,7 +97,7 @@ export function defineClientEventHandler<T>(handler: EventHandlerFunction<T>) {
|
||||
});
|
||||
if (!client)
|
||||
throw new Error(
|
||||
"client util fetch client broke - this should NOT happen"
|
||||
"client util fetch client broke - this should NOT happen",
|
||||
);
|
||||
return client;
|
||||
}
|
||||
@@ -110,7 +112,7 @@ export function defineClientEventHandler<T>(handler: EventHandlerFunction<T>) {
|
||||
|
||||
if (!client)
|
||||
throw new Error(
|
||||
"client util fetch client broke - this should NOT happen"
|
||||
"client util fetch client broke - this should NOT happen",
|
||||
);
|
||||
|
||||
return client.user;
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { randomUUID } from "node:crypto";
|
||||
import { CertificateBundle } from "./ca";
|
||||
import prisma from "../db/database";
|
||||
import type { Platform } from "@prisma/client";
|
||||
import { useCertificateAuthority } from "~/server/plugins/ca";
|
||||
@@ -10,25 +9,29 @@ export interface ClientMetadata {
|
||||
}
|
||||
|
||||
export class ClientHandler {
|
||||
private temporaryClientTable: {
|
||||
[key: string]: {
|
||||
private temporaryClientTable = new Map<
|
||||
string,
|
||||
{
|
||||
timeout: NodeJS.Timeout;
|
||||
data: ClientMetadata;
|
||||
userId?: string;
|
||||
authToken?: string;
|
||||
};
|
||||
} = {};
|
||||
}
|
||||
>();
|
||||
|
||||
async initiate(metadata: ClientMetadata) {
|
||||
const clientId = randomUUID();
|
||||
|
||||
this.temporaryClientTable[clientId] = {
|
||||
this.temporaryClientTable.set(clientId, {
|
||||
data: metadata,
|
||||
timeout: setTimeout(() => {
|
||||
if (this.temporaryClientTable[clientId])
|
||||
delete this.temporaryClientTable[clientId];
|
||||
}, 1000 * 60 * 10), // 10 minutes
|
||||
};
|
||||
timeout: setTimeout(
|
||||
() => {
|
||||
if (this.temporaryClientTable.has(clientId))
|
||||
this.temporaryClientTable.delete(clientId);
|
||||
},
|
||||
1000 * 60 * 10,
|
||||
), // 10 minutes
|
||||
});
|
||||
|
||||
return clientId;
|
||||
}
|
||||
@@ -38,23 +41,23 @@ export class ClientHandler {
|
||||
}
|
||||
|
||||
async fetchClient(clientId: string) {
|
||||
const entry = this.temporaryClientTable[clientId];
|
||||
const entry = this.temporaryClientTable.get(clientId);
|
||||
if (!entry) return undefined;
|
||||
return entry;
|
||||
}
|
||||
|
||||
async attachUserId(clientId: string, userId: string) {
|
||||
if (!this.temporaryClientTable[clientId])
|
||||
throw new Error("Invalid clientId for attaching userId");
|
||||
this.temporaryClientTable[clientId].userId = userId;
|
||||
const clientTable = this.temporaryClientTable.get(clientId);
|
||||
if (!clientTable) throw new Error("Invalid clientId for attaching userId");
|
||||
clientTable.userId = userId;
|
||||
}
|
||||
|
||||
async generateAuthToken(clientId: string) {
|
||||
const entry = this.temporaryClientTable[clientId];
|
||||
const entry = this.temporaryClientTable.get(clientId);
|
||||
if (!entry) throw new Error("Invalid clientId to generate token");
|
||||
|
||||
const token = randomUUID();
|
||||
this.temporaryClientTable[clientId].authToken = token;
|
||||
entry.authToken = token;
|
||||
|
||||
return token;
|
||||
}
|
||||
@@ -66,7 +69,7 @@ export class ClientHandler {
|
||||
}
|
||||
|
||||
async finialiseClient(id: string) {
|
||||
const metadata = this.temporaryClientTable[id];
|
||||
const metadata = this.temporaryClientTable.get(id);
|
||||
if (!metadata) throw new Error("Invalid client ID");
|
||||
if (!metadata.userId) throw new Error("Un-authorized client ID");
|
||||
|
||||
|
||||
@@ -5,6 +5,5 @@ When a client signs on and registers itself as a peer
|
||||
|
||||
*/
|
||||
|
||||
class DownloadCoordinator {
|
||||
|
||||
}
|
||||
// eslint-disable-next-line @typescript-eslint/no-extraneous-class, @typescript-eslint/no-unused-vars
|
||||
class DownloadCoordinator {}
|
||||
|
||||
@@ -33,7 +33,7 @@ class ManifestGenerator {
|
||||
key,
|
||||
Object.assign({}, value, { versionName: rootManifest.versionName }),
|
||||
];
|
||||
})
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -71,6 +71,7 @@ class ManifestGenerator {
|
||||
if (baseVersion.delta) {
|
||||
// Start at the same index minus one, and keep grabbing them
|
||||
// until we run out or we hit something that isn't a delta
|
||||
// eslint-disable-next-line no-constant-condition
|
||||
for (let i = baseVersion.versionIndex - 1; true; i--) {
|
||||
const currentVersion = await prisma.gameVersion.findFirst({
|
||||
where: {
|
||||
@@ -88,7 +89,7 @@ class ManifestGenerator {
|
||||
const metadata: DropManifestMetadata[] = leastToMost.map((e) => {
|
||||
return {
|
||||
manifest: JSON.parse(
|
||||
e.dropletManifest?.toString() ?? "{}"
|
||||
e.dropletManifest?.toString() ?? "{}",
|
||||
) as DropManifest,
|
||||
versionName: e.versionName,
|
||||
};
|
||||
@@ -96,7 +97,7 @@ class ManifestGenerator {
|
||||
|
||||
const manifest = ManifestGenerator.generateManifestFromMetadata(
|
||||
metadata[0],
|
||||
...metadata.slice(1)
|
||||
...metadata.slice(1),
|
||||
);
|
||||
|
||||
return manifest;
|
||||
|
||||
@@ -8,8 +8,7 @@
|
||||
import fs from "fs";
|
||||
import path from "path";
|
||||
import prisma from "../db/database";
|
||||
import type { GameVersion} from "@prisma/client";
|
||||
import { Platform } from "@prisma/client";
|
||||
import type { GameVersion } from "@prisma/client";
|
||||
import { fuzzy } from "fast-fuzzy";
|
||||
import { recursivelyReaddir } from "../utils/recursivedirs";
|
||||
import taskHandler from "../tasks";
|
||||
@@ -52,13 +51,13 @@ class LibraryManager {
|
||||
|
||||
async fetchUnimportedGameVersions(
|
||||
libraryBasePath: string,
|
||||
versions: Array<GameVersion>
|
||||
versions: Array<GameVersion>,
|
||||
) {
|
||||
const gameDir = path.join(this.basePath, libraryBasePath);
|
||||
const versionsDirs = fs.readdirSync(gameDir);
|
||||
const importedVersionDirs = versions.map((e) => e.versionName);
|
||||
const unimportedVersions = versionsDirs.filter(
|
||||
(e) => !importedVersionDirs.includes(e)
|
||||
(e) => !importedVersionDirs.includes(e),
|
||||
);
|
||||
|
||||
return unimportedVersions;
|
||||
@@ -89,10 +88,10 @@ class LibraryManager {
|
||||
noVersions: e.versions.length == 0,
|
||||
unimportedVersions: await this.fetchUnimportedGameVersions(
|
||||
e.libraryBasePath,
|
||||
e.versions
|
||||
e.versions,
|
||||
),
|
||||
},
|
||||
}))
|
||||
})),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -113,7 +112,7 @@ class LibraryManager {
|
||||
const targetDir = path.join(this.basePath, game.libraryBasePath);
|
||||
if (!fs.existsSync(targetDir))
|
||||
throw new Error(
|
||||
"Game in database, but no physical directory? Something is very very wrong..."
|
||||
"Game in database, but no physical directory? Something is very very wrong...",
|
||||
);
|
||||
const versions = fs.readdirSync(targetDir);
|
||||
const validVersions = versions.filter((versionDir) => {
|
||||
@@ -124,7 +123,7 @@ class LibraryManager {
|
||||
const currentVersions = game.versions.map((e) => e.versionName);
|
||||
|
||||
const unimportedVersions = validVersions.filter(
|
||||
(e) => !currentVersions.includes(e)
|
||||
(e) => !currentVersions.includes(e),
|
||||
);
|
||||
return unimportedVersions;
|
||||
}
|
||||
@@ -138,7 +137,7 @@ class LibraryManager {
|
||||
const targetDir = path.join(
|
||||
this.basePath,
|
||||
game.libraryBasePath,
|
||||
versionName
|
||||
versionName,
|
||||
);
|
||||
if (!fs.existsSync(targetDir)) return undefined;
|
||||
|
||||
@@ -217,7 +216,7 @@ class LibraryManager {
|
||||
delta: boolean;
|
||||
|
||||
umuId: string;
|
||||
}
|
||||
},
|
||||
) {
|
||||
const taskId = `import:${gameId}:${versionName}`;
|
||||
|
||||
@@ -254,7 +253,7 @@ class LibraryManager {
|
||||
(err, manifest) => {
|
||||
if (err) return reject(err);
|
||||
resolve(manifest);
|
||||
}
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
@@ -1,10 +1,5 @@
|
||||
import type {
|
||||
Developer,
|
||||
Publisher} from "@prisma/client";
|
||||
import {
|
||||
MetadataSource,
|
||||
PrismaClient
|
||||
} from "@prisma/client";
|
||||
import type { Developer, Publisher } from "@prisma/client";
|
||||
import { MetadataSource } from "@prisma/client";
|
||||
import prisma from "../db/database";
|
||||
import type {
|
||||
_FetchDeveloperMetadataParams,
|
||||
@@ -17,11 +12,7 @@ import type {
|
||||
PublisherMetadata,
|
||||
} from "./types";
|
||||
import { ObjectTransactionalHandler } from "../objects/transactional";
|
||||
import { PriorityList, PriorityListIndexed } from "../utils/prioritylist";
|
||||
import { GiantBombProvider } from "./giantbomb";
|
||||
import { ManualMetadataProvider } from "./manual";
|
||||
import { PCGamingWikiProvider } from "./pcgamingwiki";
|
||||
import { IGDBProvider } from "./igdb";
|
||||
import { PriorityListIndexed } from "../utils/prioritylist";
|
||||
|
||||
export class MissingMetadataProviderConfig extends Error {
|
||||
private providerName: string;
|
||||
@@ -47,10 +38,10 @@ export abstract class MetadataProvider {
|
||||
abstract search(query: string): Promise<GameMetadataSearchResult[]>;
|
||||
abstract fetchGame(params: _FetchGameMetadataParams): Promise<GameMetadata>;
|
||||
abstract fetchPublisher(
|
||||
params: _FetchPublisherMetadataParams
|
||||
params: _FetchPublisherMetadataParams,
|
||||
): Promise<PublisherMetadata>;
|
||||
abstract fetchDeveloper(
|
||||
params: _FetchDeveloperMetadataParams
|
||||
params: _FetchDeveloperMetadataParams,
|
||||
): Promise<DeveloperMetadata>;
|
||||
}
|
||||
|
||||
@@ -81,6 +72,8 @@ export class MetadataHandler {
|
||||
for (const provider of this.providers.values()) {
|
||||
const queryTransformationPromise = new Promise<
|
||||
InternalGameMetadataResult[]
|
||||
// TODO: fix eslint error
|
||||
// eslint-disable-next-line no-async-promise-executor
|
||||
>(async (resolve, reject) => {
|
||||
try {
|
||||
const results = await provider.search(query);
|
||||
@@ -89,7 +82,7 @@ export class MetadataHandler {
|
||||
Object.assign({}, result, {
|
||||
sourceId: provider.id(),
|
||||
sourceName: provider.name(),
|
||||
})
|
||||
}),
|
||||
);
|
||||
resolve(mappedResults);
|
||||
} catch (e) {
|
||||
@@ -119,13 +112,13 @@ export class MetadataHandler {
|
||||
sourceId: "manual",
|
||||
sourceName: "Manual",
|
||||
},
|
||||
libraryBasePath
|
||||
libraryBasePath,
|
||||
);
|
||||
}
|
||||
|
||||
async createGame(
|
||||
result: InternalGameMetadataResult,
|
||||
libraryBasePath: string
|
||||
libraryBasePath: string,
|
||||
) {
|
||||
const provider = this.providers.get(result.sourceId);
|
||||
if (!provider)
|
||||
@@ -143,7 +136,7 @@ export class MetadataHandler {
|
||||
|
||||
const [createObject, pullObjects, dumpObjects] = this.objectHandler.new(
|
||||
{},
|
||||
["internal:read"]
|
||||
["internal:read"],
|
||||
);
|
||||
|
||||
let metadata;
|
||||
@@ -197,7 +190,7 @@ export class MetadataHandler {
|
||||
return (await this.fetchDeveloperPublisher(
|
||||
query,
|
||||
"fetchDeveloper",
|
||||
"developer"
|
||||
"developer",
|
||||
)) as Developer;
|
||||
}
|
||||
|
||||
@@ -205,7 +198,7 @@ export class MetadataHandler {
|
||||
return (await this.fetchDeveloperPublisher(
|
||||
query,
|
||||
"fetchPublisher",
|
||||
"publisher"
|
||||
"publisher",
|
||||
)) as Publisher;
|
||||
}
|
||||
|
||||
@@ -214,8 +207,9 @@ export class MetadataHandler {
|
||||
private async fetchDeveloperPublisher(
|
||||
query: string,
|
||||
functionName: "fetchDeveloper" | "fetchPublisher",
|
||||
databaseName: "developer" | "publisher"
|
||||
databaseName: "developer" | "publisher",
|
||||
) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const existing = await (prisma as any)[databaseName].findFirst({
|
||||
where: {
|
||||
metadataOriginalQuery: query,
|
||||
@@ -229,7 +223,7 @@ export class MetadataHandler {
|
||||
|
||||
const [createObject, pullObjects, dumpObjects] = this.objectHandler.new(
|
||||
{},
|
||||
["internal:read"]
|
||||
["internal:read"],
|
||||
);
|
||||
let result: PublisherMetadata;
|
||||
try {
|
||||
@@ -243,6 +237,7 @@ export class MetadataHandler {
|
||||
// If we're successful
|
||||
await pullObjects();
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const object = await (prisma as any)[databaseName].create({
|
||||
data: {
|
||||
metadataSource: provider.source(),
|
||||
@@ -262,7 +257,7 @@ export class MetadataHandler {
|
||||
}
|
||||
|
||||
throw new Error(
|
||||
`No metadata provider found a ${databaseName} for "${query}"`
|
||||
`No metadata provider found a ${databaseName} for "${query}"`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,9 +6,7 @@ import type {
|
||||
_FetchPublisherMetadataParams,
|
||||
PublisherMetadata,
|
||||
_FetchDeveloperMetadataParams,
|
||||
DeveloperMetadata} from "./types";
|
||||
import {
|
||||
GameMetadataSearchResult
|
||||
DeveloperMetadata,
|
||||
} from "./types";
|
||||
import * as jdenticon from "jdenticon";
|
||||
|
||||
@@ -22,13 +20,11 @@ export class ManualMetadataProvider implements MetadataProvider {
|
||||
source() {
|
||||
return MetadataSource.Manual;
|
||||
}
|
||||
async search(query: string) {
|
||||
async search(_query: string) {
|
||||
return [];
|
||||
}
|
||||
async fetchGame({
|
||||
name,
|
||||
publisher,
|
||||
developer,
|
||||
createObject,
|
||||
}: _FetchGameMetadataParams): Promise<GameMetadata> {
|
||||
const icon = jdenticon.toPng(name, 512);
|
||||
@@ -52,12 +48,12 @@ export class ManualMetadataProvider implements MetadataProvider {
|
||||
};
|
||||
}
|
||||
async fetchPublisher(
|
||||
params: _FetchPublisherMetadataParams
|
||||
_params: _FetchPublisherMetadataParams,
|
||||
): Promise<PublisherMetadata> {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
async fetchDeveloper(
|
||||
params: _FetchDeveloperMetadataParams
|
||||
_params: _FetchDeveloperMetadataParams,
|
||||
): Promise<DeveloperMetadata> {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import type { Developer, Publisher } from "@prisma/client";
|
||||
import { MetadataSource } from "@prisma/client";
|
||||
import type { MetadataProvider} from ".";
|
||||
import { MissingMetadataProviderConfig } from ".";
|
||||
import type { MetadataProvider } from ".";
|
||||
import type {
|
||||
GameMetadataSearchResult,
|
||||
_FetchGameMetadataParams,
|
||||
@@ -48,7 +47,7 @@ interface PCGamingWikiCargoResult<T> {
|
||||
cargoquery: [
|
||||
{
|
||||
title: T;
|
||||
}
|
||||
},
|
||||
];
|
||||
error?: {
|
||||
code?: string;
|
||||
@@ -61,8 +60,6 @@ interface PCGamingWikiCargoResult<T> {
|
||||
// Api Docs: https://www.pcgamingwiki.com/wiki/PCGamingWiki:API
|
||||
// Good tool for helping build cargo queries: https://www.pcgamingwiki.com/wiki/Special:CargoQuery
|
||||
export class PCGamingWikiProvider implements MetadataProvider {
|
||||
constructor() {}
|
||||
|
||||
id() {
|
||||
return "pcgamingwiki";
|
||||
}
|
||||
@@ -75,7 +72,7 @@ export class PCGamingWikiProvider implements MetadataProvider {
|
||||
|
||||
private async request<T>(
|
||||
query: URLSearchParams,
|
||||
options?: AxiosRequestConfig
|
||||
options?: AxiosRequestConfig,
|
||||
) {
|
||||
const finalURL = `https://www.pcgamingwiki.com/w/api.php?${query.toString()}`;
|
||||
|
||||
@@ -84,12 +81,12 @@ export class PCGamingWikiProvider implements MetadataProvider {
|
||||
baseURL: "",
|
||||
};
|
||||
const response = await axios.request<PCGamingWikiCargoResult<T>>(
|
||||
Object.assign({}, options, overlay)
|
||||
Object.assign({}, options, overlay),
|
||||
);
|
||||
|
||||
if (response.status !== 200)
|
||||
throw new Error(
|
||||
`Error in pcgamingwiki \nStatus Code: ${response.status}`
|
||||
`Error in pcgamingwiki \nStatus Code: ${response.status}`,
|
||||
);
|
||||
else if (response.data.error !== undefined)
|
||||
throw new Error(`Error in pcgamingwiki, malformed query`);
|
||||
@@ -256,7 +253,7 @@ export class PCGamingWikiProvider implements MetadataProvider {
|
||||
}
|
||||
|
||||
async fetchDeveloper(
|
||||
params: _FetchDeveloperMetadataParams
|
||||
params: _FetchDeveloperMetadataParams,
|
||||
): Promise<DeveloperMetadata> {
|
||||
return await this.fetchPublisher(params);
|
||||
}
|
||||
|
||||
Vendored
-1
@@ -1,6 +1,5 @@
|
||||
import type { Developer, Publisher } from "@prisma/client";
|
||||
import type { TransactionDataType } from "../objects/transactional";
|
||||
import { ObjectTransactionalHandler } from "../objects/transactional";
|
||||
import type { ObjectReference } from "../objects/objectHandler";
|
||||
|
||||
export interface GameMetadataSearchResult {
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { triggerAsyncId } from "async_hooks";
|
||||
import prisma from "../db/database";
|
||||
import objectHandler from "../objects";
|
||||
|
||||
@@ -50,7 +49,7 @@ class NewsManager {
|
||||
orderBy?: "asc" | "desc";
|
||||
tags?: string[];
|
||||
search?: string;
|
||||
} = {}
|
||||
} = {},
|
||||
) {
|
||||
return await prisma.article.findMany({
|
||||
where: {
|
||||
@@ -116,7 +115,7 @@ class NewsManager {
|
||||
content?: string;
|
||||
excerpt?: string;
|
||||
image?: string;
|
||||
}
|
||||
},
|
||||
) {
|
||||
return await prisma.article.update({
|
||||
where: { id },
|
||||
|
||||
@@ -15,27 +15,28 @@ export type NotificationCreateArgs = Pick<
|
||||
>;
|
||||
|
||||
class NotificationSystem {
|
||||
private listeners: {
|
||||
[key: string]: Map<string, (notification: Notification) => any>;
|
||||
} = {};
|
||||
private listeners = new Map<
|
||||
string,
|
||||
Map<string, (notification: Notification) => void>
|
||||
>();
|
||||
|
||||
listen(
|
||||
userId: string,
|
||||
id: string,
|
||||
callback: (notification: Notification) => any
|
||||
callback: (notification: Notification) => void,
|
||||
) {
|
||||
this.listeners[userId] ??= new Map();
|
||||
this.listeners[userId].set(id, callback);
|
||||
this.listeners.set(userId, new Map());
|
||||
this.listeners.get(userId)?.set(id, callback);
|
||||
|
||||
this.catchupListener(userId, id);
|
||||
}
|
||||
|
||||
unlisten(userId: string, id: string) {
|
||||
this.listeners[userId].delete(id);
|
||||
this.listeners.get(userId)?.delete(id);
|
||||
}
|
||||
|
||||
private async catchupListener(userId: string, id: string) {
|
||||
const callback = this.listeners[userId].get(id);
|
||||
const callback = this.listeners.get(userId)?.get(id);
|
||||
if (!callback)
|
||||
throw new Error("Failed to catch-up listener: callback does not exist");
|
||||
const notifications = await prisma.notification.findMany({
|
||||
@@ -50,7 +51,7 @@ class NotificationSystem {
|
||||
}
|
||||
|
||||
private async pushNotification(userId: string, notification: Notification) {
|
||||
for (const listener of this.listeners[userId] ?? []) {
|
||||
for (const listener of this.listeners.get(userId) ?? []) {
|
||||
await listener[1](notification);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import { ObjectBackend } from "./objectHandler";
|
||||
import { LRUCache } from "lru-cache";
|
||||
import fs from "fs";
|
||||
import path from "path";
|
||||
import { Readable, Stream } from "stream";
|
||||
import { Readable } from "stream";
|
||||
import { createHash } from "crypto";
|
||||
import prisma from "../db/database";
|
||||
|
||||
@@ -40,7 +40,7 @@ export class FsObjectBackend extends ObjectBackend {
|
||||
if (source instanceof Readable) {
|
||||
const outputStream = fs.createWriteStream(objectPath);
|
||||
source.pipe(outputStream, { end: true });
|
||||
await new Promise((r, j) => source.on("end", r));
|
||||
await new Promise((r, _j) => source.on("end", r));
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -61,7 +61,7 @@ export class FsObjectBackend extends ObjectBackend {
|
||||
async create(
|
||||
id: string,
|
||||
source: Source,
|
||||
metadata: ObjectMetadata
|
||||
metadata: ObjectMetadata,
|
||||
): Promise<ObjectReference | undefined> {
|
||||
const objectPath = path.join(this.baseObjectPath, id);
|
||||
const metadataPath = path.join(this.baseMetadataPath, `${id}.json`);
|
||||
@@ -104,7 +104,7 @@ export class FsObjectBackend extends ObjectBackend {
|
||||
return true;
|
||||
}
|
||||
async fetchMetadata(
|
||||
id: ObjectReference
|
||||
id: ObjectReference,
|
||||
): Promise<ObjectMetadata | undefined> {
|
||||
const metadataPath = path.join(this.baseMetadataPath, `${id}.json`);
|
||||
if (!fs.existsSync(metadataPath)) return undefined;
|
||||
@@ -113,7 +113,7 @@ export class FsObjectBackend extends ObjectBackend {
|
||||
}
|
||||
async writeMetadata(
|
||||
id: ObjectReference,
|
||||
metadata: ObjectMetadata
|
||||
metadata: ObjectMetadata,
|
||||
): Promise<boolean> {
|
||||
const metadataPath = path.join(this.baseMetadataPath, `${id}.json`);
|
||||
if (!fs.existsSync(metadataPath)) return false;
|
||||
@@ -153,8 +153,6 @@ class FsHashStore {
|
||||
max: 1000, // number of items
|
||||
});
|
||||
|
||||
constructor() {}
|
||||
|
||||
/**
|
||||
* Gets hash of object
|
||||
* @param id
|
||||
@@ -211,6 +209,8 @@ class FsHashStore {
|
||||
id,
|
||||
},
|
||||
});
|
||||
} catch {}
|
||||
} catch {
|
||||
/* empty */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
import { parse as getMimeTypeBuffer } from "file-type-mime";
|
||||
import type { Writable } from "stream";
|
||||
import Stream, { Readable } from "stream";
|
||||
import { Readable } from "stream";
|
||||
import { getMimeType as getMimeTypeStream } from "stream-mime-type";
|
||||
|
||||
export type ObjectReference = string;
|
||||
@@ -50,19 +50,19 @@ export abstract class ObjectBackend {
|
||||
abstract create(
|
||||
id: string,
|
||||
source: Source,
|
||||
metadata: ObjectMetadata
|
||||
metadata: ObjectMetadata,
|
||||
): Promise<ObjectReference | undefined>;
|
||||
abstract createWithWriteStream(
|
||||
id: string,
|
||||
metadata: ObjectMetadata
|
||||
metadata: ObjectMetadata,
|
||||
): Promise<Writable | undefined>;
|
||||
abstract delete(id: ObjectReference): Promise<boolean>;
|
||||
abstract fetchMetadata(
|
||||
id: ObjectReference
|
||||
id: ObjectReference,
|
||||
): Promise<ObjectMetadata | undefined>;
|
||||
abstract writeMetadata(
|
||||
id: ObjectReference,
|
||||
metadata: ObjectMetadata
|
||||
metadata: ObjectMetadata,
|
||||
): Promise<boolean>;
|
||||
abstract fetchHash(id: ObjectReference): Promise<string | undefined>;
|
||||
}
|
||||
@@ -96,7 +96,7 @@ export class ObjectHandler {
|
||||
id: string,
|
||||
sourceFetcher: () => Promise<Source>,
|
||||
metadata: { [key: string]: string },
|
||||
permissions: Array<string>
|
||||
permissions: Array<string>,
|
||||
) {
|
||||
const { source, mime } = await this.fetchMimeType(await sourceFetcher());
|
||||
if (!mime)
|
||||
@@ -112,7 +112,7 @@ export class ObjectHandler {
|
||||
async createWithStream(
|
||||
id: string,
|
||||
metadata: { [key: string]: string },
|
||||
permissions: Array<string>
|
||||
permissions: Array<string>,
|
||||
) {
|
||||
return this.backend.createWithWriteStream(id, {
|
||||
permissions,
|
||||
@@ -194,7 +194,7 @@ export class ObjectHandler {
|
||||
async writeWithPermissions(
|
||||
id: ObjectReference,
|
||||
sourceFetcher: () => Promise<Source>,
|
||||
userId?: string
|
||||
userId?: string,
|
||||
) {
|
||||
const metadata = await this.backend.fetchMetadata(id);
|
||||
if (!metadata) return false;
|
||||
|
||||
Reference in New Issue
Block a user