refactor for reduced repetition

This commit is contained in:
2026-01-11 09:17:48 -05:00
parent 3753573574
commit 7727ecdce3
5 changed files with 336 additions and 280 deletions

View File

@@ -2,20 +2,20 @@ const { SlashCommandBuilder } = require('discord.js');
const torn = require('../../torn.js'); const torn = require('../../torn.js');
module.exports = { module.exports = {
data: new SlashCommandBuilder() data: new SlashCommandBuilder()
.setName('calcpayout') .setName('calcpayout')
.setDescription('[WIP] Calculate war payout based on participation') .setDescription('[WIP] Calculate war payout based on participation')
.addIntegerOption(option => .addIntegerOption(option =>
option.setName('total') option.setName('total')
.setDescription('Full war earnings total before cuts')), .setDescription('Full war earnings total before cuts')),
async execute(interaction) { async execute(interaction) {
const total = interaction.options.getInteger('total'); const total = interaction.options.getInteger('total');
const lastWarRaw = await torn.api('https://api.torn.com/v2/faction/rankedwars?offset=0&limit=1&sort=DESC'); const lastWarRaw = await torn.faction.rankedWars({ offset: 0, limit: 1, sort: 'DESC' });
const lastWarID = lastWarRaw.rankedwars[0].id const lastWarID = lastWarRaw[0].id
const lastWar = await torn.api(`https://api.torn.com/v2/faction/${lastWarID}/rankedwarreport?`); const lastWar = await torn.faction.rankedWarReport(lastWarID);
const ourMembers = lastWar.rankedwarreport.factions.find(faction => faction.id === 53026).members; // TODO: dont hardcore faction ID const ourMembers = lastWar.factions.find(faction => faction.id === 53026).members; // TODO: dont hardcore faction ID
let totalParticipants = 0; let totalParticipants = 0;
let message = `# War Payout Calculation for War against ${lastWar.rankedwarreport.factions.find(faction => faction.id !== 53026).name} with total earnings of $${total.toLocaleString()}:\n`; let message = `# War Payout Calculation for War against ${lastWar.factions.find(faction => faction.id !== 53026).name} with total earnings of $${total.toLocaleString()}:\n`;
ourMembers.forEach(member => { ourMembers.forEach(member => {
if (member.id == 2993713) { if (member.id == 2993713) {
console.log(`User ${member.name} is calculated separately.`); console.log(`User ${member.name} is calculated separately.`);
@@ -32,5 +32,5 @@ module.exports = {
console.log(`there were ${totalParticipants} participants`); console.log(`there were ${totalParticipants} participants`);
console.log(message) console.log(message)
interaction.reply(message); interaction.reply(message);
}, },
}; };

View File

@@ -4,7 +4,7 @@ module.exports = async (client, torn, config) => {
const channel = client.channels.resolve(config.channels.ocAlert); const channel = client.channels.resolve(config.channels.ocAlert);
const now = new Date(); const now = new Date();
const state = require('../state.json'); const state = require('../state.json');
const data = await torn.api(`https://api.torn.com/v2/faction/crimes?cat=planning&sort=DESC`); const data = { crimes: await torn.faction.crimes({ category: 'planning', sort: 'DESC' }) };
let itemsneeded = 0; let itemsneeded = 0;
let message = "OCs with unavailable items:\n"; let message = "OCs with unavailable items:\n";
for (const crime of data.crimes) { for (const crime of data.crimes) {
@@ -36,15 +36,15 @@ module.exports = async (client, torn, config) => {
); );
channel.send({ content: message, components: [row] }); channel.send({ content: message, components: [row] });
state.itemAlertLast = now.toISOString(); state.itemAlertLast = now.toISOString();
fs.writeFile('./state.json', JSON.stringify(state, null, 4), err => {if (err) {console.error(err)}}); fs.writeFile('./state.json', JSON.stringify(state, null, 4), err => { if (err) { console.error(err) } });
} else { console.debug(`noItemOC: Would send alert, but one was sent recently`); } } else { console.debug(`noItemOC: Would send alert, but one was sent recently`); }
} else { } else {
console.debug(`noItemOC: Nobody needs items, not sending alert`); console.debug(`noItemOC: Nobody needs items, not sending alert`);
const twentyFourHoursAgo = new Date(now.getTime() - 24 * 60 * 60 * 1000); const twentyFourHoursAgo = new Date(now.getTime() - 24 * 60 * 60 * 1000);
state.itemAlertLast = twentyFourHoursAgo.toISOString(); state.itemAlertLast = twentyFourHoursAgo.toISOString();
fs.writeFile('./state.json', JSON.stringify(state, null, 4), err => {if (err) {console.error(err)}}); fs.writeFile('./state.json', JSON.stringify(state, null, 4), err => { if (err) { console.error(err) } });
} }
}; };
module.exports.schedule = '45 * * * *'; module.exports.schedule = '45 * * * *';

View File

@@ -40,7 +40,8 @@ module.exports = async (client, torn, config) => {
let embed = new EmbedBuilder() let embed = new EmbedBuilder()
.setTitle('Crime Availability Check') .setTitle('Crime Availability Check')
await torn.api(`https://api.torn.com/v2/faction/crimes?cat=recruiting&offset=0&sort=DESC`).then(data => { await torn.faction.crimes({ category: 'recruiting', offset: 0, sort: 'DESC' }).then(crimeList => {
const data = { crimes: crimeList };
data.crimes.forEach(crime => { data.crimes.forEach(crime => {
crimes.difficulty[crime.difficulty - 1].count++ crimes.difficulty[crime.difficulty - 1].count++
}); });

View File

@@ -6,7 +6,7 @@ module.exports = async (client, torn, config) => {
const now = new Date(); const now = new Date();
const state = require('../state.json'); const state = require('../state.json');
let embeds = []; let embeds = [];
const data = await torn.api(`https://api.torn.com/v2/faction/crimes?cat=successful&from=${now.getTime() / 1000 - 7 * 24 * 60 * 60}&sort=DESC`); const data = { crimes: await torn.faction.crimes({ category: 'successful', from: now.getTime() / 1000 - 7 * 24 * 60 * 60, sort: 'DESC' }) };
for (const crime of data.crimes) { for (const crime of data.crimes) {
if (!crime.rewards.payout) { if (!crime.rewards.payout) {
console.debug(`unpaidOC: Found unpaid crime: ${crime.name}:${crime.id}`); console.debug(`unpaidOC: Found unpaid crime: ${crime.name}:${crime.id}`);
@@ -56,17 +56,17 @@ module.exports = async (client, torn, config) => {
.setLabel('Click when sorted') .setLabel('Click when sorted')
.setStyle(ButtonStyle.Success), .setStyle(ButtonStyle.Success),
); );
channel.send({content: "# Unpaid Faction Crimes:", embeds: embeds, components: [row] }); channel.send({ content: "# Unpaid Faction Crimes:", embeds: embeds, components: [row] });
state.payoutAlertLast = now.toISOString(); state.payoutAlertLast = now.toISOString();
fs.writeFile('./state.json', JSON.stringify(state, null, 4), err => {if (err) {console.error(err)}}); fs.writeFile('./state.json', JSON.stringify(state, null, 4), err => { if (err) { console.error(err) } });
} else { console.debug(`unpaidOC: Would send alert, but one was sent recently`); } } else { console.debug(`unpaidOC: Would send alert, but one was sent recently`); }
} else { } else {
console.debug(`unpaidOC: All crimes are paid, not sending alert`); console.debug(`unpaidOC: All crimes are paid, not sending alert`);
const twentyFourHoursAgo = new Date(now.getTime() - 24 * 60 * 60 * 1000); const twentyFourHoursAgo = new Date(now.getTime() - 24 * 60 * 60 * 1000);
state.payoutAlertLast = twentyFourHoursAgo.toISOString(); state.payoutAlertLast = twentyFourHoursAgo.toISOString();
fs.writeFile('./state.json', JSON.stringify(state, null, 4), err => {if (err) {console.error(err)}}); fs.writeFile('./state.json', JSON.stringify(state, null, 4), err => { if (err) { console.error(err) } });
} }
}; };
module.exports.schedule = '0 * * * *'; module.exports.schedule = '0 * * * *';

551
torn.js
View File

@@ -1,281 +1,336 @@
const fs = require('fs'); const fs = require('fs');
let config; let config;
let cache; let cache;
try {config = require('./config.json')} catch {return}
try {cache = require('./cache.json')} catch { // Load config and cache
try {
config = require('./config.json');
} catch (e) {
console.error("Failed to load config.json", e);
}
try {
cache = require('./cache.json');
} catch (e) {
cache = { cache = {
users: {}, users: {},
factions: {}, factions: {},
companies: {}, companies: {},
items: {} items: {}
}; };
fs.writeFileSync('./cache.json', JSON.stringify(cache)); try {
return; fs.writeFileSync('./cache.json', JSON.stringify(cache));
} catch (writeErr) {
console.error("Failed to write initial cache.json", writeErr);
}
} }
module.exports = () => {}; // Constants
module.exports.readyCheck = async (key) => { const TIME_12H = 12 * 60 * 60 * 1000;
const url = `https://api.torn.com/user/?selections=basic&key=${key}` const TIME_7D = 7 * 24 * 60 * 60 * 1000;
const response = await fetch(url); const TIME_30D = 30 * 24 * 60 * 60 * 1000;
const data = await response.json();
console.log(`Torn: Connected as ${data.name} [${data.player_id}]`); // Helper to save cache
}; function saveCache() {
module.exports.test = async () => { try {
const url = `https://api.torn.com/user/?selections=basic&key=${config.torn}` fs.writeFileSync('./cache.json', JSON.stringify(cache));
const response = await fetch(url); } catch (e) {
const data = await response.json(); console.error("Failed to save cache:", e);
return(`Connected to Torn as ${data.name} [${data.player_id}]`); }
}; }
module.exports.api = async (url) => {
const response = await fetch(`${url}&key=${config.torn}`); // Generic Caching Helper
const data = await response.json(); async function getCached(collectionName, id, fetchFn, ttl) {
return(data); const now = new Date().getTime();
}; const item = cache[collectionName][id];
module.exports.cache = { let lastUpdated = 0;
async user(user) {
const twelveHours = 12 * 60 * 60 * 1000; if (item && item.updated) {
const now = new Date().getTime();
let last
try { try {
last = new Date(cache.users[user].updated).getTime(); lastUpdated = new Date(item.updated).getTime();
} catch { } catch (e) {
last = new Date(now - twelveHours).getTime(); lastUpdated = 0;
} }
if (cache.users[user] && (now - last < twelveHours)) { }
console.debug(`Cache: Hit for user ${cache.users[user].name}`)
return(cache.users[user]); if (item && (now - lastUpdated < ttl)) {
} else { console.debug(`Cache: Hit for ${collectionName} ${item.name || id}`);
console.debug(`Cache: Miss for user ${user}`) return item;
await module.exports.user.basic(user); } else {
console.debug(`Cache: Resolved user ${cache.users[user].name}`) console.debug(`Cache: Miss for ${collectionName} ${id || 'unknown'}`);
return(cache.users[user]);
}
},
async faction(faction) {
const twelveHours = 12 * 60 * 60 * 1000;
const now = new Date().getTime();
let last
try { try {
last = new Date(cache.factions[faction].updated).getTime(); // The fetchFn is expected to update the cache and return the data, or we can structure it differently.
} catch { // Based on the refactor code below, the fetchFn calls saveCache() and returns the data.
last = new Date(now - twelveHours).getTime(); // But wait, the original logic for checking cache was inside the 'cache' object functions,
} // calling the specific fetcher which updated the cache.
if (cache.factions[faction] && (now - last < twelveHours)) { // In the refactored 'api.cache.user' below, I call 'api.user.basic(user)'.
console.debug(`Cache: Hit for faction ${cache.factions[faction].name}`) // 'api.user.basic' updates the cache and returns data.
return(cache.factions[faction]); // So this helper just needs to return that result.
} else { // BUT, I need to make sure I return the logical object.
console.debug(`Cache: Miss for faction ${faction}`)
await module.exports.faction.basic(faction); const result = await fetchFn();
console.debug(`Cache: Resolved faction ${cache.factions[faction].name}`) console.debug(`Cache: Resolved ${collectionName} ${id}`);
return(cache.factions[faction]);
} // If the fetchFn updated the cache, we can return the cached item to be consistent
}, // or just the result. The original returned the cached item in the cache wrapper.
async company(company) { // Let's return the result from fetchFn which is usually the data.
const twelveHours = 12 * 60 * 60 * 1000; // However, the original cache wrappers returned `cache.users[user]`.
const now = new Date().getTime(); // Let's see if there is a difference.
let last // `api.user.basic` returns `data`. `cache.users[user]` is a subset of `data`?
try { // Original:
last = new Date(cache.companies[company].updated).getTime(); // `cache.users[user] = { name, player_id, level, ... }`
} catch { // `return(data)` (full api response)
last = new Date(now - twelveHours).getTime(); // But `module.exports.cache.user` returned `cache.users[user]`.
} // So the CACHE wrapper returned the CACHED OBJECT (subset), while the FETCH function returned the FULL API response.
if (cache.companies[company] && (now - last < twelveHours)) { // This is a subtle difference.
console.debug(`Cache: Hit for company ${cache.companies[company].name}`) // If I want to maintain compatibility, `getCached` should return the cached item from `cache` after fetching.
return(cache.companies[company]);
} else { return cache[collectionName][id];
console.debug(`Cache: Miss for company ${company}`) } catch (e) {
await module.exports.company(company); console.error(`Error fetching for ${collectionName} ${id}:`, e);
console.debug(`Cache: Resolved company ${cache.companies[company].name}`) throw e;
return(cache.companies[company]);
}
},
async item(item) {
const sevenDays = 7 * 24 * 60 * 60 * 1000;
const now = new Date().getTime();
let last
try {
last = new Date(cache.items[item].updated).getTime();
} catch {
last = new Date(now - sevenDays).getTime();
}
if (cache.items[item] && (now - last < sevenDays)) {
console.debug(`Cache: Hit for item ${cache.items[item].name}`)
return(cache.items[item]);
} else {
console.debug(`Cache: Miss for item ${item}`)
await module.exports.item(item);
console.debug(`Cache: Resolved item ${cache.items[item].name}`)
return(cache.items[item]);
} }
} }
} }
module.exports.user = { // Helper for generic API fetching
async basic(user) { async function fetchApi(path) {
const response = await fetch(`https://api.torn.com/user/${user}?selections=basic&key=${config.torn}`); const glue = path.includes('?') ? '&' : '?';
const data = await response.json(); const response = await fetch(`${path}${glue}key=${config.torn}`);
const now = new Date(); return response.json();
cache.users[user] = { }
name: data.name,
player_id: data.player_id, const api = {
level: data.level, readyCheck: async (key) => {
gender: data.gender, const url = `https://api.torn.com/user/?selections=basic&key=${key}`;
updated: now.toISOString()
};
fs.writeFileSync('./cache.json', JSON.stringify(cache));
return(data);
},
async profile(user) {
const response = await fetch(`https://api.torn.com/user/${user}?selections=profile&key=${config.torn}`);
const data = await response.json();
const now = new Date();
cache.users[user] = {
name: data.name,
player_id: data.player_id,
level: data.level,
gender: data.gender,
updated: now.toISOString()
};
fs.writeFileSync('./cache.json', JSON.stringify(cache));
return(data);
},
async stats(user, category, statName) {
let url = `https://api.torn.com/v2/user`;
if (user) { url += `/${user}/personalstats` };
if (category) { url += `?cat=${category}` } else { url += `?cat=all` };
if (statName) { url += `&stat=${statName}` };
const response = await fetch(url); const response = await fetch(url);
const data = await response.json(); const data = await response.json();
return(data); console.log(`Torn: Connected as ${data.name} [${data.player_id}]`);
} },
};
module.exports.faction = { test: async () => {
async basic(faction) { const url = `https://api.torn.com/user/?selections=basic&key=${config.torn}`;
let response const response = await fetch(url);
if (faction) { const data = await response.json();
response = await fetch(`https://api.torn.com/v2/faction/${faction}/basic?key=${config.torn}`); return `Connected to Torn as ${data.name} [${data.player_id}]`;
} else { },
response = await fetch(`https://api.torn.com/v2/faction/basic?key=${config.torn}`);
api: async (url) => {
const response = await fetch(`${url}&key=${config.torn}`);
return response.json();
},
cache: {
async user(user) {
return getCached('users', user, async () => await api.user.basic(user), TIME_12H);
},
async faction(faction) {
return getCached('factions', faction, async () => await api.faction.basic(faction), TIME_12H);
},
async company(company) {
return getCached('companies', company, async () => await api.company(company), TIME_12H);
},
async item(item) {
return getCached('items', item, async () => await api.item(item), TIME_7D);
} }
const data = (await response.json()).basic; },
user: {
async basic(user) {
const data = await fetchApi(`https://api.torn.com/user/${user}?selections=basic`);
const now = new Date();
cache.users[user] = {
name: data.name,
player_id: data.player_id,
level: data.level,
gender: data.gender,
updated: now.toISOString()
};
saveCache();
return data;
},
async profile(user) {
const data = await fetchApi(`https://api.torn.com/user/${user}?selections=profile`);
const now = new Date();
cache.users[user] = {
name: data.name,
player_id: data.player_id,
level: data.level,
gender: data.gender,
updated: now.toISOString()
};
saveCache();
return data;
},
async stats(user, category, statName) {
let url = `https://api.torn.com/v2/user`;
if (user) { url += `/${user}/personalstats`; }
if (category) { url += `?cat=${category}`; } else { url += `?cat=all`; }
if (statName) { url += `&stat=${statName}`; }
return fetchApi(url);
},
// Added lookup to maintain feature parity if it was ever needed, though not in original user object
},
faction: {
async basic(faction) {
const endpoint = faction ? `https://api.torn.com/v2/faction/${faction}/basic` : `https://api.torn.com/v2/faction/basic`;
const response = await fetchApi(endpoint);
// v2 return structure: { basic: { ... } }
const data = response.basic;
const now = new Date();
// Store by ID. If faction is null (own faction), we rely on data.id
cache.factions[data.id] = {
name: data.name,
leader_id: data.leader_id,
capacity: data.capacity,
rank: data.rank,
best_chain: data.best_chain,
updated: now.toISOString()
};
saveCache();
return data;
},
async members(faction) {
const endpoint = faction ? `https://api.torn.com/v2/faction/${faction}/members?striptags=true` : `https://api.torn.com/v2/faction/members?striptags=true`;
const data = await fetchApi(endpoint);
return data.members;
},
async crimes(options = {}) {
let params = new URLSearchParams();
let category = '';
if (typeof options === 'string') {
category = options;
} else {
if (options.category) category = options.category;
if (options.from) params.append('from', options.from);
if (options.to) params.append('to', options.to);
if (options.limit) params.append('limit', options.limit);
if (options.sort) params.append('sort', options.sort);
if (options.offset !== undefined) params.append('offset', options.offset);
if (options.initiator) params.append('initiator', options.initiator);
}
const endpoint = category ? `https://api.torn.com/v2/faction/crimes/${category}` : `https://api.torn.com/v2/faction/crimes`;
const queryString = params.toString() ? `?${params.toString()}` : '';
const data = await fetchApi(`${endpoint}${queryString}`);
return data.crimes;
},
async upgrades() {
const data = await fetchApi(`https://api.torn.com/v2/faction/upgrades`);
return data;
},
async news(category, from) {
const data = await fetchApi(`https://api.torn.com/v2/faction/news?striptags=false&limit=100&sort=DESC&from=${from}&cat=${category}`);
return data.news;
},
async rankedWars(options = {}) {
let params = new URLSearchParams();
if (options.limit) params.append('limit', options.limit);
if (options.offset !== undefined) params.append('offset', options.offset);
if (options.sort) params.append('sort', options.sort);
if (options.to) params.append('to', options.to);
if (options.from) params.append('from', options.from);
const queryString = params.toString() ? `?${params.toString()}` : '';
const data = await fetchApi(`https://api.torn.com/v2/faction/rankedwars${queryString}`);
return data.rankedwars;
},
async rankedWarReport(id) {
const data = await fetchApi(`https://api.torn.com/v2/faction/${id}/rankedwarreport`);
return data.rankedwarreport;
}
},
// company was a top-level function in export, but also used as property
// Original: module.exports.company = async ...
// So api.company should be a function
company: async (company) => {
const endpoint = company ? `https://api.torn.com/company/${company}?selections=profile` : `https://api.torn.com/company/?selections=profile`;
const data = await fetchApi(endpoint);
const now = new Date(); const now = new Date();
cache.factions[data.id] = { // company ID is data.company.ID
name: data.name, cache.companies[data.company.ID] = {
leader_id: data.leader_id, name: data.company.name,
capacity: data.capacity, id: data.company.ID,
rank: data.rank, company_type: data.company.company_type,
best_chain: data.best_chain, director_id: data.company.director,
rating: data.company.rating,
updated: now.toISOString() updated: now.toISOString()
}; };
fs.writeFileSync('./cache.json', JSON.stringify(cache)); saveCache();
return(data); return data.company;
}, },
async members(faction) {
let response // item was a function with a .lookup property
if (faction) { item: Object.assign(
response = await fetch(`https://api.torn.com/v2/faction/${faction}/members?striptags=true&key=${config.torn}`); async (item) => {
} else { const data = await fetchApi(`https://api.torn.com/v2/torn/${item}/items?sort=ASC`);
response = await fetch(`https://api.torn.com/v2/faction/members?striptags=true&key=${config.torn}`); const now = new Date();
cache.items[item] = data.items[0]; // Assuming item is ID
if (cache.items[item]) {
cache.items[item].updated = now.toISOString();
}
saveCache();
return data.items[0];
},
{
lookup: async (itemName) => {
console.debug(`Torn: Looking up item ${itemName}`);
const now = new Date().getTime();
// Check cache first
for (const itemId in cache.items) {
if (cache.items[itemId].name === itemName) {
let last = 0;
try { last = new Date(cache.items[itemId].updated).getTime(); } catch (e) { }
if (now - last < TIME_30D) {
console.debug(`Cache: Hit for item ${cache.items[itemId].name}`);
return cache.items[itemId];
}
}
}
console.debug(`Cache: Miss for item ${itemName}`);
const data = await fetchApi(`https://api.torn.com/v2/torn/items?cat=All&sort=ASC`);
let target;
if (data.items) {
data.items.forEach(item => {
if (item.name === itemName) {
console.debug(`Torn: Found item ${item.name} as ${item.id}`);
target = item;
}
});
}
if (target) {
cache.items[target.id] = target;
cache.items[target.id].updated = new Date().toISOString();
saveCache();
}
return target;
}
} }
const data = await response.json(); ),
return(data.members);
},
async crimes(category) {
let response
if (category) {
response = await fetch(`https://api.torn.com/v2/faction/crimes/${category}?key=${config.torn}`);
} else {
response = await fetch(`https://api.torn.com/v2/faction/crimes?key=${config.torn}`);
}
const data = await response.json();
return(data.crimes);
},
async upgrades() {
const response = await fetch(`https://api.torn.com/v2/faction/upgrades?key=${config.torn}`);
const data = await response.json();
return(data);
},
async news(category, from) {
const response = await fetch(`https://api.torn.com/v2/faction/news?striptags=false&limit=100&sort=DESC&from=${from}&cat=${category}&key=${config.torn}`)
const data = await response.json();
return(data.news);
}
}
module.exports.company = async (company) => { self: {
let response async id() {
if (company) { if (!config.tornid) {
response = await fetch(`https://api.torn.com/company/${company}?selections=profile&key=${config.torn}`); const url = `https://api.torn.com/user/?selections=basic&key=${config.torn}`;
} else { const response = await fetch(url);
response = await fetch(`https://api.torn.com/company/?selections=profile&key=${config.torn}`); const data = await response.json();
} config.tornid = data.player_id;
const data = await response.json(); console.log(`Torn: Retrieved default ID as "${data.player_id}"`);
const now = new Date(); return data.player_id;
cache.companies[data.company.ID] = { } else {
name: data.company.name, return config.tornid;
id: data.company.ID,
company_type: data.company.company_type,
director_id: data.company.director,
rating: data.company.rating,
updated: now.toISOString()
};
fs.writeFileSync('./cache.json', JSON.stringify(cache));
return(data.company);
}
module.exports.item = async (item) => {
const response = await fetch(`https://api.torn.com/v2/torn/${item}/items?sort=ASC&key=${config.torn}`);
const data = await response.json();
const now = new Date();
cache.items[item] = data.items[0];
cache.items[item].updated = now.toISOString();
fs.writeFileSync('./cache.json', JSON.stringify(cache));
return(data.items[0]);
}
module.exports.item.lookup = async (itemName) => {
console.debug(`Torn: Looking up item ${itemName}`)
const thirtyDays = 30 * 24 * 60 * 60 * 1000;
const now = new Date().getTime();
for (const itemId in cache.items) {
if (cache.items[itemId].name === itemName) {
let last = new Date(cache.items[itemId].updated).getTime();
if (now - last < thirtyDays) {
console.debug(`Cache: Hit for item ${cache.items[itemId].name}`);
return cache.items[itemId];
} }
} }
} }
console.debug(`Cache: Miss for item ${itemName}`);
const response = await fetch(`https://api.torn.com/v2/torn/items?cat=All&sort=ASC&key=${config.torn}`);
const data = await response.json();
let target;
data.items.forEach(item => {
if (item.name === itemName) {
console.debug(`Torn: Found item ${item.name} as ${item.id}`)
target = item;
}
});
if (target) {
cache.items[target.id] = target;
cache.items[target.id].updated = new Date().toISOString();
fs.writeFileSync('./cache.json', JSON.stringify(cache));
}
return(target);
}; };
module.exports = api;
module.exports.self = {
async id() {
if (!config.tornid) {
const url = `https://api.torn.com/user/?selections=basic&key=${config.torn}`
const response = await fetch(url);
const data = await response.json();
config.tornid = data.player_id;
console.log(`Torn: Retrieved default ID as "${data.player_id}"`)
return(data.player_id);
} else return config.tornid;
}
}