This repository has been archived by the owner on Aug 5, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
6 changed files
with
753 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
.idea/ | ||
node_modules/ | ||
items_game.txt | ||
csgo_english.txt | ||
config.js |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
module.exports = { | ||
port: 80, | ||
// amount of seconds between updating game files | ||
file_update_interval: 30 * 60 * 1000, | ||
// postgres connection string | ||
connectionString: '<POSTGRES_CONNECTION>' | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
const config = require('./config'); | ||
const vdf = require('simple-vdf'); | ||
const fs = require('fs'); | ||
const express = require('express'); | ||
const fetch = require('node-fetch'); | ||
const { Pool } = require('pg'); | ||
const ItemParser = require('./item_parser'); | ||
const app = express(); | ||
|
||
const pool = new Pool({ | ||
connectionString: config.connectionString, | ||
}); | ||
|
||
let itemParser; | ||
|
||
const itemUrl = `https://raw.githubusercontent.com/SteamDatabase/GameTracking-CSGO/master/csgo/scripts/items/items_game.txt`; | ||
const englishUrl = `https://raw.githubusercontent.com/SteamDatabase/GameTracking-CSGO/master/csgo/resource/csgo_english.txt`; | ||
|
||
async function updateItems() { | ||
try { | ||
const resp = await fetch(itemUrl); | ||
const data = await resp.text(); | ||
fs.writeFile('items_game.txt', data, () => { | ||
console.log('Saved items_game.txt'); | ||
}); | ||
|
||
const langResp = await fetch(englishUrl); | ||
const langData = await langResp.text(); | ||
fs.writeFile('csgo_english.txt', langData, () => { | ||
console.log('Saved csgo_english.txt'); | ||
}); | ||
|
||
itemParser = new ItemParser(vdf.parse(data).items_game, vdf.parse(langData).lang.Tokens); | ||
} catch (e) { | ||
console.error(e); | ||
} | ||
} | ||
|
||
if (fs.existsSync('items_game.txt') && fs.existsSync('items_game.txt')) { | ||
const itemsGame = fs.readFileSync('items_game.txt', 'utf8'); | ||
itemParser = new ItemParser(vdf.parse(itemsGame)['items_game']); | ||
|
||
const english = fs.readFileSync('csgo_english.txt', 'utf8'); | ||
itemParser = new ItemParser(vdf.parse(itemsGame).items_game, vdf.parse(english).lang.Tokens); | ||
} else { | ||
updateItems(); | ||
} | ||
|
||
setInterval(() => updateItems(), config.file_update_interval); | ||
|
||
|
||
app.get('/items', (req, res) => { | ||
if (itemParser) { | ||
res.json(itemParser.getFullResponse()); | ||
} else { | ||
res.status(500).json({error: 'Item response is not initialized, new csgo update?'}); | ||
} | ||
}); | ||
|
||
/* | ||
Possible URL Query Params | ||
defIndex: Weapon index | ||
paintIndex: Paint index | ||
order: 1 for asc, -1 for desc | ||
stattrak: true/false | ||
souvenir: true/false | ||
TODO: Implement support for stickers | ||
*/ | ||
function buildQuery(params) { | ||
const conditions = [], values = []; | ||
|
||
if (params.defIndex) { | ||
conditions.push(`defindex = $${conditions.length+1}`); | ||
values.push(params.defIndex); | ||
} | ||
|
||
if (params.paintIndex) { | ||
conditions.push(`paintindex = $${conditions.length+1}`); | ||
values.push(params.paintIndex); | ||
} | ||
|
||
if (params.stattrak) { | ||
conditions.push(`stattrak = $${conditions.length+1}`); | ||
values.push(params.stattrak); | ||
} | ||
|
||
if (params.souvenir) { | ||
conditions.push(`souvenir = $${conditions.length+1}`); | ||
values.push(params.souvenir); | ||
} | ||
|
||
let statement; | ||
if (conditions.length > 0) { | ||
statement = `SELECT * FROM items ORDER BY paintwear ${params.order === -1 ? 'DESC' : ''} LIMIT 200`; | ||
} else { | ||
statement = `SELECT * FROM items ${conditions.length > 0 ? 'WHERE' : ''} ${conditions.join(' AND ')} | ||
ORDER BY paintwear ${params.order === -1 ? 'DESC' : ''} LIMIT 200`; | ||
} | ||
|
||
return { | ||
text: statement, | ||
values | ||
} | ||
} | ||
|
||
app.get('/search', async (req, res) => { | ||
const query = buildQuery(req.params); | ||
|
||
try { | ||
const results = await pool.query(query); | ||
res.json(results.rows); | ||
} catch (e) { | ||
console.error(e); | ||
res.status(400).json({error: 'Something went wrong'}); | ||
} | ||
}); | ||
|
||
app.listen(config.port, () => console.log(`Listening on Port ${config.port}`)); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,129 @@ | ||
class ItemParser { | ||
constructor(itemsGame, language) { | ||
this.itemsGame = itemsGame; | ||
this.language = language; | ||
} | ||
|
||
_getPrefabStickerAmount(prefabName) { | ||
const prefab = this.itemsGame.prefabs[prefabName]; | ||
return Object.keys(prefab.stickers || {}).length; | ||
} | ||
|
||
_isWeapon(prefabName) { | ||
const prefab = this.itemsGame.prefabs[prefabName]; | ||
const usedClasses = prefab && prefab.used_by_classes; | ||
|
||
return usedClasses && (usedClasses['terrorists'] || usedClasses['counter-terrorists']); | ||
} | ||
|
||
_getWeapons() { | ||
const weapons = {}; | ||
for (const defIndex in this.itemsGame.items) { | ||
const item = this.itemsGame.items[defIndex]; | ||
if (item.prefab && this._isWeapon(item.prefab)) { | ||
weapons[defIndex] = item; | ||
} | ||
} | ||
|
||
return weapons; | ||
} | ||
|
||
_getWeaponLanguageName(defIndex) { | ||
const item = this.itemsGame.items[defIndex]; | ||
|
||
if (item.item_name) { | ||
return this._getLanguageValue(item.item_name); | ||
} else { | ||
const prefab = this.itemsGame.prefabs[item.prefab]; | ||
return this._getLanguageValue(prefab.item_name); | ||
} | ||
} | ||
|
||
_getPaintKitIndex(name) { | ||
return Object.keys(this.itemsGame.paint_kits).find((paintIndex) => { | ||
const kit = this.itemsGame.paint_kits[paintIndex]; | ||
|
||
if (kit.name === name) { | ||
return true; | ||
} | ||
}) | ||
} | ||
|
||
_getLanguageValue(token) { | ||
return this.language[token.replace('#', '')]; | ||
} | ||
|
||
_getWeaponPaints(weaponName) { | ||
const paints = {}; | ||
|
||
for (const setName of Object.keys(this.itemsGame.item_sets)) { | ||
const setItems = Object.keys(this.itemsGame.item_sets[setName].items); | ||
|
||
for (const setItem of setItems) { | ||
if (setItem.indexOf(weaponName) === -1) continue; | ||
|
||
const paintName = setItem.match(/\[(.*)].*/)[1]; | ||
|
||
const index = this._getPaintKitIndex(paintName); | ||
|
||
if (index) { | ||
const kit = this.itemsGame.paint_kits[index]; | ||
paints[index] = { | ||
name: this._getLanguageValue(kit.description_tag), | ||
min: parseFloat(kit.wear_remap_min || 0.06), | ||
max: parseFloat(kit.wear_remap_max || 0.80), | ||
}; | ||
} | ||
|
||
} | ||
} | ||
|
||
return paints; | ||
} | ||
|
||
getStickers() { | ||
const stickers = {}; | ||
|
||
for (const stickerId of Object.keys(this.itemsGame.sticker_kits)) { | ||
if (stickerId == '0') continue; | ||
|
||
const sticker = this.itemsGame.sticker_kits[stickerId]; | ||
|
||
stickers[stickerId] = this._getLanguageValue(sticker.item_name) | ||
} | ||
|
||
return stickers; | ||
} | ||
|
||
getFullResponse() { | ||
if (this.resp) return this.resp; | ||
|
||
const resp = {}; | ||
|
||
const weapons = this._getWeapons(); | ||
|
||
const weaponsResp = {}; | ||
|
||
for (const defIndex of Object.keys(weapons)) { | ||
const weapon = weapons[defIndex]; | ||
const paints = this._getWeaponPaints(weapon.name); | ||
|
||
if (Object.keys(paints).length === 0) continue; | ||
|
||
weaponsResp[defIndex] = { | ||
name: this._getWeaponLanguageName(defIndex), | ||
stickerAmount: this._getPrefabStickerAmount(weapon.prefab), | ||
paints | ||
}; | ||
} | ||
|
||
resp.weapons = weaponsResp; | ||
resp.stickers = this.getStickers(); | ||
|
||
this.resp = resp; | ||
|
||
return resp; | ||
} | ||
} | ||
|
||
module.exports = ItemParser; |
Oops, something went wrong.