refactor for reduced repetition
This commit is contained in:
@@ -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);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@@ -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 * * * *';
|
||||||
@@ -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++
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -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}`);
|
||||||
@@ -31,7 +31,7 @@ module.exports = async (client, torn, config) => {
|
|||||||
});
|
});
|
||||||
embed.setDescription(items);
|
embed.setDescription(items);
|
||||||
}
|
}
|
||||||
const profilePromises = crime.slots.map(slot =>
|
const profilePromises = crime.slots.map(slot =>
|
||||||
torn.user.profile(slot.user.id).then(profile => ({
|
torn.user.profile(slot.user.id).then(profile => ({
|
||||||
name: profile.name,
|
name: profile.name,
|
||||||
value: `Pass rate: ${slot.checkpoint_pass_rate}`,
|
value: `Pass rate: ${slot.checkpoint_pass_rate}`,
|
||||||
@@ -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
551
torn.js
@@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user