Logger
This commit is contained in:
parent
0e5c664250
commit
af2c334e66
|
@ -30,3 +30,92 @@ export async function getAPIKeyInformation(key: string): Promise<
|
||||||
_response: response
|
_response: response
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Skyblock profiles by player
|
||||||
|
* @param key API key
|
||||||
|
* @param player The player's UUID
|
||||||
|
* @returns A response with the player's profiles
|
||||||
|
*/
|
||||||
|
export async function getProfilesByPlayer(
|
||||||
|
key: string,
|
||||||
|
player: string
|
||||||
|
): Promise<
|
||||||
|
HypixelResponse<{
|
||||||
|
profiles?: {
|
||||||
|
profile_id: string;
|
||||||
|
members: any;
|
||||||
|
community_upgrades: any | null;
|
||||||
|
cute_name: string;
|
||||||
|
banking: any | null;
|
||||||
|
game_mode: string | null;
|
||||||
|
}[];
|
||||||
|
}>
|
||||||
|
> {
|
||||||
|
let response = await request(
|
||||||
|
`/skyblock/profiles?uuid=${player}`,
|
||||||
|
authorize(key)
|
||||||
|
);
|
||||||
|
return {
|
||||||
|
...(await response.json()),
|
||||||
|
_response: response
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Skyblock profile by its UUID
|
||||||
|
* @param key API key
|
||||||
|
* @param profile The profile's UUID
|
||||||
|
* @returns A response with the profile data
|
||||||
|
*/
|
||||||
|
export async function getProfileByUUID(
|
||||||
|
key: string,
|
||||||
|
profile: string
|
||||||
|
): Promise<
|
||||||
|
HypixelResponse<{
|
||||||
|
profile?: {
|
||||||
|
profile_id: string;
|
||||||
|
members: any;
|
||||||
|
community_upgrades: any | null;
|
||||||
|
cute_name: string;
|
||||||
|
banking: any | null;
|
||||||
|
game_mode: string | null;
|
||||||
|
};
|
||||||
|
}>
|
||||||
|
> {
|
||||||
|
let response = await request(
|
||||||
|
`/skyblock/profile?profile=${profile}`,
|
||||||
|
authorize(key)
|
||||||
|
);
|
||||||
|
return {
|
||||||
|
...(await response.json()),
|
||||||
|
_response: response
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a player's current online status
|
||||||
|
* @param key API key
|
||||||
|
* @param player Player to get status of
|
||||||
|
* @returns A response with player status data
|
||||||
|
*/
|
||||||
|
export async function getOnlineStatus(
|
||||||
|
key: string,
|
||||||
|
player: string
|
||||||
|
): Promise<
|
||||||
|
HypixelResponse<{
|
||||||
|
uuid?: string;
|
||||||
|
session?: {
|
||||||
|
online: boolean;
|
||||||
|
gameType: string;
|
||||||
|
mode: string;
|
||||||
|
map: string;
|
||||||
|
};
|
||||||
|
}>
|
||||||
|
> {
|
||||||
|
let response = await request(`/status?uuid=${player}`, authorize(key));
|
||||||
|
return {
|
||||||
|
...(await response.json()),
|
||||||
|
_response: response
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
export enum Permissions {
|
||||||
|
ALL = "*"
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check permissions
|
||||||
|
* @param required The permission required
|
||||||
|
* @param has The permissions to check against
|
||||||
|
* @returns Whether the required permissions are fulfilled
|
||||||
|
*/
|
||||||
|
export function checkPermissions(required: string[], has: string[]): boolean {
|
||||||
|
if (has.includes("*")) return true;
|
||||||
|
|
||||||
|
return !required.some(req => {
|
||||||
|
if (!has.includes(req)) return true;
|
||||||
|
});
|
||||||
|
}
|
|
@ -1,5 +1,3 @@
|
||||||
import { join } from "path";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a fetch function
|
* Get a fetch function
|
||||||
* @returns A fetch function
|
* @returns A fetch function
|
||||||
|
@ -11,6 +9,12 @@ export function getFetch(): typeof fetch {
|
||||||
return fetch;
|
return fetch;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a fetch-like function with defaults
|
||||||
|
* @param baseURL Base URL of all requests
|
||||||
|
* @param defaultInit Default RequestInit options
|
||||||
|
* @returns A fetch-like function
|
||||||
|
*/
|
||||||
export function requestWithDefaults(
|
export function requestWithDefaults(
|
||||||
baseURL: string,
|
baseURL: string,
|
||||||
defaultInit?: RequestInit
|
defaultInit?: RequestInit
|
||||||
|
@ -20,7 +24,7 @@ export function requestWithDefaults(
|
||||||
overrideInit?: RequestInit
|
overrideInit?: RequestInit
|
||||||
): Promise<Response> {
|
): Promise<Response> {
|
||||||
let response = await getFetch()(
|
let response = await getFetch()(
|
||||||
join(baseURL, endpoint),
|
new URL(endpoint, baseURL).href,
|
||||||
defaultInit ? deepMerge(defaultInit, overrideInit) : overrideInit
|
defaultInit ? deepMerge(defaultInit, overrideInit) : overrideInit
|
||||||
);
|
);
|
||||||
if (response.ok) {
|
if (response.ok) {
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
import { getOnlineStatus, getProfileByUUID } from "./lib/hypixel";
|
||||||
|
|
||||||
|
export async function log(key: string, profile: string) {
|
||||||
|
let r = await getProfileByUUID(key, profile);
|
||||||
|
if (!r.success || !r.profile) throw new Error("No success from Hypixel");
|
||||||
|
|
||||||
|
let d = r.profile;
|
||||||
|
for (const member in d.members) {
|
||||||
|
let onlineStatus = await getOnlineStatus(key, member);
|
||||||
|
if (onlineStatus.success && onlineStatus.session) {
|
||||||
|
d.members[member].online_status = onlineStatus.session;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return d;
|
||||||
|
}
|
|
@ -3,8 +3,88 @@ import polka from "polka";
|
||||||
import compression from "compression";
|
import compression from "compression";
|
||||||
import * as sapper from "@sapper/server";
|
import * as sapper from "@sapper/server";
|
||||||
|
|
||||||
const { PORT, NODE_ENV } = process.env;
|
import arangojs, { Database, aql } from "arangojs";
|
||||||
|
import { hash } from "bcrypt";
|
||||||
|
import { log } from "./logger";
|
||||||
|
|
||||||
|
const { PORT, NODE_ENV, DB_USERNAME, DB_PASSWORD, DB_URL, DB_NAME, API_KEY } =
|
||||||
|
process.env;
|
||||||
const dev = NODE_ENV === "development";
|
const dev = NODE_ENV === "development";
|
||||||
|
const db = arangojs({
|
||||||
|
auth: {
|
||||||
|
username: DB_USERNAME || "root",
|
||||||
|
password: DB_PASSWORD
|
||||||
|
},
|
||||||
|
url: DB_URL || "http://127.0.0.1:8529",
|
||||||
|
databaseName: DB_NAME || "sbdatatracker"
|
||||||
|
});
|
||||||
|
const saltRounds = 10;
|
||||||
|
const delay = 3 * 60 * 1000;
|
||||||
|
|
||||||
|
const intervalFunc = async (db: Database) => {
|
||||||
|
const cnf = db.collection("config");
|
||||||
|
const users = db.collection("users");
|
||||||
|
if (!(await cnf.exists())) {
|
||||||
|
await cnf.create();
|
||||||
|
}
|
||||||
|
if (!(await users.exists())) {
|
||||||
|
await users.create();
|
||||||
|
await users.save({
|
||||||
|
username: DB_USERNAME,
|
||||||
|
password: await hash(DB_PASSWORD || "SBDataTracker", saltRounds),
|
||||||
|
forceChangePassword: true,
|
||||||
|
permissions: ["*"]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const cursor = await db.query(
|
||||||
|
aql`
|
||||||
|
FOR doc IN ${cnf}
|
||||||
|
FILTER doc.type == "tracker"
|
||||||
|
RETURN doc
|
||||||
|
`,
|
||||||
|
{
|
||||||
|
count: true
|
||||||
|
}
|
||||||
|
);
|
||||||
|
/*
|
||||||
|
Instead of running a loop on all trackers at once,
|
||||||
|
they are spread out evenly across the delay which
|
||||||
|
lowers the chance of exceeding the Hypixel rate-limit
|
||||||
|
when there are a lot of trackers.
|
||||||
|
|
||||||
|
TODO : Add a hard-stop if the rate-limit is about
|
||||||
|
to be exceeded.
|
||||||
|
*/
|
||||||
|
if (cursor.hasNext) {
|
||||||
|
let counter = 0;
|
||||||
|
let interval: NodeJS.Timeout;
|
||||||
|
const iterate = async () => {
|
||||||
|
if (++counter >= (cursor.count as number)) clearInterval(interval);
|
||||||
|
|
||||||
|
const { _key, profile } = await cursor.next();
|
||||||
|
if (profile) {
|
||||||
|
const col = db.collection(`c${profile}`);
|
||||||
|
if (!(await col.exists())) col.create();
|
||||||
|
|
||||||
|
await col.save(await log(API_KEY || "", profile));
|
||||||
|
} else {
|
||||||
|
console.warn(
|
||||||
|
`Configuration entry '${_key}' with type 'tracker' has no "profile" value`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if ((cursor.count as number) > 1)
|
||||||
|
interval = setInterval(
|
||||||
|
iterate,
|
||||||
|
delay / ((cursor.count as number) - 1)
|
||||||
|
);
|
||||||
|
setTimeout(iterate);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
setInterval(intervalFunc, delay, db);
|
||||||
|
setTimeout(intervalFunc, 0, db);
|
||||||
|
|
||||||
polka({
|
polka({
|
||||||
onError: err => {
|
onError: err => {
|
||||||
|
|
Loading…
Reference in New Issue