You've already forked tf2wikipricing
bump version to 0.5.0
- Adds festive & botkiller pricing - Script retries if API is hit too frequently
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { describe, expect, test, mock } from "bun:test";
|
||||
import { ItemSchema, ItemSlot, getItemIndexByName, getTradableStatusByDefindex, getTradableStatusByName, prepareSchema } from '../src/content/schemaService'
|
||||
import { ItemSchema, ItemSlot, getItemIndexByName, getTradableStatusByDefindex, getTradableStatusByName, linkBotkillerVariants, linkFestiveVariants, prepareSchema } from '../src/content/schemaService'
|
||||
|
||||
// Mock the storage and log functions
|
||||
mock.module('../src/content/storage', () => ({
|
||||
@@ -19,35 +19,72 @@ const mockSchema: ItemSchema = {
|
||||
slot: ItemSlot.Primary,
|
||||
tradable: false,
|
||||
hasAustraliumVariant: false,
|
||||
canKillstreakify: true
|
||||
canKillstreakify: true,
|
||||
festiveVariant: null,
|
||||
botkillerVariants: null
|
||||
},
|
||||
'208': {
|
||||
name: 'Flame Thrower',
|
||||
slot: ItemSlot.Primary,
|
||||
tradable: true,
|
||||
hasAustraliumVariant: true,
|
||||
canKillstreakify: true
|
||||
canKillstreakify: true,
|
||||
festiveVariant: 659,
|
||||
botkillerVariants: [798, 807]
|
||||
},
|
||||
'659': {
|
||||
name: 'Festive Flame Thrower',
|
||||
slot: ItemSlot.Primary,
|
||||
tradable: true,
|
||||
hasAustraliumVariant: false,
|
||||
canKillstreakify: true,
|
||||
festiveVariant: null,
|
||||
botkillerVariants: null
|
||||
},
|
||||
'798': {
|
||||
name: 'Silver Botkiller Flame Thrower Mk.I',
|
||||
slot: ItemSlot.Primary,
|
||||
tradable: true,
|
||||
hasAustraliumVariant: false,
|
||||
canKillstreakify: true,
|
||||
festiveVariant: null,
|
||||
botkillerVariants: null
|
||||
},
|
||||
'807': {
|
||||
name: 'Gold Botkiller Flame Thrower Mk.I',
|
||||
slot: ItemSlot.Primary,
|
||||
tradable: true,
|
||||
hasAustraliumVariant: false,
|
||||
canKillstreakify: true,
|
||||
festiveVariant: null,
|
||||
botkillerVariants: null
|
||||
},
|
||||
'5021': {
|
||||
name: 'Mann Co. Supply Crate Key',
|
||||
slot: ItemSlot.Tool,
|
||||
tradable: true,
|
||||
hasAustraliumVariant: false,
|
||||
canKillstreakify: false
|
||||
canKillstreakify: false,
|
||||
festiveVariant: null,
|
||||
botkillerVariants: null
|
||||
},
|
||||
'15141': {
|
||||
name: 'Flame Thrower',
|
||||
slot: ItemSlot.Primary,
|
||||
tradable: true,
|
||||
hasAustraliumVariant: false,
|
||||
canKillstreakify: true
|
||||
canKillstreakify: true,
|
||||
festiveVariant: null,
|
||||
botkillerVariants: null
|
||||
},
|
||||
'69420': {
|
||||
name: 'Non-Tradable Item',
|
||||
slot: ItemSlot.Misc,
|
||||
tradable: false,
|
||||
hasAustraliumVariant: false,
|
||||
canKillstreakify: false
|
||||
canKillstreakify: false,
|
||||
festiveVariant: null,
|
||||
botkillerVariants: null
|
||||
}
|
||||
}
|
||||
|
||||
@@ -117,4 +154,187 @@ describe('Schema Service', () => {
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe('linkFestiveVariants', () => {
|
||||
test('should link festive variants to their original counterparts', () => {
|
||||
const testSchema = {
|
||||
'21': { // Stock (should be ignored)
|
||||
name: 'Flame Thrower',
|
||||
slot: ItemSlot.Primary,
|
||||
tradable: false,
|
||||
hasAustraliumVariant: false,
|
||||
canKillstreakify: false,
|
||||
festiveVariant: null,
|
||||
botkillerVariants: null
|
||||
},
|
||||
'208': { // Original Flame Thrower
|
||||
name: 'Flame Thrower',
|
||||
slot: ItemSlot.Primary,
|
||||
tradable: true,
|
||||
hasAustraliumVariant: true,
|
||||
canKillstreakify: true,
|
||||
festiveVariant: null,
|
||||
botkillerVariants: null
|
||||
},
|
||||
'659': { // Festive Flame Thrower (should be detected)
|
||||
name: 'Festive Flame Thrower',
|
||||
slot: ItemSlot.Primary,
|
||||
tradable: true,
|
||||
hasAustraliumVariant: false,
|
||||
canKillstreakify: true,
|
||||
festiveVariant: null,
|
||||
botkillerVariants: null
|
||||
},
|
||||
'15141': { // Decorated (should be ignored)
|
||||
name: 'Flame Thrower',
|
||||
slot: ItemSlot.Primary,
|
||||
tradable: true,
|
||||
hasAustraliumVariant: false,
|
||||
canKillstreakify: true,
|
||||
festiveVariant: null,
|
||||
botkillerVariants: null
|
||||
}
|
||||
};
|
||||
const mockResponseItems = [
|
||||
{ item_class: 'tf_weapon_flamethrower', defindex: 21, item_name: 'Flame Thrower' }, // Incorrect; stock
|
||||
{ item_class: 'tf_weapon_flamethrower', defindex: 208, item_name: 'Flame Thrower' }, // Original
|
||||
{ item_class: 'tf_weapon_flamethrower', defindex: 659, item_name: 'Festive Flame Thrower' }, // Festive
|
||||
{ item_class: 'tf_weapon_flamethrower', defindex: 15141, item_name: 'Flame Thrower' }, // Incorrect; decorated
|
||||
];
|
||||
linkFestiveVariants(mockResponseItems, testSchema)
|
||||
expect(testSchema['21'].festiveVariant).toBeNull()
|
||||
expect(testSchema['208'].festiveVariant).toBe(659)
|
||||
expect(testSchema['659'].festiveVariant).toBeNull();
|
||||
expect(testSchema['15141'].festiveVariant).toBeNull()
|
||||
})
|
||||
|
||||
test('should not link if no festive variant exists', () => {
|
||||
const testSchema = {
|
||||
'163': {
|
||||
name: 'Crit-a-Cola',
|
||||
slot: ItemSlot.Secondary,
|
||||
tradable: true,
|
||||
hasAustraliumVariant: false,
|
||||
canKillstreakify: false,
|
||||
festiveVariant: null,
|
||||
botkillerVariants: null
|
||||
}
|
||||
};
|
||||
|
||||
const mockResponseItems = [
|
||||
{ item_class: 'tf_weapon_lunchbox_drink', defindex: 163, item_name: 'Crit-a-Cola' }
|
||||
];
|
||||
|
||||
linkFestiveVariants(mockResponseItems, testSchema);
|
||||
|
||||
expect(testSchema['163'].festiveVariant).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
describe('linkBotkillerVariants', () => {
|
||||
test('should link botkiller variants to their original counterparts', () => {
|
||||
const testSchema = {
|
||||
'21': { // Original Rocket Launcher
|
||||
name: 'Flame Thrower',
|
||||
slot: ItemSlot.Primary,
|
||||
tradable: false,
|
||||
hasAustraliumVariant: false,
|
||||
canKillstreakify: false,
|
||||
festiveVariant: null,
|
||||
botkillerVariants: null
|
||||
},
|
||||
'208': { // Original Flame Thrower
|
||||
name: 'Flame Thrower',
|
||||
slot: ItemSlot.Primary,
|
||||
tradable: true,
|
||||
hasAustraliumVariant: true,
|
||||
canKillstreakify: true,
|
||||
festiveVariant: null,
|
||||
botkillerVariants: null
|
||||
},
|
||||
'798': {
|
||||
name: 'Silver Botkiller Flame Thrower Mk. I',
|
||||
slot: ItemSlot.Primary,
|
||||
tradable: true,
|
||||
hasAustraliumVariant: false,
|
||||
canKillstreakify: true,
|
||||
festiveVariant: null,
|
||||
botkillerVariants: null
|
||||
},
|
||||
'807': {
|
||||
name: 'Gold Botkiller Flame Thrower Mk. I',
|
||||
slot: ItemSlot.Primary,
|
||||
tradable: true,
|
||||
hasAustraliumVariant: false,
|
||||
canKillstreakify: true,
|
||||
festiveVariant: null,
|
||||
botkillerVariants: null
|
||||
},
|
||||
'15141': { // Decorated (should be ignored)
|
||||
name: 'Flame Thrower',
|
||||
slot: ItemSlot.Primary,
|
||||
tradable: true,
|
||||
hasAustraliumVariant: false,
|
||||
canKillstreakify: true,
|
||||
festiveVariant: null,
|
||||
botkillerVariants: null
|
||||
}
|
||||
};
|
||||
const mockResponseItems = [
|
||||
{ item_class: 'tf_weapon_flamethrower', defindex: 21, item_name: 'Flame Thrower', item_type_name: 'Flame Thrower'
|
||||
}, // Incorrect; stock
|
||||
{
|
||||
item_class: 'tf_weapon_flamethrower',
|
||||
defindex: 208,
|
||||
item_name: 'Flame Thrower',
|
||||
item_type_name: 'Flame Thrower'
|
||||
},
|
||||
{
|
||||
item_class: 'tf_weapon_flamethrower',
|
||||
defindex: 798,
|
||||
item_name: 'Silver Botkiller Flame Thrower Mk.I',
|
||||
item_type_name: 'Flame Thrower'
|
||||
},
|
||||
{
|
||||
item_class: 'tf_weapon_flamethrower',
|
||||
defindex: 807,
|
||||
item_name: 'Gold Botkiller Flame Thrower Mk.I',
|
||||
item_type_name: 'Flame Thrower'
|
||||
},
|
||||
{ item_class: 'tf_weapon_flamethrower', defindex: 15141, item_name: 'Flame Thrower', item_type_name: 'Flame Thrower' }, // Incorrect; decorated
|
||||
];
|
||||
linkBotkillerVariants(mockResponseItems, testSchema);
|
||||
expect(testSchema['21'].botkillerVariants).toBeNull()
|
||||
expect(testSchema['208'].botkillerVariants).toEqual([798, 807]);
|
||||
expect(testSchema['798'].botkillerVariants).toBeNull();
|
||||
expect(testSchema['807'].botkillerVariants).toBeNull();
|
||||
expect(testSchema['15141'].botkillerVariants).toBeNull()
|
||||
});
|
||||
|
||||
test('should not link if no botkiller variants exist', () => {
|
||||
const testSchema = {
|
||||
'163': { // Crit-a-Cola
|
||||
name: 'Crit-a-Cola',
|
||||
slot: ItemSlot.Secondary,
|
||||
tradable: true,
|
||||
hasAustraliumVariant: false,
|
||||
festiveVariant: null,
|
||||
canKillstreakify: false,
|
||||
botkillerVariants: null,
|
||||
}
|
||||
};
|
||||
|
||||
const mockResponseItems = [
|
||||
{
|
||||
item_class: 'tf_weapon_lunchbox_drink',
|
||||
defindex: 163,
|
||||
item_name: 'Crit-a-Cola',
|
||||
item_type_name: 'Lunch Box',
|
||||
}
|
||||
];
|
||||
|
||||
linkBotkillerVariants(mockResponseItems, testSchema);
|
||||
expect(testSchema['163'].botkillerVariants).toBeNull();
|
||||
});
|
||||
})
|
||||
})
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "tf2wikipricing",
|
||||
"version": "0.4.1",
|
||||
"version": "0.5.0",
|
||||
"description": "Adds item pricing to the Team Fortress 2 wiki",
|
||||
"devDependencies": {
|
||||
"@happy-dom/global-registrator": "^17.4.4",
|
||||
|
||||
@@ -187,9 +187,16 @@ async function inject() {
|
||||
|
||||
var updateTime: Date | null = null;
|
||||
|
||||
enum PriceRowCategory {
|
||||
None,
|
||||
Festive,
|
||||
Botkiller
|
||||
}
|
||||
|
||||
interface PriceRow {
|
||||
quality: number
|
||||
order: number
|
||||
row: HTMLTableRowElement
|
||||
category: PriceRowCategory
|
||||
}
|
||||
var priceRows: PriceRow[]= [];
|
||||
|
||||
@@ -214,7 +221,7 @@ async function inject() {
|
||||
const qualityName = itemQualities[quality as unknown as keyof typeof itemQualities].toString()
|
||||
const priceRow = createPriceRow(qualityName, data, keyPrice, locale)
|
||||
|
||||
priceRows.push({quality: quality, row: priceRow})
|
||||
priceRows.push({order: quality == 6 ? -1 : quality, row: priceRow, category: PriceRowCategory.None})
|
||||
})
|
||||
|
||||
// Check item schema for Australium variant of current defindex
|
||||
@@ -231,24 +238,128 @@ async function inject() {
|
||||
|
||||
const priceRow = createPriceRow($T("Australium"), data, keyPrice, locale, "https://wiki.teamfortress.com/wiki/Australium_weapons")
|
||||
|
||||
priceRows.push({quality: 99, row: priceRow})
|
||||
priceRows.push({order: 99, row: priceRow, category: PriceRowCategory.None})
|
||||
resolve()
|
||||
return
|
||||
}))
|
||||
}
|
||||
|
||||
var festiveHeadingRow: HTMLTableRowElement | null
|
||||
// Check item schema for Festive variant of current defindex
|
||||
if(itemSchema[itemIndex].festiveVariant != null) {
|
||||
/// Create subheading
|
||||
festiveHeadingRow = document.createElement("tr")
|
||||
const festiveHeading = document.createElement("th")
|
||||
festiveHeading.className = "infobox-subheader"
|
||||
festiveHeading.colSpan = 2
|
||||
festiveHeading.innerText = $T("Festive")
|
||||
festiveHeading.style.fontSize = '1em';
|
||||
festiveHeading.style.backgroundColor = '#F5C087';
|
||||
festiveHeadingRow.appendChild(festiveHeading);
|
||||
|
||||
promises.push(new Promise(async (resolve) => {
|
||||
logDebug(`Fetching price for Festive ${itemName}`)
|
||||
var data: ItemPriceData | null
|
||||
try {
|
||||
data = await fetchPrice(token, `${itemSchema[itemIndex].festiveVariant};6`, currentTime);
|
||||
updateTime = new Date(data.update)
|
||||
} catch {
|
||||
log(`Festive ${itemName} is unpriced or unavailable, skipping...`)
|
||||
}
|
||||
|
||||
const priceRow = createPriceRow($T("Unique"), data, keyPrice, locale)
|
||||
|
||||
priceRows.push({order: -1, row: priceRow, category: PriceRowCategory.Festive})
|
||||
resolve()
|
||||
return
|
||||
}))
|
||||
promises.push(new Promise(async (resolve) => {
|
||||
logDebug(`Fetching price for Strange Festive ${itemName}`)
|
||||
var data: ItemPriceData | null
|
||||
try {
|
||||
data = await fetchPrice(token, `${itemSchema[itemIndex].festiveVariant};11`, currentTime);
|
||||
updateTime = new Date(data.update)
|
||||
} catch {
|
||||
log(`Strange Festive ${itemName} is unpriced or unavailable, skipping...`)
|
||||
}
|
||||
|
||||
const priceRow = createPriceRow($T("Strange"), data, keyPrice, locale)
|
||||
|
||||
priceRows.push({order: 11, row: priceRow, category: PriceRowCategory.Festive})
|
||||
resolve()
|
||||
return
|
||||
}))
|
||||
}
|
||||
|
||||
// Silver Mk.I, Gold Mk.II, Rust, Blood, Carbonado, Diamond, Silver Mk.II, Gold Mk.II
|
||||
const botkillerOrder = [
|
||||
"Silver",
|
||||
"Gold",
|
||||
"Rust",
|
||||
"Blood",
|
||||
"Carbonado",
|
||||
"Diamond",
|
||||
"Silver Mk.II",
|
||||
"Gold Mk.II",
|
||||
]
|
||||
var botKillerHeadingRow: HTMLTableRowElement | null
|
||||
if(itemSchema[itemIndex].botkillerVariants != null && itemSchema[itemIndex].botkillerVariants.length > 0) {
|
||||
/// Create subheading
|
||||
botKillerHeadingRow = document.createElement("tr")
|
||||
const festiveHeading = document.createElement("th")
|
||||
festiveHeading.className = "infobox-subheader"
|
||||
festiveHeading.colSpan = 2
|
||||
festiveHeading.innerText = $T("Botkiller")
|
||||
festiveHeading.style.fontSize = '1em';
|
||||
festiveHeading.style.backgroundColor = '#F5C087';
|
||||
botKillerHeadingRow.appendChild(festiveHeading);
|
||||
|
||||
itemSchema[itemIndex].botkillerVariants.map((variantIndex) => {
|
||||
const itemName = itemSchema[variantIndex].name
|
||||
// FIXME: variantName should match wiki display name
|
||||
const variantName = itemName.includes('Mk.II') ? itemName.split(' ')[0] + ' Mk.II' : itemName.split(' ')[0]
|
||||
promises.push(new Promise(async (resolve) => {
|
||||
logDebug(`Fetching price for ${itemName}`)
|
||||
var data: ItemPriceData | null
|
||||
try {
|
||||
data = await fetchPrice(token, `${variantIndex};11`, currentTime);
|
||||
updateTime = new Date(data.update)
|
||||
} catch {
|
||||
log(`${itemName} is unpriced or unavailable, skipping...`)
|
||||
}
|
||||
|
||||
const priceRow = createPriceRow($T(variantName), data, keyPrice, locale, "https://wiki.teamfortress.com/wiki/Botkiller_weapons")
|
||||
|
||||
// FIXME: order should be by release
|
||||
// Silver Mk.I, Gold Mk.II, Rust, Blood, Carbonado, Diamond, Silver Mk.II, Gold Mk.II
|
||||
priceRows.push({order: botkillerOrder.indexOf(variantName), row: priceRow, category: PriceRowCategory.Botkiller})
|
||||
resolve()
|
||||
return
|
||||
}))
|
||||
})
|
||||
}
|
||||
|
||||
if(botKillerHeadingRow) priceInfoboxHeadingRow.insertAdjacentElement('afterend', botKillerHeadingRow);
|
||||
if(festiveHeadingRow) priceInfoboxHeadingRow.insertAdjacentElement('afterend', festiveHeadingRow);
|
||||
|
||||
Promise.all(promises).then(() => {
|
||||
priceRows.sort((a, b) => {
|
||||
// Sort 6 first always, then numerically
|
||||
if (a.quality === 6) {
|
||||
return -1;
|
||||
} else if (b.quality === 6) {
|
||||
return 1;
|
||||
} else {
|
||||
return a.quality == b.quality ? a.quality < b.quality ? -1 : 1 : 0;
|
||||
if (a.category != b.category) {
|
||||
return a.category - b.category;
|
||||
}
|
||||
return a.order - b.order;
|
||||
}).reverse().forEach((element) => {
|
||||
priceInfoboxHeadingRow.insertAdjacentElement('afterend', element.row);
|
||||
switch(element.category) {
|
||||
case PriceRowCategory.None:
|
||||
priceInfoboxHeadingRow.insertAdjacentElement('afterend', element.row);
|
||||
break;
|
||||
case PriceRowCategory.Festive:
|
||||
festiveHeadingRow.insertAdjacentElement('afterend', element.row);
|
||||
break;
|
||||
case PriceRowCategory.Botkiller:
|
||||
botKillerHeadingRow.insertAdjacentElement('afterend', element.row);
|
||||
break;
|
||||
}
|
||||
})
|
||||
if(!updateTime || !(updateTime instanceof Date) || isNaN(+updateTime)) updateTime = new Date()
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
declare function GM_fetch(input: string | URL | globalThis.Request, init?: RequestInit): Promise<Response>
|
||||
import '../GM_fetch'
|
||||
import { logDebug } from '../utils/log'
|
||||
|
||||
async function getPricesToken(): Promise<string> {
|
||||
return new Promise<any>((resolve, reject) => {
|
||||
@@ -37,7 +38,7 @@ class PricesResponse {
|
||||
* @returns {Promise<PricesResponse>} Object containing 'keys' and 'metal' prices
|
||||
* @throws When authentication fails or API returns non-200 status code
|
||||
*/
|
||||
async function priceUsingPricesTF(token: string, sku: string): Promise<PricesResponse> {
|
||||
async function priceUsingPricesTF(token: string, sku: string, retries: number = 3): Promise<PricesResponse> {
|
||||
// prices.tf
|
||||
// https://api2.prices.tf/prices/${sku}
|
||||
// Authorization: Bearer ${token}
|
||||
@@ -65,11 +66,37 @@ async function priceUsingPricesTF(token: string, sku: string): Promise<PricesRes
|
||||
})
|
||||
}
|
||||
}
|
||||
if (response.status === 200) {
|
||||
const json = await response.json()
|
||||
resolve({ keys: json['sellKeys'], metal: json['sellHalfScrap'] / 18.0 })
|
||||
} else {
|
||||
reject(response.status)
|
||||
switch (response.status) {
|
||||
case 200:
|
||||
const json = await response.json()
|
||||
resolve({ keys: json['sellKeys'], metal: json['sellHalfScrap'] / 18.0 })
|
||||
break;
|
||||
case 404:
|
||||
reject("Not found in prices.tf")
|
||||
break;
|
||||
case 429:
|
||||
case 503:
|
||||
// Happens if we send too many requests in a short period of time
|
||||
// Retry after a few seconds
|
||||
if(retries > 0) {
|
||||
logDebug(`Cloudflare rate limit exceeded, trying again after 2 seconds, ${retries} retries left`)
|
||||
await new Promise(resolve => setTimeout(resolve, 2000));
|
||||
try {
|
||||
const retryResult = await priceUsingPricesTF(token, sku, retries - 1);
|
||||
resolve(retryResult);
|
||||
} catch (err) {
|
||||
reject(err);
|
||||
}
|
||||
} else {
|
||||
reject("Cloudflare rate limit exceeded, stopping")
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// Something went wrong
|
||||
logDebug(`Received ${response.status} error while pricing ${sku}`)
|
||||
logDebug(`${JSON.stringify(response.headers)}`)
|
||||
reject("Unknown error")
|
||||
break;
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -38,6 +38,8 @@ export class ItemSchema {
|
||||
slot: ItemSlot,
|
||||
tradable: Boolean,
|
||||
hasAustraliumVariant: Boolean,
|
||||
festiveVariant: number | null
|
||||
botkillerVariants: Array<number> | null
|
||||
canKillstreakify: Boolean
|
||||
};
|
||||
}
|
||||
@@ -70,6 +72,45 @@ export function getTradableStatusByName(schema: ItemSchema, name: string, exclud
|
||||
return true
|
||||
}
|
||||
|
||||
export function linkFestiveVariants(items: Array<{item_class: string, defindex: number, item_name: string}>, schema: ItemSchema): void {
|
||||
if(!schema) return
|
||||
items.filter(item =>
|
||||
item.item_class != null &&
|
||||
item.item_class.startsWith('tf_weapon') &&
|
||||
item.item_name.startsWith('Festive ')
|
||||
).forEach(festive => {
|
||||
const originalName = festive.item_name.slice(8); // "Festive " is 8 chars
|
||||
const original = items.find(item => item.item_name === originalName && item.defindex > 30 && (item.defindex < 15000 || item.defindex >= 16000));
|
||||
|
||||
if (original) {
|
||||
if(schema[original.defindex]) {
|
||||
schema[original.defindex].festiveVariant = festive.defindex;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export function linkBotkillerVariants(items: Array<{item_class: string, defindex: number, item_name: string, item_type_name: string}>, schema: ItemSchema): void {
|
||||
if(!schema) return
|
||||
items.filter(item =>
|
||||
item.item_class != null &&
|
||||
item.item_class.startsWith('tf_weapon') &&
|
||||
item.item_name.includes('Botkiller')
|
||||
).forEach(botkiller => {
|
||||
const originalName = botkiller.item_type_name
|
||||
const original = items.find(item => item.item_name === originalName && item.defindex > 30 && (item.defindex < 15000 || item.defindex >= 16000));
|
||||
if (original) {
|
||||
if(schema[original.defindex]) {
|
||||
if(schema[original.defindex].botkillerVariants == null) {
|
||||
// init array
|
||||
schema[original.defindex].botkillerVariants = new Array<number>()
|
||||
}
|
||||
schema[original.defindex].botkillerVariants.push(botkiller.defindex)
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export async function wipeSchema(): Promise<void> {
|
||||
await setStorageValue(storage_version, __VERSION__)
|
||||
await setStorageValue(storage_schema, null)
|
||||
@@ -149,6 +190,9 @@ export async function prepareSchema(): Promise<ItemSchema> {
|
||||
}
|
||||
});
|
||||
|
||||
linkFestiveVariants(responseItems, cacheItems)
|
||||
linkBotkillerVariants(responseItems, cacheItems)
|
||||
|
||||
await setStorageValue(storage_schema, (cacheItems));
|
||||
itemSchema = cacheItems
|
||||
await setStorageValue(storage_version, __VERSION__);
|
||||
|
||||
@@ -22,5 +22,17 @@ module.exports = {
|
||||
"Strange": "Strange",
|
||||
"Collector's": "Collector's",
|
||||
"Haunted": "Haunted",
|
||||
"Australium": "Australium"
|
||||
"Australium": "Australium",
|
||||
"Festive": "Festive",
|
||||
|
||||
// Botkiller names, all sourced from TF2 wiki
|
||||
"Botkiller": "Botkiller",
|
||||
"Silver": "Silver",
|
||||
"Gold": "Gold",
|
||||
"Rust": "Rust",
|
||||
"Blood": "Blood",
|
||||
"Carbonado": "Carbonado",
|
||||
"Diamond": "Diamond",
|
||||
"Silver Mk.II": "Silver Mk.II",
|
||||
"Gold Mk.II": "Gold Mk.II",
|
||||
}
|
||||
@@ -22,5 +22,17 @@ module.exports = {
|
||||
"Strange": "de Calidad Rara",
|
||||
"Collector's": "de Coleccionista",
|
||||
"Haunted": "de Calidad Embrujada",
|
||||
"Australium": "de Australium"
|
||||
"Australium": "de Australium",
|
||||
"Festive": "Festiva",
|
||||
|
||||
// Botkiller names, all sourced from TF2 wiki
|
||||
"Botkiller": "Matabots",
|
||||
"Silver": "Plata",
|
||||
"Gold": "Oro",
|
||||
"Rust": "Oxidado",
|
||||
"Blood": "Sangriento",
|
||||
"Carbonado": "Carbonado",
|
||||
"Diamond": "Diamante",
|
||||
"Silver Mk.II": "Plata Mk.II",
|
||||
"Gold Mk.II": "Oro Mk.II",
|
||||
}
|
||||
Reference in New Issue
Block a user