diff --git a/src/cachetimes.js b/src/cachetimes.js new file mode 100644 index 0000000000..7c2da39780 --- /dev/null +++ b/src/cachetimes.js @@ -0,0 +1,47 @@ +import credentials from "./credentials.js"; + +/** + * Check if a resource is expired based on the cache time + * @param {number} unixMs Unix timestamp in milliseconds + * @param {number} cacheTime The cache time in seconds + * @returns {boolean} Whether the cache is expired + */ +export function isCacheExpired(unixMs, cacheTime) { + return Date.now() - unixMs > cacheTime * 1000; +} + +/** + * Check if a profile cache is expired based on the configured cache time + * @param {number} unixMs Unix timestamp in milliseconds + * @returns {boolean} Whether the cache is expired + */ +export function isProfileCacheExpired(unixMs) { + return isCacheExpired(unixMs, credentials.cacheSeconds.profiles); +} + +/** + * Check if a museum cache is expired based on the configured cache time + * @param {number} unixMs Unix timestamp in milliseconds + * @returns {boolean} Whether the cache is expired + */ +export function isMuseumCacheExpired(unixMs) { + return isCacheExpired(unixMs, credentials.cacheSeconds.museum); +} + +/** + * Check if a guild cache is expired based on the configured cache time + * @param {number} unixMs Unix timestamp in milliseconds + * @returns {boolean} Whether the cache is expired + */ +export function isGuildCacheExpired(unixMs) { + return isCacheExpired(unixMs, credentials.cacheSeconds.guild); +} + +/** + * Check if a bingo profile cache is expired based on the configured cache time + * @param {number} unixMs Unix timestamp in milliseconds + * @returns {boolean} Whether the cache is expired + */ +export function isBingoProfileCacheExpired(unixMs) { + return isCacheExpired(unixMs, credentials.cacheSeconds.bingoProfiles); +} diff --git a/src/credentials.js b/src/credentials.js index 91eaec0a3c..41a3be2151 100644 --- a/src/credentials.js +++ b/src/credentials.js @@ -19,6 +19,12 @@ const defaultCredentials = { get session_secret() { return randomBytes(32).toString("hex"); }, + cacheSeconds: { + profiles: 60 * 5, // 5 minutes + bingoProfile: 60 * 5, // 5 minutes + museum: 60 * 30, // 30 minutes + guild: 60 * 60 * 24, // 24 hours + }, }; /** @@ -50,6 +56,15 @@ for (const key in defaultCredentials) { CREDENTIALS[key] = defaultCredentials[key]; hasBeenModified = true; } + + if (typeof defaultCredentials[key] === "object") { + for (const subKey in defaultCredentials[key]) { + if (CREDENTIALS[key][subKey] == undefined) { + CREDENTIALS[key][subKey] = defaultCredentials[key][subKey]; + hasBeenModified = true; + } + } + } } if (hasBeenModified) { @@ -72,4 +87,20 @@ if (process.env.DISCORD_WEBHOOK) { CREDENTIALS.discord_webhook = process.env.DISCORD_WEBHOOK; } +if (process.env.CACHE_PROFILES && isFinite(parseInt(process.env.CACHE_PROFILES))) { + CREDENTIALS.cacheSeconds.profiles = parseInt(process.env.CACHE_PROFILES); +} + +if (process.env.CACHE_MUSEUM && isFinite(parseInt(process.env.CACHE_MUSEUM))) { + CREDENTIALS.cacheSeconds.museum = parseInt(process.env.CACHE_MUSEUM); +} + +if (process.env.CACHE_GUILD && isFinite(parseInt(process.env.CACHE_GUILD))) { + CREDENTIALS.cacheSeconds.guild = parseInt(process.env.CACHE_GUILD); +} + +if (process.env.CACHE_BINGO_PROFILE && isFinite(parseInt(process.env.CACHE_BINGO_PROFILE))) { + CREDENTIALS.cacheSeconds.bingoProfile = parseInt(process.env.CACHE_BINGO_PROFILE); +} + export default CREDENTIALS; diff --git a/src/lib.js b/src/lib.js index e429adb89f..61d0680c8c 100644 --- a/src/lib.js +++ b/src/lib.js @@ -4,6 +4,7 @@ import axios from "axios"; import * as constants from "./constants.js"; import credentials from "./credentials.js"; +import * as cacheTimes from "./cachetimes.js"; import * as helper from "./helper.js"; import * as stats from "./stats.js"; import { SkyCryptError } from "./constants/error.js"; @@ -255,8 +256,6 @@ export async function getProfile( let profileObject = await db.collection("profileStore").findOne({ uuid: sanitize(paramPlayer) }); - let lastCachedSave = 0; - if (profileObject) { const profileData = db .collection("profileCache") @@ -276,13 +275,9 @@ export async function getProfile( let response = null; - lastCachedSave = Math.max(profileObject.last_update, Date.now() || 0); + const lastCachedSave = profileObject.last_update; - if ( - !options.cacheOnly && - ((Date.now() - lastCachedSave > 190 * 1000 && Date.now() - lastCachedSave < 300 * 1000) || - Date.now() - profileObject.last_update >= 300 * 1000) - ) { + if (!options.cacheOnly && (cacheTimes.isProfileCacheExpired(lastCachedSave) || lastCachedSave === 0)) { try { profileObject.last_update = Date.now(); response = await retry( @@ -504,12 +499,7 @@ export async function getBingoProfile( }; const lastCachedSave = profileData.last_save ?? 0; - if ( - (!options.cacheOnly && - ((Date.now() - lastCachedSave > 190 * 1000 && Date.now() - lastCachedSave < 300 * 1000) || - Date.now() - profileData.last_save >= 300 * 1000)) || - lastCachedSave === 0 - ) { + if (!options.cacheOnly && (cacheTimes.isBingoProfileCacheExpired(lastCachedSave) || lastCachedSave === 0)) { try { const response = await retry( async () => { @@ -565,7 +555,7 @@ export async function getMuseum( } let museumData = await db.collection("museumCache").findOne({ profile_id: profileID }); - if (!options.cacheOnly && (museumData == undefined || museumData.last_save < Date.now() - 1000 * 60 * 30)) { + if (!options.cacheOnly && (museumData == undefined || cacheTimes.isMuseumCacheExpired(museumData.last_save))) { try { const params = { key: credentials.hypixel_api_key, @@ -616,7 +606,7 @@ export async function getGuild( const timeStarted = Date.now(); let output = await db.collection("guildCache").findOne({ uuid: paramPlayer }); - if (!options.cacheOnly && (!output || output.last_updated < Date.now() - 1000 * 60 * 60 * 24)) { + if (!options.cacheOnly && (!output || cacheTimes.isGuildCacheExpired(output.last_updated))) { try { const params = { key: credentials.hypixel_api_key, diff --git a/views/stats.ejs b/views/stats.ejs index 1877118fb3..bd02748937 100644 --- a/views/stats.ejs +++ b/views/stats.ejs @@ -119,7 +119,7 @@ function itemIcon(item, classes) { %> icon-<%= item.id %>_<%= item.Damage %> "> -<% } +<% } function jerriefy(rank) { if (extra.isFoolsDay) { @@ -380,7 +380,7 @@ const metaDescription = getMetaDescription() <% for (let error in calculated.errors) { %> <% console.log(calculated.errors[error]) %> <%- calculated.errors[error] %> - +
<% } %>
@@ -438,7 +438,7 @@ const metaDescription = getMetaDescription() <% for (let profile_id in calculated.profiles) { const _profile = calculated.profiles[profile_id]; %>
  • - + <%= _profile.cute_name %> <% if (_profile.game_mode == 'ironman') { %> @@ -468,40 +468,43 @@ const metaDescription = getMetaDescription() Plancke - + + + Elite +
    - + <% if ('social' in calculated && Object.keys(calculated.social).length > 0) { %> - <% if ('DISCORD' in calculated.social) { %> - + <% if ('DISCORD' in calculated.social) { %> + <% } %> - <% if ('TWITTER' in calculated.social) { %> - + <% if ('TWITTER' in calculated.social) { %> + <% } %> - <% if ('YOUTUBE' in calculated.social) { %> - + <% if ('YOUTUBE' in calculated.social) { %> + <% } %> - <% if ('INSTAGRAM' in calculated.social) { %> - + <% if ('INSTAGRAM' in calculated.social) { %> + <% } %> - <% if ('TWITCH' in calculated.social) { %> - + <% if ('TWITCH' in calculated.social) { %> + <% } %> - <% if ('HYPIXEL' in calculated.social) { %> - + <% if ('HYPIXEL' in calculated.social) { %> + <% } %> @@ -572,8 +575,8 @@ const metaDescription = getMetaDescription() <% } %> <% if (calculated.profile.game_mode == 'ironman') { %> - <% if (notAvailable.length > 0) { %> -
    + <% if (notAvailable.length > 0) { %> +
    <% } %> This is an Ironman profile. The player cannot use the auction house, bazaar, or trade with other players. @@ -581,18 +584,18 @@ const metaDescription = getMetaDescription() <% if (calculated.profile.game_mode == 'bingo') { %> - <% if (notAvailable.length > 0) { %> -
    + <% if (notAvailable.length > 0) { %> +
    <% } %> - + This is a Bingo profile. The player cannot spend gems, use the auction house, bazaar or trade with other players. <% } %> <% if (calculated.profile.game_mode == 'island') { %> - <% if (notAvailable.length > 0) { %> + <% if (notAvailable.length > 0) { %>
    <% } %> - + This is a Stranded profile. The player cannot leave their skyblock island or trade with other players. <% } %>
    @@ -630,14 +633,14 @@ const metaDescription = getMetaDescription() <%- include('./sections/stats/items/inventory.ejs', { getRarityUpgradeClass, rarityOrder, isEnchanted }); %> <% } %> - + <%- include('./sections/stats/skills.ejs', { getRarityUpgradeClass, rarityOrder, isEnchanted }); %> <% if (calculated.dungeons !== undefined) { %> <%- include('./sections/stats/dungeons.ejs', { skillItems }); %> - <% } %> + <% } %> <% if (calculated.slayer !== undefined) { %> @@ -645,7 +648,7 @@ const metaDescription = getMetaDescription() <% } %> - <% if (calculated.minions.unlockedTiers > 0) { %> + <% if (calculated.minions.unlockedTiers > 0) { %> <%- include('./sections/stats/minions.ejs', { skillItems }); %> <% } %> @@ -659,7 +662,7 @@ const metaDescription = getMetaDescription() <% } %> - <% if (calculated.crimson_isle !== undefined) { %> + <% if (calculated.crimson_isle !== undefined) { %> <%- include('./sections/stats/crimson_isle.ejs', {}); %> <% } %> @@ -672,8 +675,8 @@ const metaDescription = getMetaDescription() <% if (calculated.profile.game_mode === "bingo" && calculated.bingo !== undefined) { %> <%- include('./sections/stats/bingo.ejs', {}); %> <% } %> - - + + <% if (calculated.misc !== undefined) { %> <%- include('./sections/stats/misc.ejs', { rarityOrder }); %> <% } %>