UNPKG

cs2schema

Version:

A TypeScript SDK for Counter-Strike 2 schema data with ID/name resolution utilities

321 lines (320 loc) 12.1 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.CS2SchemaSDK = void 0; const fs_1 = require("fs"); const path_1 = require("path"); class CS2SchemaSDK { constructor(schemaPath) { this.nameToIdMaps = new Map(); this.searchCache = new Map(); this.initialized = false; this.categories = [ "stickers", "keychains", "collectibles", "containers", "agents", "custom_stickers", "music_kits", "weapons", ]; const defaultPath = schemaPath || (0, path_1.join)(__dirname, "..", "schema.json"); const resolvedPath = defaultPath; try { const schemaData = (0, fs_1.readFileSync)(resolvedPath, "utf-8"); this.schema = JSON.parse(schemaData); this.processedSchema = this.processSchema(this.schema); this.buildNameToIdMaps(); this.initialized = true; } catch (error) { throw new Error(`Failed to load schema from ${resolvedPath}: ${error}`); } } processSchema(schema) { const processed = JSON.parse(JSON.stringify(schema)); const processedWeapons = {}; Object.entries(schema.weapons).forEach(([weaponId, weapon]) => { Object.entries(weapon.paints).forEach(([paintId, paint]) => { const compositeId = `${weaponId}-${paintId}`; const weaponName = weapon.type === "Knives" ? `★ ${weapon.name}` : weapon.name; processedWeapons[compositeId] = { ...paint, market_hash_name: `${weaponName} | ${paint.name}`, }; }); }); processed.weapons = processedWeapons; return processed; } buildNameToIdMaps() { this.categories.forEach((category) => { const nameToIdMap = new Map(); const categoryData = this.processedSchema[category]; if (categoryData) { Object.entries(categoryData).forEach(([id, item]) => { if (item && typeof item === "object" && "market_hash_name" in item) { const name = item.market_hash_name.toLowerCase(); nameToIdMap.set(name, id); } }); } this.nameToIdMaps.set(category, nameToIdMap); }); } clearCache() { this.searchCache.clear(); } searchItems(query, options = {}) { if (!this.initialized) { throw new Error("SDK not properly initialized"); } const cacheKey = `${query}:${JSON.stringify(options)}`; if (this.searchCache.has(cacheKey)) { return this.searchCache.get(cacheKey); } const { caseSensitive = false, category, exactMatch = false } = options; const results = []; const searchQuery = caseSensitive ? query : query.toLowerCase(); const categoriesToSearch = category ? [category] : this.categories; categoriesToSearch.forEach((cat) => { const categoryData = this.processedSchema[cat]; if (!categoryData) return; Object.entries(categoryData).forEach(([id, item]) => { if (item && typeof item === "object" && "market_hash_name" in item) { const itemName = caseSensitive ? item.market_hash_name : item.market_hash_name.toLowerCase(); const match = exactMatch ? itemName === searchQuery : itemName.includes(searchQuery); if (match) { results.push({ id, item: item, category: cat, }); } } }); }); this.searchCache.set(cacheKey, results); return results; } resolveIdToName(id, category) { if (!this.initialized) { throw new Error("SDK not properly initialized"); } const categoryData = this.processedSchema[category]; if (!categoryData || !(id in categoryData)) { return null; } const item = categoryData[id]; return item && typeof item === "object" && "market_hash_name" in item ? item.market_hash_name : null; } resolveNameToId(name, category, options = {}) { if (!this.initialized) { throw new Error("SDK not properly initialized"); } const { caseSensitive = false, exactMatch = true } = options; const nameToIdMap = this.nameToIdMaps.get(category); if (!nameToIdMap) { return null; } const searchName = caseSensitive ? name : name.toLowerCase(); if (exactMatch) { return nameToIdMap.get(searchName) || null; } for (const [itemName, id] of nameToIdMap) { if (itemName.includes(searchName)) { return id; } } return null; } getItemById(id, category) { if (!this.initialized) { throw new Error("SDK not properly initialized"); } const categoryData = this.processedSchema[category]; if (!categoryData || !(id in categoryData)) { return null; } const item = categoryData[id]; return { id, item, category, }; } getItemByName(name, category, options = {}) { const id = this.resolveNameToId(name, category, options); if (!id) { return null; } return this.getItemById(id, category); } searchSkins(query, options = {}) { if (!this.initialized) { throw new Error("SDK not properly initialized"); } const results = this.searchItems(query, { ...options, category: "weapons", }); return results.map((result) => { const [weaponId] = result.id.split("-"); return { ...result, weaponId: weaponId || "", }; }); } getCollections() { if (!this.initialized) { throw new Error("SDK not properly initialized"); } return this.schema.collections || []; } getRarities() { if (!this.initialized) { throw new Error("SDK not properly initialized"); } return this.schema.rarities || []; } getCollectionByKey(key) { const collections = this.getCollections(); return collections.find((col) => col.key === key) || null; } getRarityByKey(key) { const rarities = this.getRarities(); return rarities.find((rarity) => rarity.key === key) || null; } getAllItemsInCategory(category) { if (!this.initialized) { throw new Error("SDK not properly initialized"); } const categoryData = this.processedSchema[category]; if (!categoryData) { return []; } return Object.entries(categoryData).map(([id, item]) => ({ id, item: item, category, })); } getCategoryStats() { if (!this.initialized) { throw new Error("SDK not properly initialized"); } const stats = {}; this.categories.forEach((category) => { const categoryData = this.processedSchema[category]; stats[category] = categoryData ? Object.keys(categoryData).length : 0; }); return stats; } isInitialized() { return this.initialized; } getSchema() { if (!this.initialized) { throw new Error("SDK not properly initialized"); } return this.processedSchema; } getAllCharmNames() { if (!this.initialized) { throw new Error("SDK not properly initialized"); } const keychainData = this.processedSchema.keychains; if (!keychainData) { return []; } return Object.values(keychainData) .filter((item) => item && typeof item === "object" && "market_hash_name" in item) .map((item) => item.market_hash_name); } getWeaponWearStates() { return [ { name: "Factory New", minFloat: 0.0, maxFloat: 0.07 }, { name: "Minimal Wear", minFloat: 0.07, maxFloat: 0.15 }, { name: "Field-Tested", minFloat: 0.15, maxFloat: 0.38 }, { name: "Well-Worn", minFloat: 0.38, maxFloat: 0.45 }, { name: "Battle-Scarred", minFloat: 0.45, maxFloat: 1.0 }, ]; } generateAllWeaponMarketHashNames(options = {}) { if (!this.initialized) { throw new Error("SDK not properly initialized"); } const { includeSouvenir = true, includeStatTrak = true, specificCollections, } = options; const wearStates = this.getWeaponWearStates(); const collections = this.getCollections(); const generatedNames = []; Object.entries(this.schema.weapons).forEach(([, weapon]) => { const weaponName = weapon.type === "Knives" ? `★ ${weapon.name}` : weapon.name; Object.entries(weapon.paints).forEach(([, paint]) => { const baseName = `${weaponName} | ${paint.name}`; const collection = paint.collection; if (specificCollections && collection && !specificCollections.includes(collection)) { return; } const collectionData = collections.find((col) => col.key === collection); const isSouvenirEligible = collectionData?.has_souvenir || false; wearStates.forEach((wearState) => { const fullName = `${baseName} (${wearState.name})`; generatedNames.push({ baseName, wearState: wearState.name, fullName, minFloat: wearState.minFloat, maxFloat: wearState.maxFloat, collection, isSouvenir: false, }); if (includeStatTrak) { const statTrakName = `StatTrak™ ${fullName}`; generatedNames.push({ baseName: `StatTrak™ ${baseName}`, wearState: wearState.name, fullName: statTrakName, minFloat: wearState.minFloat, maxFloat: wearState.maxFloat, collection, isSouvenir: false, }); } if (includeSouvenir && isSouvenirEligible) { const souvenirName = `Souvenir ${fullName}`; generatedNames.push({ baseName: `Souvenir ${baseName}`, wearState: wearState.name, fullName: souvenirName, minFloat: wearState.minFloat, maxFloat: wearState.maxFloat, collection, isSouvenir: true, }); } }); }); }); return generatedNames; } generateWeaponMarketHashNamesByCollection(collectionKey, options = {}) { return this.generateAllWeaponMarketHashNames({ ...options, specificCollections: [collectionKey], }); } } exports.CS2SchemaSDK = CS2SchemaSDK;