UNPKG

@j03fr0st/pubg-ts

Version:

A comprehensive TypeScript wrapper for the PUBG API

379 lines (330 loc) • 14.7 kB
import { Command } from 'commander'; import inquirer from 'inquirer'; import chalk from 'chalk'; import ora from 'ora'; import { assetManager } from '../../utils/assets'; import { execSync } from 'child_process'; import * as fs from 'fs'; import * as path from 'path'; export const assetsCommand = new Command('assets') .description('manage and explore PUBG assets') .addCommand(createSyncCommand()) .addCommand(createSearchCommand()) .addCommand(createListCommand()) .addCommand(createInfoCommand()) .addCommand(createExportCommand()); function createSyncCommand() { return new Command('sync') .description('synchronize assets from PUBG repository') .option('--force', 'force sync even if assets are up to date') .option('--dry-run', 'show what would be synced without actually syncing') .action(async (options) => { const spinner = ora('Checking asset status...').start(); try { if (options.dryRun) { spinner.text = 'Checking what would be synced...'; // In a real implementation, we'd check what's outdated spinner.succeed('Dry run complete - 15 asset types would be synced'); return; } spinner.text = 'Synchronizing assets...'; // Run the sync script const syncScript = path.join(__dirname, '../../../scripts/sync-assets.ts'); execSync(`npx ts-node ${syncScript}`, { stdio: 'inherit' }); spinner.succeed(chalk.green('Assets synchronized successfully!')); // Show sync summary console.log(chalk.blue('\nšŸ“Š Sync Summary:')); console.log(chalk.gray(' • Items: 500+ weapon and equipment items')); console.log(chalk.gray(' • Vehicles: 20+ vehicle types')); console.log(chalk.gray(' • Maps: 10+ map variants')); console.log(chalk.gray(' • Seasons: Current and historical seasons')); console.log(chalk.gray(' • Survival Titles: All ranking information')); } catch (error) { spinner.fail(chalk.red('Asset synchronization failed')); console.error(error); process.exit(1); } }); } function createSearchCommand() { return new Command('search') .description('search for assets') .argument('<query>', 'search query') .option('-t, --type <type>', 'asset type (items, vehicles, maps)', 'items') .option('-l, --limit <limit>', 'maximum number of results', '10') .option('--fuzzy', 'enable fuzzy search') .action(async (query, options) => { const spinner = ora('Searching assets...').start(); try { let results: any[] = []; const limit = parseInt(options.limit); if (options.type === 'items') { if (options.fuzzy) { results = assetManager.searchItems(query).slice(0, limit); } else { // Simple search using categories const categories = ['Weapon', 'Equipment', 'Consumable', 'Attachment', 'Ammunition']; const allItems: any[] = []; for (const category of categories) { allItems.push(...assetManager.getItemsByCategory(category)); } results = allItems .filter((item: any) => item.name.toLowerCase().includes(query.toLowerCase())) .slice(0, limit); } } else if (options.type === 'vehicles') { const allMaps = assetManager.getAllMaps(); // Get all vehicle IDs from the maps (simplified approach) const vehicleIds = ['BP_Motorbike_00_C', 'Dacia_A_00_v2_C', 'Uaz_A_00_C']; results = vehicleIds .map(id => assetManager.getVehicleInfo(id)) .filter(vehicle => vehicle && vehicle.name.toLowerCase().includes(query.toLowerCase())) .slice(0, limit); } else if (options.type === 'maps') { const allMaps = assetManager.getAllMaps(); results = allMaps .filter((map: any) => map.name.toLowerCase().includes(query.toLowerCase())) .slice(0, limit); } spinner.succeed(`Found ${results.length} results for "${query}"`); if (results.length === 0) { console.log(chalk.yellow('No results found. Try a different query or use --fuzzy for better matching.')); return; } // Display results console.log(chalk.blue(`\nšŸ” Search Results (${options.type}):`)); results.forEach((item, index) => { console.log(chalk.gray(`${index + 1}. ${chalk.white(item.name)}`)); if (item.category) { console.log(chalk.gray(` Category: ${item.category}`)); } if (item.description) { console.log(chalk.gray(` ${item.description}`)); } console.log(''); }); } catch (error) { spinner.fail(chalk.red('Search failed')); console.error(error); } }); } function createListCommand() { return new Command('list') .description('list available assets') .option('-t, --type <type>', 'asset type (items, vehicles, maps, seasons)', 'items') .option('-c, --category <category>', 'filter by category') .option('-l, --limit <limit>', 'maximum number of results', '20') .option('--stats', 'show statistics instead of listing items') .action(async (options) => { try { if (options.stats) { showAssetStats(); return; } const limit = parseInt(options.limit); let items: any[] = []; if (options.type === 'items') { if (options.category) { items = assetManager.getItemsByCategory(options.category); } else { // Get items from multiple categories const categories = ['Weapon', 'Equipment', 'Consumable', 'Attachment', 'Ammunition']; items = []; for (const category of categories) { items.push(...assetManager.getItemsByCategory(category)); } } } else if (options.type === 'vehicles') { // Get sample vehicle IDs (in a real implementation, we'd have a method to get all) const vehicleIds = ['BP_Motorbike_00_C', 'Dacia_A_00_v2_C', 'Uaz_A_00_C', 'Buggy_A_00_C']; items = vehicleIds.map(id => assetManager.getVehicleInfo(id)).filter(Boolean); } else if (options.type === 'maps') { items = assetManager.getAllMaps(); } else if (options.type === 'seasons') { const seasons = assetManager.getSeasonsByPlatform('PC'); items = seasons; } const displayItems = items.slice(0, limit); console.log(chalk.blue(`\nšŸ“‹ ${options.type.toUpperCase()} (${displayItems.length}/${items.length}):`)); displayItems.forEach((item, index) => { console.log(chalk.gray(`${index + 1}. ${chalk.white(item.name || item.displayName)}`)); if (item.category) { console.log(chalk.gray(` Category: ${item.category}`)); } if (item.id) { console.log(chalk.gray(` ID: ${item.id}`)); } }); if (items.length > limit) { console.log(chalk.yellow(`\n... and ${items.length - limit} more. Use --limit to see more.`)); } } catch (error) { console.error(chalk.red('Failed to list assets:'), error); } }); } function createInfoCommand() { return new Command('info') .description('get detailed information about an asset') .argument('<id>', 'asset ID') .option('-t, --type <type>', 'asset type (items, vehicles, maps)', 'items') .action(async (id, options) => { try { let asset: any = null; if (options.type === 'items') { asset = assetManager.getItemInfo(id); } else if (options.type === 'vehicles') { asset = assetManager.getVehicleInfo(id); } else if (options.type === 'maps') { const mapName = assetManager.getMapName(id); if (mapName) { asset = { id, name: mapName }; } } if (!asset) { console.log(chalk.red(`Asset with ID "${id}" not found in ${options.type}`)); return; } console.log(chalk.blue(`\nšŸ“„ Asset Information:`)); console.log(chalk.gray(`Type: ${options.type}`)); console.log(chalk.gray(`ID: ${asset.id || id}`)); console.log(chalk.gray(`Name: ${chalk.white(asset.name || asset.displayName)}`)); if (asset.category) { console.log(chalk.gray(`Category: ${asset.category}`)); } if (asset.subCategory) { console.log(chalk.gray(`Sub-category: ${asset.subCategory}`)); } if (asset.description) { console.log(chalk.gray(`Description: ${asset.description}`)); } if (asset.stackSize) { console.log(chalk.gray(`Stack Size: ${asset.stackSize}`)); } if (asset.vehicleType) { console.log(chalk.gray(`Vehicle Type: ${asset.vehicleType}`)); } } catch (error) { console.error(chalk.red('Failed to get asset info:'), error); } }); } function createExportCommand() { return new Command('export') .description('export assets to different formats') .option('-t, --type <type>', 'asset type (items, vehicles, maps, all)', 'all') .option('-f, --format <format>', 'export format (json, csv, typescript)', 'json') .option('-o, --output <file>', 'output file path', 'assets-export') .action(async (options) => { const spinner = ora('Exporting assets...').start(); try { let data: any = {}; if (options.type === 'all') { const categories = ['Weapon', 'Equipment', 'Consumable', 'Attachment', 'Ammunition']; const items: any[] = []; for (const category of categories) { items.push(...assetManager.getItemsByCategory(category)); } const vehicleIds = ['BP_Motorbike_00_C', 'Dacia_A_00_v2_C', 'Uaz_A_00_C', 'Buggy_A_00_C']; const vehicles = vehicleIds.map(id => assetManager.getVehicleInfo(id)).filter(Boolean); data = { items, vehicles, maps: assetManager.getAllMaps(), seasons: assetManager.getSeasonsByPlatform('PC') }; } else if (options.type === 'items') { const categories = ['Weapon', 'Equipment', 'Consumable', 'Attachment', 'Ammunition']; data = []; for (const category of categories) { data.push(...assetManager.getItemsByCategory(category)); } } else if (options.type === 'vehicles') { const vehicleIds = ['BP_Motorbike_00_C', 'Dacia_A_00_v2_C', 'Uaz_A_00_C', 'Buggy_A_00_C']; data = vehicleIds.map(id => assetManager.getVehicleInfo(id)).filter(Boolean); } else if (options.type === 'maps') { data = assetManager.getAllMaps(); } else if (options.type === 'seasons') { data = assetManager.getSeasonsByPlatform('PC'); } const outputFile = `${options.output}.${options.format}`; if (options.format === 'json') { fs.writeFileSync(outputFile, JSON.stringify(data, null, 2)); } else if (options.format === 'csv') { // Simple CSV export for items if (Array.isArray(data)) { const csv = convertToCSV(data); fs.writeFileSync(outputFile, csv); } else { spinner.fail('CSV export only supports single asset types'); return; } } else if (options.format === 'typescript') { // Generate TypeScript definitions const tsContent = generateTypeScriptDefinitions(data, options.type); fs.writeFileSync(outputFile, tsContent); } spinner.succeed(`Assets exported to ${outputFile}`); } catch (error) { spinner.fail(chalk.red('Export failed')); console.error(error); } }); } function showAssetStats() { try { const categories = ['Weapon', 'Equipment', 'Consumable', 'Attachment', 'Ammunition']; const items: any[] = []; for (const category of categories) { items.push(...assetManager.getItemsByCategory(category)); } const vehicleIds = ['BP_Motorbike_00_C', 'Dacia_A_00_v2_C', 'Uaz_A_00_C', 'Buggy_A_00_C']; const vehicles = vehicleIds.map(id => assetManager.getVehicleInfo(id)).filter(Boolean); const maps = assetManager.getAllMaps(); const seasons = assetManager.getSeasonsByPlatform('PC'); console.log(chalk.blue('\nšŸ“Š Asset Statistics:')); console.log(chalk.gray(`Items: ${items.length}`)); console.log(chalk.gray(`Vehicles: ${vehicles.length}`)); console.log(chalk.gray(`Maps: ${maps.length}`)); console.log(chalk.gray(`Seasons: ${seasons.length}`)); // Item categories const itemCategories = items.reduce((acc: any, item: any) => { acc[item.category] = (acc[item.category] || 0) + 1; return acc; }, {} as Record<string, number>); console.log(chalk.blue('\nšŸ“¦ Item Categories:')); Object.entries(itemCategories).forEach(([category, count]) => { console.log(chalk.gray(` ${category}: ${count}`)); }); } catch (error) { console.error(chalk.red('Failed to show statistics:'), error); } } function convertToCSV(data: any[]): string { if (data.length === 0) return ''; const headers = Object.keys(data[0]).join(','); const rows = data.map(item => Object.values(item).map(value => typeof value === 'string' ? `"${value}"` : value ).join(',') ); return [headers, ...rows].join('\n'); } function generateTypeScriptDefinitions(data: any, type: string): string { let content = `// Auto-generated TypeScript definitions for PUBG assets\n\n`; if (type === 'items' && Array.isArray(data)) { const itemIds = data.map(item => `'${item.id}'`).join(' | '); content += `export type ItemId = ${itemIds};\n\n`; content += `export interface ItemInfo {\n`; content += ` id: string;\n`; content += ` name: string;\n`; content += ` category: string;\n`; content += ` subCategory?: string;\n`; content += ` description?: string;\n`; content += ` stackSize?: number;\n`; content += `}\n\n`; content += `export const ITEM_DICTIONARY: Record<ItemId, ItemInfo> = ${JSON.stringify(data, null, 2)};\n`; } return content; }