biketag
Version:
The Javascript client API for BikeTag Games
1,115 lines • 173 kB
JavaScript
(function(global, factory) {
typeof exports === "object" && typeof module !== "undefined" ? factory(exports, require("form-data"), require("imgur"), require("@sanity/client"), require("axios"), require("events"), require("axios-cache-adapter"), require("lodash"), require("tinycache")) : typeof define === "function" && define.amd ? define(["exports", "form-data", "imgur", "@sanity/client", "axios", "events", "axios-cache-adapter", "lodash", "tinycache"], factory) : (global = typeof globalThis !== "undefined" ? globalThis : global || self, factory(global.BikeTagClient = {}, null, global.ImgurClient, global.sanityClient, global.axios, global.events, global.axiosCacheAdapter, global.lodash, global.TinyCache));
})(this, function(exports2, FormData, imgur, sanityClient, axios, events, axiosCacheAdapter, lodash, TinyCache) {
"use strict";
var AvailableApis = /* @__PURE__ */ ((AvailableApis2) => {
AvailableApis2["biketag"] = "biketag";
AvailableApis2["imgur"] = "imgur";
AvailableApis2["sanity"] = "sanity";
return AvailableApis2;
})(AvailableApis || {});
var DataTypes = /* @__PURE__ */ ((DataTypes2) => {
DataTypes2[DataTypes2["ambassador"] = 0] = "ambassador";
DataTypes2[DataTypes2["game"] = 1] = "game";
DataTypes2[DataTypes2["player"] = 2] = "player";
DataTypes2[DataTypes2["setting"] = 3] = "setting";
DataTypes2[DataTypes2["tag"] = 4] = "tag";
DataTypes2[DataTypes2["queue"] = 5] = "queue";
DataTypes2[DataTypes2["stat"] = 6] = "stat";
DataTypes2[DataTypes2["achievement"] = 7] = "achievement";
return DataTypes2;
})(DataTypes || {});
var GameSettingsKeys = /* @__PURE__ */ ((GameSettingsKeys2) => {
GameSettingsKeys2["achievementsEnabled"] = "achievements::enabled";
return GameSettingsKeys2;
})(GameSettingsKeys || {});
var Errors = /* @__PURE__ */ ((Errors2) => {
Errors2["NotImplemented"] = "method not implemented for adapter: ";
return Errors2;
})(Errors || {});
var HttpStatusCode = /* @__PURE__ */ ((HttpStatusCode2) => {
HttpStatusCode2[HttpStatusCode2["Continue"] = 100] = "Continue";
HttpStatusCode2[HttpStatusCode2["SwitchingProtocols"] = 101] = "SwitchingProtocols";
HttpStatusCode2[HttpStatusCode2["Processing"] = 102] = "Processing";
HttpStatusCode2[HttpStatusCode2["Ok"] = 200] = "Ok";
HttpStatusCode2[HttpStatusCode2["Created"] = 201] = "Created";
HttpStatusCode2[HttpStatusCode2["Accepted"] = 202] = "Accepted";
HttpStatusCode2[HttpStatusCode2["NonAuthoritativeInformation"] = 203] = "NonAuthoritativeInformation";
HttpStatusCode2[HttpStatusCode2["NoContent"] = 204] = "NoContent";
HttpStatusCode2[HttpStatusCode2["ResetContent"] = 205] = "ResetContent";
HttpStatusCode2[HttpStatusCode2["PartialContent"] = 206] = "PartialContent";
HttpStatusCode2[HttpStatusCode2["MultiStatus"] = 207] = "MultiStatus";
HttpStatusCode2[HttpStatusCode2["AlreadyReported"] = 208] = "AlreadyReported";
HttpStatusCode2[HttpStatusCode2["ImUsed"] = 226] = "ImUsed";
HttpStatusCode2[HttpStatusCode2["MultipleChoices"] = 300] = "MultipleChoices";
HttpStatusCode2[HttpStatusCode2["MovedPermanently"] = 301] = "MovedPermanently";
HttpStatusCode2[HttpStatusCode2["Found"] = 302] = "Found";
HttpStatusCode2[HttpStatusCode2["SeeOther"] = 303] = "SeeOther";
HttpStatusCode2[HttpStatusCode2["NotModified"] = 304] = "NotModified";
HttpStatusCode2[HttpStatusCode2["UseProxy"] = 305] = "UseProxy";
HttpStatusCode2[HttpStatusCode2["SwitchProxy"] = 306] = "SwitchProxy";
HttpStatusCode2[HttpStatusCode2["TemporaryRedirect"] = 307] = "TemporaryRedirect";
HttpStatusCode2[HttpStatusCode2["PermanentRedirect"] = 308] = "PermanentRedirect";
HttpStatusCode2[HttpStatusCode2["BadRequest"] = 400] = "BadRequest";
HttpStatusCode2[HttpStatusCode2["Unauthorized"] = 401] = "Unauthorized";
HttpStatusCode2[HttpStatusCode2["PaymentRequired"] = 402] = "PaymentRequired";
HttpStatusCode2[HttpStatusCode2["Forbidden"] = 403] = "Forbidden";
HttpStatusCode2[HttpStatusCode2["NotFound"] = 404] = "NotFound";
HttpStatusCode2[HttpStatusCode2["MethodNotAllowed"] = 405] = "MethodNotAllowed";
HttpStatusCode2[HttpStatusCode2["NotAcceptable"] = 406] = "NotAcceptable";
HttpStatusCode2[HttpStatusCode2["ProxyAuthenticationRequired"] = 407] = "ProxyAuthenticationRequired";
HttpStatusCode2[HttpStatusCode2["RequestTimeout"] = 408] = "RequestTimeout";
HttpStatusCode2[HttpStatusCode2["Conflict"] = 409] = "Conflict";
HttpStatusCode2[HttpStatusCode2["Gone"] = 410] = "Gone";
HttpStatusCode2[HttpStatusCode2["LengthRequired"] = 411] = "LengthRequired";
HttpStatusCode2[HttpStatusCode2["PreconditionFailed"] = 412] = "PreconditionFailed";
HttpStatusCode2[HttpStatusCode2["PayloadTooLarge"] = 413] = "PayloadTooLarge";
HttpStatusCode2[HttpStatusCode2["UriTooLong"] = 414] = "UriTooLong";
HttpStatusCode2[HttpStatusCode2["UnsupportedMediaType"] = 415] = "UnsupportedMediaType";
HttpStatusCode2[HttpStatusCode2["RangeNotSatisfiable"] = 416] = "RangeNotSatisfiable";
HttpStatusCode2[HttpStatusCode2["ExpectationFailed"] = 417] = "ExpectationFailed";
HttpStatusCode2[HttpStatusCode2["IAmATeapot"] = 418] = "IAmATeapot";
HttpStatusCode2[HttpStatusCode2["MisdirectedRequest"] = 421] = "MisdirectedRequest";
HttpStatusCode2[HttpStatusCode2["UnprocessableEntity"] = 422] = "UnprocessableEntity";
HttpStatusCode2[HttpStatusCode2["Locked"] = 423] = "Locked";
HttpStatusCode2[HttpStatusCode2["FailedDependency"] = 424] = "FailedDependency";
HttpStatusCode2[HttpStatusCode2["UpgradeRequired"] = 426] = "UpgradeRequired";
HttpStatusCode2[HttpStatusCode2["PreconditionRequired"] = 428] = "PreconditionRequired";
HttpStatusCode2[HttpStatusCode2["TooManyRequests"] = 429] = "TooManyRequests";
HttpStatusCode2[HttpStatusCode2["RequestHeaderFieldsTooLarge"] = 431] = "RequestHeaderFieldsTooLarge";
HttpStatusCode2[HttpStatusCode2["UnavailableForLegalReasons"] = 451] = "UnavailableForLegalReasons";
HttpStatusCode2[HttpStatusCode2["InternalServerError"] = 500] = "InternalServerError";
HttpStatusCode2[HttpStatusCode2["NotImplemented"] = 501] = "NotImplemented";
HttpStatusCode2[HttpStatusCode2["BadGateway"] = 502] = "BadGateway";
HttpStatusCode2[HttpStatusCode2["ServiceUnavailable"] = 503] = "ServiceUnavailable";
HttpStatusCode2[HttpStatusCode2["GatewayTimeout"] = 504] = "GatewayTimeout";
HttpStatusCode2[HttpStatusCode2["HttpVersionNotSupported"] = 505] = "HttpVersionNotSupported";
HttpStatusCode2[HttpStatusCode2["VariantAlsoNegotiates"] = 506] = "VariantAlsoNegotiates";
HttpStatusCode2[HttpStatusCode2["InsufficientStorage"] = 507] = "InsufficientStorage";
HttpStatusCode2[HttpStatusCode2["LoopDetected"] = 508] = "LoopDetected";
HttpStatusCode2[HttpStatusCode2["NotExtended"] = 510] = "NotExtended";
HttpStatusCode2[HttpStatusCode2["NetworkAuthenticationRequired"] = 511] = "NetworkAuthenticationRequired";
return HttpStatusCode2;
})(HttpStatusCode || {});
const cacheKeys = {
sanityUrlText: `sanity::`,
imageHashText: `hash::`,
albumHash: `album::`,
hintText: `hint::`,
timeText: `time::`,
playerText: `player::`,
playerData: `playerData::`,
playerIdText: `playerId::`,
gameIdText: `gameId::`,
gameSlugText: `slug::`,
gameText: `game::`,
locationText: `location::`,
discussionText: `discussion::`,
mentionText: `mention::`,
tagNumberText: `tag::`,
imagesText: `images::`,
imageUrlText: `imageUrl::`,
gpsStringText: `gpsString::`,
slugText: `slug::`
};
const createTagObject = (tagData = {}, foundTagData = {}) => {
return {
_id: tagData._id,
_type: tagData._type,
/// Common Tag Data
game: tagData.game ?? "",
slug: tagData.slug ?? "",
name: tagData.name ?? "",
playerId: tagData.playerId ?? "",
tagnumber: tagData.tagnumber ?? 0,
/// Mystery Tag Data
mysteryPlayer: tagData.mysteryPlayer ?? "",
mysteryImage: tagData.mysteryImage,
mysteryImageUrl: tagData.mysteryImageUrl ?? "",
mysteryTime: tagData.mysteryTime ?? 0,
hint: tagData.hint ?? "",
discussionUrl: tagData.discussionUrl ?? "",
mentionUrl: tagData.mentionUrl ?? "",
/// Found Tag Data
foundPlayer: foundTagData.foundPlayer ?? tagData.foundPlayer ?? "",
foundImage: foundTagData.foundImage ?? tagData.foundImage,
foundImageUrl: foundTagData.foundImageUrl ?? tagData.foundImageUrl ?? "",
foundTime: foundTagData.foundTime ?? tagData.foundTime ?? 0,
foundLocation: foundTagData.foundLocation ?? tagData.foundLocation ?? "",
confirmedBoundary: foundTagData.confirmedBoundary ?? tagData.confirmedBoundary ?? false,
gps: foundTagData.gps ?? tagData.gps ?? ""
};
};
const tagDataFields = Object.keys(createTagObject());
const tagDataReferenceFields = ["game", "player"];
const tagDataAssetFields = ["foundImage", "mysteryImage"];
const tagDataObjectFields = {
foundImage: "asset->_ref",
mysteryImage: "asset->_ref"
};
const createGameObject = (gameData = {}) => {
return {
_id: gameData._id,
_type: gameData._type,
name: gameData.name ?? gameData.slug ?? "",
ambassadors: gameData.ambassadors ?? [],
settings: gameData.settings ?? [],
boundary: gameData.boundary ?? {},
mainhash: gameData.mainhash ?? "",
archivehash: gameData.archivehash ?? "",
queuehash: gameData.queuehash ?? "",
logo: gameData.logo,
region: gameData.region ?? { name: gameData.name },
slug: gameData.slug ?? gameData.name ?? ""
};
};
const gameDataReferenceFields = ["region", "settings"];
const gameDataArrayFields = ["ambassadors", "tags", "settings"];
const gameDataCustomFields = {
settings: "[]->{key,value}",
region: "name,description,zipcode,radius,tz"
};
const gameDataFields = Object.keys(createGameObject());
const gameDataObjectFields = {
logo: "asset->_ref"
};
const createPlayerObject = (playerData = {}) => {
return {
_id: playerData._id,
_type: playerData._type,
achievements: playerData.achievements ?? [],
bicon: playerData.bicon ?? "",
games: playerData.games ?? (playerData.game ? [playerData.game] : []),
name: playerData.name ?? "",
slug: playerData.slug ?? "",
tags: playerData.tags ?? []
};
};
const playerDataFields = Object.keys(createPlayerObject());
const playerDataReferenceFields = ["games", "tags", "achievements"];
const playerDataArrayFields = ["games", "tags", "achievements"];
const playerDataAssetFields = [];
const playerDataObjectFields = {};
const createAmbassadorObject = (ambassadorData = {}) => {
return {
id: ambassadorData._id ?? ambassadorData.id ?? "",
address1: ambassadorData.address1 ?? "",
address2: ambassadorData.address2 ?? "",
city: ambassadorData.city ?? "",
country: ambassadorData.country ?? "",
email: ambassadorData.email ?? "",
name: ambassadorData.name ?? "",
phone: ambassadorData.phone ?? "",
player: ambassadorData.player ?? "",
slug: ambassadorData.slug ?? "",
zipcode: ambassadorData.zipcode ?? ""
};
};
const ambassadorDataFields = Object.keys(createAmbassadorObject());
const ambassadorDataReferenceFields = ["player"];
const createSettingObject = (settingData = {}) => {
return {
slug: settingData.slug ?? "",
description: settingData.description ?? "",
name: settingData.name ?? "",
key: settingData.key ?? "",
value: settingData.value ?? ""
};
};
const settingDataFields = Object.keys(createSettingObject());
const statDataReferenceFields = ["game"];
const statDataArrayFields = [];
const createStatObject = (statData = {}) => {
return {
description: statData.description ?? "",
game: statData.game ?? "",
name: statData.name ?? "",
key: statData.key ?? "",
value: statData.value ?? "",
updatedAt: statData._updatedAt ?? statData._updatedAt ?? /* @__PURE__ */ new Date()
};
};
const statDataFields = [...Object.keys(createStatObject()), "_updatedAt"];
const createAchievementObject = (achievementData = {}) => {
return {
slug: achievementData.slug ?? "",
description: achievementData.description ?? "",
name: achievementData.name ?? "",
key: achievementData.key ?? "",
value: achievementData.value ?? "",
group: achievementData.group ?? ""
};
};
const achievementDataFields = Object.keys(createAchievementObject());
const putCacheIfExists = (key, value, cache) => {
if (cache) cache.put(key, value);
};
const getCacheIfExists = (key, cache) => {
if (cache) return cache.get(key);
return null;
};
const hasAccessToken = (arg) => {
return arg.accessToken !== void 0;
};
const hasClientKey = (arg) => {
return arg.clientKey !== void 0;
};
const constructTagNumberSlug = (number, game = "") => {
return `${game}-tag-${number}`;
};
const isImgurCredentials = (credentials) => {
return (credentials == null ? void 0 : credentials.clientId) !== void 0 || (credentials == null ? void 0 : credentials.clientSecret) !== void 0 || (credentials == null ? void 0 : credentials.clientId) !== void 0 && (credentials == null ? void 0 : credentials.hash) !== void 0;
};
const isImgurApiReady = (credentials) => {
if (!(credentials.clientId || credentials.hash)) {
return 0;
} else if (credentials.accessToken) {
return 3;
} else if (credentials.clientId && credentials.clientSecret) {
return 2;
}
return 1;
};
const isSanityCredentials = (credentials) => {
return (credentials == null ? void 0 : credentials.projectId) !== void 0;
};
const isSanityApiReady = (credentials) => {
if (credentials.projectId !== void 0 && credentials.dataset !== void 0 && credentials.apiVersion !== void 0) {
return credentials.token !== void 0 ? 3 : 1;
}
return 0;
};
const isBikeTagCredentials = (credentials) => {
return (credentials == null ? void 0 : credentials.game) !== void 0 || (credentials == null ? void 0 : credentials.clientToken) !== void 0 && (credentials == null ? void 0 : credentials.clientKey) !== void 0;
};
const isBikeTagApiReady = (credentials) => {
return credentials ? 1 : 0;
};
const createImgurCredentials = (credentials, defaults = {}) => {
var _a, _b, _c, _d, _e, _f, _g, _h, _i;
return {
hash: ((_a = credentials.hash) == null ? void 0 : _a.length) ? credentials.hash : defaults.hash,
queuehash: ((_b = credentials.queuehash) == null ? void 0 : _b.length) ? credentials.queuehash : defaults.queuehash,
archivehash: ((_c = credentials.archivehash) == null ? void 0 : _c.length) ? credentials.archivehash : defaults.archivehash,
clientId: ((_d = credentials.clientId) == null ? void 0 : _d.length) ? credentials.clientId : defaults.clientId,
clientSecret: ((_e = credentials.clientSecret) == null ? void 0 : _e.length) ? credentials.clientSecret : defaults.clientSecret,
accessToken: ((_f = credentials.accessToken) == null ? void 0 : _f.length) ? credentials.accessToken : defaults.accessToken,
refreshToken: ((_g = credentials.refreshToken) == null ? void 0 : _g.length) ? credentials.refreshToken : defaults.refreshToken,
rapidApiHost: ((_h = credentials.rapidApiHost) == null ? void 0 : _h.length) ? credentials.rapidApiHost : defaults.rapidApiHost,
rapidApiKey: ((_i = credentials.rapidApiKey) == null ? void 0 : _i.length) ? credentials.rapidApiKey : defaults.rapidApiKey
};
};
const assignImgurCredentials = (credentials, defaults = {}) => {
const imgurCredentials = isImgurCredentials(credentials) ? createImgurCredentials(credentials, defaults) : defaults;
return imgurCredentials;
};
const createSanityCredentials = (credentials, defaults = {}) => {
var _a, _b, _c, _d, _e, _f, _g;
return {
useCdn: ((_a = credentials.token) == null ? void 0 : _a.length) ? false : typeof credentials.useCdn !== "undefined" ? credentials.useCdn : typeof defaults.useCdn !== "undefined" ? defaults.useCdn : true,
projectId: ((_b = credentials.projectId) == null ? void 0 : _b.length) ? credentials.projectId : defaults.projectId,
dataset: ((_c = credentials.dataset) == null ? void 0 : _c.length) ? credentials.dataset : defaults.dataset ?? "development",
token: ((_d = credentials.token) == null ? void 0 : _d.length) ? credentials.token : defaults.token ?? "",
password: ((_e = credentials.password) == null ? void 0 : _e.length) ? credentials.password : defaults.password,
username: ((_f = credentials.username) == null ? void 0 : _f.length) ? credentials.username : defaults.username,
apiVersion: ((_g = credentials.apiVersion) == null ? void 0 : _g.length) ? credentials.apiVersion : defaults.apiVersion ?? "2021-10-21"
};
};
const assignSanityCredentials = (credentials, defaults) => {
const sanityCredentials = isSanityCredentials(
credentials
) ? createSanityCredentials(credentials, defaults) : defaults;
return sanityCredentials;
};
const createBikeTagCredentials = (credentials, defaults = {}) => {
var _a, _b, _c, _d, _e, _f;
return {
game: ((_a = credentials.game) == null ? void 0 : _a.length) ? credentials.game : defaults.game,
host: ((_b = credentials.host) == null ? void 0 : _b.length) ? credentials.host : defaults.host,
cached: typeof credentials.cached !== "undefined" ? credentials.cached : defaults.cached,
source: ((_c = credentials.source) == null ? void 0 : _c.length) ? credentials.source : defaults.source,
clientKey: ((_d = credentials.clientKey) == null ? void 0 : _d.length) ? credentials.clientKey : defaults.clientKey,
clientToken: ((_e = credentials.clientToken) == null ? void 0 : _e.length) ? credentials.clientToken : defaults.clientToken,
accessToken: ((_f = credentials.accessToken) == null ? void 0 : _f.length) ? credentials.accessToken : defaults.accessToken
};
};
const assignBikeTagCredentials = (credentials, defaults) => {
const biketagCredentials = isBikeTagCredentials(credentials) ? createBikeTagCredentials(credentials, defaults) : defaults;
return biketagCredentials;
};
const assignBikeTagConfiguration = (config, defaults) => {
const configuration = {};
const parsedConfig = {
biketag: assignBikeTagCredentials(
config,
defaults == null ? void 0 : defaults.biketag
),
sanity: assignSanityCredentials(
config,
defaults == null ? void 0 : defaults.sanity
),
imgur: assignImgurCredentials(
config,
defaults == null ? void 0 : defaults.imgur
)
};
configuration.biketag = config.biketag ? { ...parsedConfig.biketag, ...createBikeTagCredentials(config.biketag) } : parsedConfig.biketag;
configuration.sanity = config.sanity ? { ...parsedConfig.sanity, ...createSanityCredentials(config.sanity) } : parsedConfig.sanity;
configuration.imgur = config.imgur ? { ...parsedConfig.imgur, ...createImgurCredentials(config.imgur) } : parsedConfig.imgur;
return configuration;
};
const sortTags = (tags, sort = "new", limit = 0, time = "all") => {
let sorted = tags;
switch (sort) {
/// Leaderboard?
case "top":
sorted = tags.sort((a, b) => b.tagnumber - a.tagnumber);
break;
/// Queue
case "relevance":
sorted = tags.sort((a, b) => {
var _a, _b, _c, _d;
const aHasFoundImage = (_a = a == null ? void 0 : a.foundImageUrl) == null ? void 0 : _a.length;
const aHasMysteryImage = (_b = a == null ? void 0 : a.mysteryImageUrl) == null ? void 0 : _b.length;
const bHasFoundImage = (_c = b == null ? void 0 : b.foundImageUrl) == null ? void 0 : _c.length;
const bHasMysteryImage = (_d = b == null ? void 0 : b.mysteryImageUrl) == null ? void 0 : _d.length;
const aHasBothImages = aHasFoundImage && aHasMysteryImage;
const bHasBothImages = bHasFoundImage && bHasMysteryImage;
const bIsBeforeA = -1;
const aIsBeforeB = 1;
if (!aHasBothImages && !bHasBothImages) {
if (aHasFoundImage && bHasFoundImage) {
return (a == null ? void 0 : a.foundTime) - (b == null ? void 0 : b.foundTime);
} else if (aHasFoundImage) {
return aIsBeforeB;
} else if (bHasFoundImage) {
return aIsBeforeB;
}
} else if (aHasBothImages && bHasBothImages) {
const firstToComplete = (a == null ? void 0 : a.mysteryTime) - (b == null ? void 0 : b.mysteryTime);
return firstToComplete;
} else if (aHasBothImages && !bHasBothImages) {
return bIsBeforeA;
} else if (!aHasBothImages && bHasBothImages) {
return aIsBeforeB;
}
return 0;
});
break;
/// BikeTags
case "new":
sorted = tags.sort((a, b) => (b == null ? void 0 : b.tagnumber) - (a == null ? void 0 : a.tagnumber));
break;
default:
sorted = tags.sort((a, b) => (a == null ? void 0 : a.tagnumber) - (b == null ? void 0 : b.tagnumber));
break;
}
let timeConstraint = 0;
switch (time) {
case "hour":
timeConstraint = 60 * 60 * 1e3;
break;
case "day":
timeConstraint = 60 * 60 * 24 * 1e3;
break;
case "week":
timeConstraint = 60 * 60 * 24 * 7 * 1e3;
break;
}
if (timeConstraint) {
const afterDate = Date.now() - timeConstraint;
sorted = sorted.filter((t) => t.mysteryTime * 1e3 > afterDate);
}
return limit !== 0 ? sorted.slice(0, limit) : sorted;
};
const sortPlayers = (players, sort = "new", limit = 0) => {
let sorted = players;
switch (sort) {
case "top":
sorted = players.sort((a, b) => b.tags.length - a.tags.length);
break;
case "comments":
sorted = players.sort((a, b) => a.name.localeCompare(b.name));
break;
case "new":
sorted = players.reverse();
break;
}
return limit !== 0 ? sorted.slice(0, limit) : sorted;
};
const sortAmbassadors = (ambassadors, sort = "new", limit = 0) => {
const sorter = (a, b) => b.name.localeCompare(a.name);
let sorted = ambassadors;
switch (sort) {
case "top":
sorted = ambassadors.sort(sorter);
break;
case "new":
sorted = ambassadors.reverse();
break;
}
return limit !== 0 ? sorted.slice(0, limit) : sorted;
};
const sortSettings = (settings, sort = "new", limit = 0) => {
let sorted = settings;
switch (sort) {
case "comments":
sorted = settings.sort((a, b) => a.name.localeCompare(b.name));
break;
case "new":
sorted = settings.reverse();
break;
}
return limit !== 0 ? sorted.slice(0, limit) : sorted;
};
const sortStats = (stats, sort = "new", limit = 0) => {
let sorted = stats;
switch (sort) {
case "comments":
sorted = stats.sort((a, b) => a.name.localeCompare(b.name));
break;
case "new":
sorted = stats.reverse();
break;
}
return limit !== 0 ? sorted.slice(0, limit) : sorted;
};
const sortAchievements = (achievements, sort = "new", limit = 0) => {
let sorted = achievements;
switch (sort) {
case "comments":
sorted = achievements.sort((a, b) => a.name.localeCompare(b.name));
break;
case "new":
sorted = achievements.reverse();
break;
}
return limit !== 0 ? sorted.slice(0, limit) : sorted;
};
const getGameAlbumFromCache = async (gameAlbumHash, cache, fallback, useCache = true) => {
const cacheKey = `imgur::${cacheKeys.albumHash}${gameAlbumHash}`;
const existsInCache = getCacheIfExists(cacheKey, useCache ? cache : void 0);
if (existsInCache) {
return existsInCache;
}
if (fallback) {
const putIntoCache = await fallback();
putCacheIfExists(cacheKey, putIntoCache, cache);
return putIntoCache;
}
};
const getTagDate = (time) => new Date(time * 1e3);
const convertMiliseconds = (miliseconds, format) => {
const total_seconds = Math.floor(miliseconds / 1e3);
const total_minutes = Math.floor(total_seconds / 60);
const total_hours = Math.floor(total_minutes / 60);
const days = Math.floor(total_hours / 24);
const seconds = total_seconds % 60;
const minutes = total_minutes % 60;
const hours = total_hours % 24;
switch (format) {
case "s":
return total_seconds;
case "m":
return total_minutes;
case "h":
return total_hours;
case "d":
return days;
default:
return { d: days, h: hours, m: minutes, s: seconds };
}
};
const getLongestTimeBetweenTags = (tags) => {
let longestTimeBetweenTags = 0;
let startDate = null;
let endDate = null;
let previousTag = null;
let staleTagNumber = 0;
const sortedTags = [...tags].reverse();
for (const tag of sortedTags) {
if (previousTag !== null) {
const timeBetweenTags = tag.mysteryTime - previousTag.mysteryTime;
if (timeBetweenTags > longestTimeBetweenTags) {
longestTimeBetweenTags = timeBetweenTags;
startDate = new Date(previousTag.mysteryTime * 1e3);
endDate = new Date(tag.mysteryTime * 1e3);
staleTagNumber = previousTag.tagnumber;
}
}
previousTag = tag;
}
return {
timeBetweenTagsDays: convertMiliseconds(
longestTimeBetweenTags * 1e3,
"d"
),
startDate,
endDate,
staleTagNumber
};
};
const getPlayersWithLongestDailyTagStreakData = (players) => {
let longestStreakDays = 0;
let playerRecord;
const playersData = [];
for (const player of players) {
if (player.name === "") {
console.log(
"Player has no name, and probably no real data. Ignoring player: ",
player
);
continue;
}
const playerLongestStreakData = getTagLongestDailyStreakData(
player.tags
);
if (playerLongestStreakData.longestStreakDaysCount > longestStreakDays) {
longestStreakDays = playerLongestStreakData.longestStreakDaysCount;
}
playerRecord = {
playerName: player.name,
longestStreakData: playerLongestStreakData
};
playersData.push(playerRecord);
}
const longestStreakPlayersData = [];
for (const pd of playersData) {
if (pd.longestStreakData.longestStreakDaysCount >= longestStreakDays) {
longestStreakPlayersData.push(pd);
}
}
return longestStreakPlayersData;
};
const getTagLongestDailyStreakData = (tags) => {
const tagDates = getUniqueTagDates(tags);
tagDates.sort((a, b) => a.getTime() - b.getTime());
let streakDaysCount = 1;
let streakDaysCountLongest = 1;
let streakStartDate = null;
let streakLongestStartDate = null;
let streakEndDate = null;
let previousDate = null;
const oneDay = 24 * 60 * 60 * 1e3;
for (const td of tagDates) {
if (previousDate !== null) {
const tagDateMinusOneDay = /* @__PURE__ */ new Date();
tagDateMinusOneDay.setTime(td.getTime() - oneDay);
if (getIsSameDay(tagDateMinusOneDay, previousDate)) {
streakDaysCount++;
if (streakDaysCount === 2) {
streakStartDate = previousDate;
}
if (streakDaysCount >= streakDaysCountLongest) {
streakLongestStartDate = streakStartDate;
streakDaysCountLongest = streakDaysCount;
streakEndDate = td;
}
} else {
streakDaysCount = 1;
}
} else {
streakStartDate = td;
streakEndDate = td;
}
previousDate = td;
}
const streakData = {
longestStreakDaysCount: streakDaysCountLongest,
longestStreakStartDate: streakDaysCountLongest > 1 ? streakLongestStartDate : null,
longestStreakEndDate: streakDaysCountLongest > 1 ? streakEndDate : null
};
return streakData;
};
const getUniqueTagDates = (tags) => {
const uniqueTagDates = [];
for (const tag of tags) {
if (tag.mysteryTime === 0) {
continue;
}
const tagDate = getTagDate(tag.mysteryTime);
if (uniqueTagDates.length === 0) {
uniqueTagDates.push(tagDate);
} else {
const isAlreadyPresent = uniqueTagDates.some(
(date) => getIsSameDay(date, tagDate)
);
if (!isAlreadyPresent) {
uniqueTagDates.push(tagDate);
}
}
}
return uniqueTagDates;
};
const getIsSameDay = (d1, d2) => {
return d1.getFullYear() === d2.getFullYear() && d1.getMonth() === d2.getMonth() && d1.getDate() === d2.getDate();
};
const getDaysDifference = (d1, d2) => {
const timeDiff = Math.abs(d2.getTime() - d1.getTime());
const oneDay = 24 * 60 * 60 * 1e3;
const diffDays = Math.ceil(timeDiff / oneDay);
return diffDays;
};
const getIsWithinDaysRange = (d1, d2, days) => {
const diffDays = getDaysDifference(d1, d2);
return diffDays <= days;
};
const getGameHighestNumberTagsPerNumberDaysData = (tags, days = 1) => {
let tagsPerNumberDaysHighest = 1;
let previousTagDate = null;
let startDate = null;
let endDate = null;
let tagDatesInRange = [];
let tagIsInRange = false;
let tagsPerNumberDaysData = {
tagCount: tagsPerNumberDaysHighest,
dayCount: days,
startDate: null,
endDate: null
};
const oneDay = 24 * 60 * 60 * 1e3;
const daysBack = [...Array(days).keys()];
const sortedTags = [...tags].reverse();
for (const tag of sortedTags) {
const tagDate = getTagDate(tag.mysteryTime);
if (previousTagDate !== null) {
if (tagDatesInRange.length === 0) {
tagDatesInRange = [previousTagDate];
}
const tagDatesInRangeNew = [...tagDatesInRange];
for (const dayBack of daysBack) {
const daysBackTime = oneDay * dayBack;
const tagDateMinusDayBack = /* @__PURE__ */ new Date();
tagDateMinusDayBack.setTime(tagDate.getTime() - daysBackTime);
for (const tagDateInRange of tagDatesInRange) {
if (getIsWithinDaysRange(tagDateInRange, tagDateMinusDayBack, days)) {
tagDatesInRangeNew.push(tagDate);
tagIsInRange = true;
break;
} else {
const indexNotInRangeDate = tagDatesInRangeNew.indexOf(tagDateInRange);
tagDatesInRangeNew.splice(indexNotInRangeDate, 1);
tagIsInRange = false;
}
}
if (tagIsInRange) {
break;
}
}
tagDatesInRange = tagDatesInRangeNew;
if (tagDatesInRange.length >= tagsPerNumberDaysHighest) {
tagsPerNumberDaysHighest = tagDatesInRange.length;
startDate = tagDatesInRange[0];
endDate = tagDatesInRange[tagDatesInRange.length - 1];
}
}
previousTagDate = tagDate;
}
tagsPerNumberDaysData = {
tagCount: tagsPerNumberDaysHighest,
dayCount: days,
startDate,
endDate
};
return tagsPerNumberDaysData;
};
const getPlayerHighestNumberTagsPerDayData = (player) => {
const tagsPerDayData = {
playerName: player.name,
tagCount: null,
tagDate: null
};
let tagsPerDay = 1;
let tagsPerDayHighest = 1;
let previousTagDate = null;
for (const tag of player.tags) {
const tagDate = getTagDate(tag.mysteryTime);
if (previousTagDate !== null && getIsSameDay(tagDate, previousTagDate)) {
tagsPerDay++;
} else {
tagsPerDay = 1;
}
if (tagsPerDay > tagsPerDayHighest) {
tagsPerDayHighest = tagsPerDay;
tagsPerDayData.tagCount = tagsPerDayHighest;
tagsPerDayData.tagDate = tagDate;
}
previousTagDate = tagDate;
}
return tagsPerDayData;
};
const getPlayersWithHighestNumberTagsPerDayData = (players) => {
let tagsPerDayHighest = 0;
const tagsPerDayData = [];
const highestTagsPerDayData = [];
for (const player of players) {
if (player.name === "") {
console.log(
"Player has no name, and probably no real data. Ignoring player: ",
player
);
continue;
}
const tagsPerDayRecord = getPlayerHighestNumberTagsPerDayData(player);
tagsPerDayData.push(tagsPerDayRecord);
if (tagsPerDayRecord.tagCount !== null && tagsPerDayRecord.tagCount > tagsPerDayHighest) {
tagsPerDayHighest = tagsPerDayRecord.tagCount;
}
}
for (const tpdr of tagsPerDayData) {
if (tpdr.tagCount !== null && tpdr.tagCount >= tagsPerDayHighest) {
highestTagsPerDayData.push(tpdr);
}
}
return highestTagsPerDayData;
};
const getTagNumbersFromTextRegex = new RegExp(
/((?:(?:bike\s*)?(?:\s*tag)?)(#|num|number)(\d+)(?:(?:\s*tag)?|(?:\s*proof)?))|((?:bike\s*)?(?:tag\s*)(#|num|number)?\s*(\d+))|((?:(?:found\s*#?)|(?:here'?i?s?\s*))\[?(\d+)\]?)/gi
);
const getPlayerFromTextRegex = new RegExp(
/((?:proof\s*(?:found\s*at\s*)?(?:\(.*\))?\s*by\s*)(.*?(?= on \[|$)))|((?:tag\s*(?:(?:\(\s*hint:\s*)?.*\))?\s*by\s*)(.+?(?= on \[|\r|\n|$))?)|((?:tag\s*(?:(?:\(\s*hint:\s*)?.*\))?\s*by\s*)(.+?(?= on \[|\r|\n))?)|((?:credit goes to:\s*)(.*)(?:\sfor finding))|(?:tag\s*)(?:number\s*)?(\d*)?(?:\s*by\s*)(.+?(?= on \[|$|\n))/i
);
const getFoundLocationFromTextRegex = new RegExp(
/(?:is\s*(?:at|the)?\s*?)(.*?)(?=\s*by\s+|\]|$)|(?:found)\s*(?:at)?\s*\(([^()]+(\([^()]+\)[^()]*)*)\)(.*(?:\)|]|$))|(?:found\s*at\s*\()(.*(?:\)))/im
);
const getConfirmedBoundaryFromTextRegex = new RegExp(
/(\s*\[.*\]✓\s*\(.*\)\s*)/im
);
const getPlayerFromInfoFromTextRegex = new RegExp(
/(?:\[Player\s*)(.*)(?:]\s*\+\()(.*)(?=\))/i
);
const getGameFromInfoFromTextRegex = new RegExp(
/(((?:{\s*)(.*)(?:}))((?:\s*\[)(.*)(?=\])\])?((?:\s*@\()(.*)(?=\))\))?)\s*::\s*(((?:\[BikeTag\s*Game\s*)(.*)(?:]))((?:\s*#\()(.*)(?=\))\))?((?:\s*\|)(.*)(?=\|)\|)?)/i
);
const getGameSlugFromTextRegex = new RegExp(/((\w*)\s*bike\s*tag!?)/i);
const getHintFromTextRegex = new RegExp(/(?:hint:\s*)(.*)\)/i);
const getTimeFromTextRegex = new RegExp(
/(?:on\s+\[(\d+\/\d+\/\d\d)@(\d+:\d+:\d+)\])/i
);
const getGPSLocationFromTextRegex = new RegExp(
/(([0-9]{1,2})[:|°]([0-9]{1,2})[:|'|′]?([0-9]{1,2}(?:\.[0-9]+){0,1})?["|″]([N|S]),?\s*([0-9]{1,3})[:|°]([0-9]{1,2})[:|'|′]?([0-9]{1,2}(?:\.[0-9]+){0,1})?["|″]([E|W]))|((-?\d+(\.\d+)?),\s*(-?\d+(\.\d+)?))/
);
const getImageURLsFromTextRegex = new RegExp(
/https?:\/\/.*?\.[a-z]{2,4}\/.+?(?=\)|\s|$)/gi
);
const getAlbumIdFromTextRegex = new RegExp(
/((?:imgur.com\/)(?:(a|album|gallery)\/)(\w+))/i
);
const getPlayerIdFromTextRegex = RegExp(/\[(.*)\]/i);
const getDiscussionUrlFromTextRegex = RegExp(/{(.*)}/i);
const getGPSCoordinatesValueFromTextRegex = RegExp(/\((.*)\)/i);
const getTagnumberFromSlugRegex = RegExp(/([^-]*)([^-]*)(\d)/);
const getImgurImageHashFromUrlRegex = RegExp(
/(?:imgur.com\/)(.*)(?:\.)/i
);
const getSanityImageUrlHashFromTextRegex = RegExp(
/^(?:image-)(.*?(?=-(-png|-jpg|-jpeg|-gif)))/i
);
const getCreditFromBlueskyTextRegex = RegExp(
/(?:tag\s*)(?:number\s*)?(\d*)?(?:\s*by\s*)(.+?(?=$|\n))/i
);
const BikeTagExpressions = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
__proto__: null,
getAlbumIdFromTextRegex,
getConfirmedBoundaryFromTextRegex,
getCreditFromBlueskyTextRegex,
getDiscussionUrlFromTextRegex,
getFoundLocationFromTextRegex,
getGPSCoordinatesValueFromTextRegex,
getGPSLocationFromTextRegex,
getGameFromInfoFromTextRegex,
getGameSlugFromTextRegex,
getHintFromTextRegex,
getImageURLsFromTextRegex,
getImgurImageHashFromUrlRegex,
getPlayerFromInfoFromTextRegex,
getPlayerFromTextRegex,
getPlayerIdFromTextRegex,
getSanityImageUrlHashFromTextRegex,
getTagNumbersFromTextRegex,
getTagnumberFromSlugRegex,
getTimeFromTextRegex
}, Symbol.toStringTag, { value: "Module" }));
const getConfirmedBoundarySymbol = "✓";
const getTagnumberFromSlug = (inputText, fallback, cache) => {
if (!inputText.length) return fallback;
const cacheKey = `${cacheKeys.slugText}${inputText}`;
const existingParsed = getCacheIfExists(cacheKey, cache);
if (existingParsed) return existingParsed;
const slugText = getTagnumberFromSlugRegex.exec(inputText);
if (!slugText) {
putCacheIfExists(cacheKey, fallback, cache);
return fallback;
}
const slug = parseInt((slugText[0] || "").trim());
putCacheIfExists(cacheKey, slug, cache);
return slug;
};
const getTagNumbersFromText$1 = (inputText, fallback, cache) => {
if (!inputText.length) return fallback;
const cacheKey = `${cacheKeys.tagNumberText}${inputText}`;
const existingParsed = getCacheIfExists(cacheKey, cache);
if (existingParsed) return existingParsed;
const tagNumberText = inputText.match(getTagNumbersFromTextRegex);
if (!tagNumberText) return fallback || [];
const tagNumbers = tagNumberText.reduce((numbers, text) => {
if (!text) return numbers;
const tagNumberMatches = text.match(/\d+/);
const tagNumber = tagNumberMatches && tagNumberMatches.length ? tagNumberMatches[0] : null;
if (!tagNumber) return numbers;
const number = Number.parseInt(tagNumber);
if (numbers.indexOf(number) == -1) numbers.push(number);
return numbers;
}, []);
if (!tagNumbers.length && fallback) {
putCacheIfExists(cacheKey, fallback, cache);
return fallback;
}
putCacheIfExists(cacheKey, tagNumbers, cache);
return tagNumbers;
};
const getPlayerFromText$1 = (inputText, fallback, cache) => {
if (!inputText.length) return fallback;
const cacheKey = `${cacheKeys.playerText}${inputText}`;
const existingParsed = getCacheIfExists(cacheKey, cache);
if (existingParsed) return existingParsed;
const playerText = getPlayerFromTextRegex.exec(inputText);
if (!playerText) return fallback ?? null;
const tagPlayers = playerText.filter(
(c) => typeof c === "string" && (c.indexOf("tag ") === -1 || c.indexOf("tag") !== 0) && (c.indexOf("proof ") === -1 || c.indexOf("proof") !== 0) && c.indexOf("to:") === -1 && c.indexOf("hint:") === -1 && Number.isInteger(Number.parseInt(c)) === false && (c.indexOf(" by ") === -1 || c.indexOf(" by ") !== 0)
);
if (!tagPlayers.length && fallback) {
putCacheIfExists(cacheKey, fallback, cache);
return fallback;
}
const player = tagPlayers[0];
putCacheIfExists(cacheKey, player, cache);
return player;
};
const getFoundLocationFromText$1 = (inputText, fallback, cache) => {
if (!inputText.length) return fallback;
const cacheKey = `${cacheKeys.locationText}${inputText}`;
const existingParsed = getCacheIfExists(cacheKey, cache);
if (existingParsed) return existingParsed;
const foundLocationText = getFoundLocationFromTextRegex.exec(inputText);
if (!foundLocationText) {
fallback = fallback ?? null;
putCacheIfExists(cacheKey, fallback, cache);
return fallback;
}
const foundLocation = (foundLocationText[1] ?? foundLocationText[2] ?? "").trim();
putCacheIfExists(cacheKey, foundLocation, cache);
return foundLocation;
};
const getHintFromText$1 = (inputText, fallback, cache) => {
if (!inputText.length) return fallback;
const cacheKey = `${cacheKeys.hintText}${inputText}`;
const existingParsed = getCacheIfExists(cacheKey, cache);
if (existingParsed) return existingParsed;
const tagNumberText = inputText.match(getHintFromTextRegex);
if (!tagNumberText) return fallback ?? null;
const tagNumbers = tagNumberText.reduce((numbers, text) => {
const tagNumberMatches = text.match(/\d+/);
const tagNumber = tagNumberMatches && tagNumberMatches.length ? tagNumberMatches[0] : null;
if (!tagNumber) return numbers;
const number = Number.parseInt(tagNumber);
if (numbers.indexOf(number) == -1) numbers.push(number);
return numbers;
}, []);
if (!tagNumbers.length && fallback) {
putCacheIfExists(cacheKey, fallback, cache);
return fallback;
}
putCacheIfExists(cacheKey, tagNumbers, cache);
return tagNumbers;
};
const getGpsStringLocationFromText = (inputText, fallback, cache) => {
if (!(inputText == null ? void 0 : inputText.length)) return fallback;
const cacheKey = `${cacheKeys.gpsStringText}${inputText}`;
const existingParsed = getCacheIfExists(cacheKey, cache);
if (existingParsed) return existingParsed;
inputText = inputText.replace(/\\/g, "");
inputText.match(getGPSLocationFromTextRegex);
const gpsText = getGPSLocationFromTextRegex.exec(inputText);
if (!gpsText) {
fallback = fallback ?? null;
putCacheIfExists(cacheKey, fallback, cache);
return fallback;
}
const gpsString = gpsText[0].split(",").length > 2 ? gpsText[0] : `${gpsText[0]}, 0`;
putCacheIfExists(cacheKey, gpsString, cache);
return gpsString;
};
const getGPSLocationFromText = (inputText, fallback, cache) => {
const gpsString = getGpsStringLocationFromText(inputText, "", cache);
if (gpsString.length) {
const gpsPair = gpsString.split(",");
const gpsLocation = {
lat: parseFloat(gpsPair[0]),
long: parseFloat(gpsPair[1]),
alt: parseFloat(gpsPair[2])
};
return gpsLocation;
}
return fallback ?? {
lat: 0,
long: 0,
alt: 0
};
};
const getImgurAlbumIdFromText = (inputText, fallback, cache) => {
if (!inputText.length) return fallback;
const cacheKey = `${cacheKeys.imageUrlText}${inputText}`;
const existingParsed = getCacheIfExists(cacheKey, cache);
if (existingParsed) return existingParsed;
inputText.match(getAlbumIdFromTextRegex);
const albumbIdMatches = getAlbumIdFromTextRegex.exec(inputText);
const albumbIds = albumbIdMatches.reduce((ids, id) => {
if (id.indexOf("gallery") === -1 && id.indexOf("?") === -1 && id.indexOf("a/") === -1 && id.length > 1) {
ids.push(id);
}
return ids;
}, []);
if (!albumbIds.length && fallback) {
putCacheIfExists(cacheKey, fallback, cache);
return fallback;
}
const albumbId = albumbIds[0];
putCacheIfExists(cacheKey, albumbId, cache);
return albumbId;
};
const getMentionURLsFromText = (inputText, fallback, cache) => {
if (!inputText.length) return fallback;
const cacheKey = `${cacheKeys.mentionText}${inputText}`;
const existingParsed = getCacheIfExists(cacheKey, cache);
if (existingParsed) return existingParsed;
const validImageURLs = ["t.co"];
const selfTextURLs = inputText.match(getImageURLsFromTextRegex);
if (selfTextURLs) {
const tagImageURLs = selfTextURLs.reduce((urls, url) => {
if (!url || !new RegExp(validImageURLs.join("|")).test(url)) return urls;
const ext = /[^.]+$/.test(url) ? "." + /[^.]+$/.exec(url) : "";
if (
// ['.jpg', '.jpeg', '.png', '.bmp'].indexOf(ext) === -1 &&
ext.indexOf(".co") === 0 && url.indexOf("//t.co/") !== -1 && url.length > 2
) ;
urls.push(url);
return urls;
}, []);
if (!tagImageURLs.length && fallback) {
putCacheIfExists(cacheKey, fallback, cache);
return fallback;
}
putCacheIfExists(cacheKey, tagImageURLs, cache);
return tagImageURLs;
}
putCacheIfExists(cacheKey, fallback, cache);
return fallback;
};
const getImageURLsFromText = (inputText, fallback, cache) => {
if (!inputText.length) return fallback;
const cacheKey = `${cacheKeys.imagesText}${inputText}`;
const existingParsed = getCacheIfExists(cacheKey, cache);
if (existingParsed) return existingParsed;
const validImageURLs = ["imgur", "t.co"];
const selfTextURLs = inputText.match(getImageURLsFromTextRegex);
if (selfTextURLs) {
const tagImageURLs = selfTextURLs.reduce((urls, url) => {
if (!url || !new RegExp(validImageURLs.join("|")).test(url)) return urls;
const ext = /[^.]+$/.test(url) ? "." + /[^.]+$/.exec(url) : "";
if ([".jpg", ".jpeg", ".png", ".webp", ".bmp"].indexOf(ext) === -1 && ext.indexOf(".com/") === 0 && url.indexOf("//imgur.com/") !== -1 && url.indexOf("3/album") === -1 && url.indexOf("/a/") === -1 && url.indexOf(".com/gallery") === -1 && url.length > 2) {
url = `${url.replace("//imgur.com", "//i.imgur.com")}.jpg`;
}
urls.push(url);
return urls;
}, []);
if (!tagImageURLs.length && fallback) {
putCacheIfExists(cacheKey, fallback, cache);
return fallback;
}
putCacheIfExists(cacheKey, tagImageURLs, cache);
return tagImageURLs;
}
putCacheIfExists(cacheKey, fallback, cache);
return fallback;
};
const getDiscussionUrlFromText$1 = (inputText, cache) => {
if (!inputText.length) return "";
const cacheKey = `${cacheKeys.discussionText}${inputText}`;
const existingParsed = getCacheIfExists(cacheKey, cache);
if (existingParsed) return existingParsed;
const tagDiscussionLinkMatches = getDiscussionUrlFromTextRegex.exec(inputText);
if (!(tagDiscussionLinkMatches == null ? void 0 : tagDiscussionLinkMatches.length)) {
putCacheIfExists(cacheKey, null, cache);
return null;
}
const discussionUrl = (tagDiscussionLinkMatches[1] || "").trim();
putCacheIfExists(cacheKey, discussionUrl, cache);
return discussionUrl;
};
const getImageHashFromText = (inputText, cache) => {
if (!(inputText == null ? void 0 : inputText.length)) return "";
const cacheKey = `${cacheKeys.imageHashText}${inputText}`;
const existingParsed = getCacheIfExists(cacheKey, cache);
if (existingParsed) return existingParsed;
inputText.match(getImgurImageHashFromUrlRegex);
const imageHashMatches = getImgurImageHashFromUrlRegex.exec(inputText);
if (!imageHashMatches || !imageHashMatches.length) {
putCacheIfExists(cacheKey, null, cache);
return null;
}
const imageHash = (imageHashMatches[1] || "").trim();
putCacheIfExists(cacheKey, imageHash, cache);
return imageHash;
};
const getSanityImageUrlHashFromText = (inputText, cache) => {
if (!inputText.length) return "";
const cacheKey = `${cacheKeys.sanityUrlText}${inputText}`;
const existingParsed = getCacheIfExists(cacheKey, cache);
if (existingParsed) return existingParsed;
const imageUrlMatches = getSanityImageUrlHashFromTextRegex.exec(inputText);
if (!imageUrlMatches || !imageUrlMatches.length) {
putCacheIfExists(cacheKey, null, cache);
return null;
}
const imageHash = (imageUrlMatches[1] || "").trim();
putCacheIfExists(cacheKey, imageHash, cache);
return imageHash;
};
const getImgurFoundImageHashFromBikeTagData = (tag, cache) => {
return getImageHashFromText(tag.foundImageUrl, cache);
};
const getDateStringForImgurDescription = (isodate) => {
if (!isodate) return "";
const date = new Date(isodate * 1e3);
const dateString = `${date.getMonth() + 1}/${date.getDate()}/${date.getFullYear().toString().substring(2)}`;
const timeString = `${date.getHours().toString().padStart(2, "0")}:${date.getMinutes().toString().padStart(2, "0")}:${date.getSeconds().toString().padStart(2, "0")}`;
return ` on [${dateString}@${timeString}]`;
};
const getImgurFoundDescriptionFromBikeTagData = (tag, includeCredit = true, includeDate = true) => `#${tag.tagnumber} proof${tag.foundLocation ? ` found at (${tag.foundLocation})` : ""}${includeCredit ? ` by ${tag.foundPlayer}` : ""}${includeDate ? getDateStringForImgurDescription(tag.foundTime) : ""}`;
const getImgurFoundTitleFromBikeTagData = (tag, fromCombinedTag = false) => {
var _a;
return `${!tag.gps || tag.gps.lat === 0 && tag.gps.long === 0 ? "" : `(${tag.gps.lat ?? 0}, ${tag.gps.long ?? 0}, ${tag.gps.alt ?? 0})`}
${!fromCombinedTag && // don't include the player id from a combined tag in the found tag
((_a = tag.playerId) == null ? void 0 : _a.length) ? `[${tag.playerId}]` : ""}
${tag.confirmedBoundary ? getConfirmedBoundarySymbol : ""}`;
};
const getImgurMysteryImageHashFromBikeTagData = (tag, cache) => {
return getImageHashFromText(tag.mysteryImageUrl, cache);
};
const getImgurMysteryTitleFromBikeTagData = (tag, fromCombinedTag = false) => {
var _a;
return `${!fromCombinedTag && // don't include the gps from a combined tag in the mystery
!tag.gps || tag.gps.lat === 0 && tag.gps.long === 0 ? "" : `(${tag.gps.lat ?? 0}, ${tag.gps.long ?? 0}, ${tag.gps.alt ?? 0})`}
${((_a = tag.playerId) == null ? void 0 : _a.length) ? `[${tag.playerId}]` : ""}
${tag.discussionUrl ? `{${tag.discussionUrl}}` : ""}`;
};
const getImgurMysteryDescriptionFromBikeTagData = (tag, includeCredit = true, includeHint = true, includeDate = true) => `#${tag.tagnumber} tag ${includeHint && tag.hint ? `(hint: ${tag.hint})` : ""}${includeCredit ? ` by ${tag.mysteryPlayer}` : ""}${includeDate ? getDateStringForImgurDescription(tag.mysteryTime) : ""}`;
const getOnlyMysteryTagFromTagData = (tagData) => {
const onlyMysteryTagFields = {
playerId: tagData.playerId,
game: tagData.game,
tagnumber: tagData.tagnumber,
name: tagData.name,
slug: tagData.slug,
mysteryImageUrl: tagData.mysteryIm