feat: add arsenal, marketplace, and contracts handlers

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
achmad
2026-05-29 16:42:36 +07:00
parent a1129f6e6d
commit 60666015cb
3 changed files with 155 additions and 0 deletions
+81
View File
@@ -0,0 +1,81 @@
import { route, HandlerContext, HttpError } from '@/lib/router';
import { getDb } from '@/lib/db';
route('player/:steamId/arsenal_loadouts', ['GET'], (ctx: HandlerContext) => {
const db = getDb();
const rows = db.prepare('SELECT * FROM arsenal_loadouts WHERE steam_id = ?').all(ctx.params.steamId);
const loadouts: Record<string, any> = {};
for (const r of rows as any[]) {
loadouts[r.hero_name] = JSON.parse(r.loadout);
}
return { arsenal_loadouts: loadouts };
});
route('player/:steamId/arsenal_loadouts', ['PUT'], (ctx: HandlerContext) => {
const { arsenal_loadouts } = ctx.body as any;
if (!arsenal_loadouts) throw new HttpError(400, 'arsenal_loadouts required');
const db = getDb();
const upsert = db.prepare(`
INSERT INTO arsenal_loadouts (steam_id, hero_name, loadout, updated_at) VALUES (?, ?, ?, datetime('now'))
ON CONFLICT(steam_id, hero_name) DO UPDATE SET loadout = ?, updated_at = datetime('now')
`);
const tx = db.transaction(() => {
for (const [hero, loadout] of Object.entries(arsenal_loadouts)) {
upsert.run(ctx.params.steamId, hero, JSON.stringify(loadout), JSON.stringify(loadout));
}
});
tx();
return { success: true };
});
route('player/:steamId/arsenal_inventory', ['GET'], (ctx: HandlerContext) => {
const db = getDb();
const items = db.prepare('SELECT * FROM arsenal_inventory WHERE steam_id = ?').all(ctx.params.steamId);
const instances: Record<string, any> = {};
for (const item of items as any[]) {
instances[item.instance_id] = {
instanceId: item.instance_id,
itemName: item.item_name,
quality: item.quality,
upgradeLevel: item.upgrade_level,
serial: item.serial,
globalSerial: item.global_serial,
ownerName: item.owner_name,
pinned: !!item.pinned,
favorite: !!item.favorite,
stats: JSON.parse(item.stats || '[]'),
};
}
return { arsenal_inventory: { instances } };
});
route('player/:steamId/arsenal_inventory', ['PUT'], (ctx: HandlerContext) => {
const { arsenal_inventory } = ctx.body as any;
if (!arsenal_inventory || !arsenal_inventory.instances) throw new HttpError(400, 'arsenal_inventory.instances required');
const db = getDb();
const upsert = db.prepare(`
INSERT INTO arsenal_inventory (steam_id, instance_id, item_name, quality, upgrade_level, serial, global_serial, owner_name, pinned, favorite, stats)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
ON CONFLICT(steam_id, instance_id) DO UPDATE SET
item_name = excluded.item_name, quality = excluded.quality, upgrade_level = excluded.upgrade_level,
serial = excluded.serial, global_serial = excluded.global_serial, owner_name = excluded.owner_name,
pinned = excluded.pinned, favorite = excluded.favorite, stats = excluded.stats
`);
const tx = db.transaction(() => {
for (const [instId, inst] of Object.entries(arsenal_inventory.instances)) {
const i = inst as any;
upsert.run(ctx.params.steamId, instId,
i.itemName || i.item_name || '',
i.quality || 'common',
i.upgradeLevel || i.upgrade_level || 0,
i.serial || 0,
i.globalSerial || i.global_serial || 0,
i.ownerName || i.owner_name || '',
i.pinned ? 1 : 0,
i.favorite ? 1 : 0,
JSON.stringify(i.stats || []));
}
});
tx();
return { success: true };
});
+18
View File
@@ -0,0 +1,18 @@
import { route, HandlerContext, HttpError } from '@/lib/router';
import { getDb } from '@/lib/db';
route('player/:steamId/death_sentence_contracts', ['GET'], (ctx: HandlerContext) => {
const db = getDb();
const row = db.prepare('SELECT contracts FROM death_sentence_contracts WHERE steam_id = ?').get(ctx.params.steamId) as any;
return { death_sentence_contracts: row ? JSON.parse(row.contracts) : { roster: [] } };
});
route('player/:steamId/death_sentence_contracts', ['PUT'], (ctx: HandlerContext) => {
const { death_sentence_contracts } = ctx.body as any;
const db = getDb();
db.prepare(`
INSERT INTO death_sentence_contracts (steam_id, contracts, updated_at) VALUES (?, ?, datetime('now'))
ON CONFLICT(steam_id) DO UPDATE SET contracts = ?, updated_at = datetime('now')
`).run(ctx.params.steamId, JSON.stringify(death_sentence_contracts || {}), JSON.stringify(death_sentence_contracts || {}));
return { success: true };
});
+56
View File
@@ -0,0 +1,56 @@
import { route, HandlerContext, HttpError } from '@/lib/router';
import { getDb } from '@/lib/db';
route('arsenal_market/listings', ['GET'], (ctx: HandlerContext) => {
const db = getDb();
return db.prepare("SELECT * FROM arsenal_market_listings WHERE status = 'active' ORDER BY created_at DESC").all();
});
route('player/:steamId/arsenal_market/my_listings', ['GET'], (ctx: HandlerContext) => {
const db = getDb();
return db.prepare("SELECT * FROM arsenal_market_listings WHERE steam_id = ? AND status = 'active' ORDER BY created_at DESC").all(ctx.params.steamId);
});
route('player/:steamId/arsenal_market/slots', ['GET'], (ctx: HandlerContext) => {
return { slots: 5, used: 0 };
});
route('player/:steamId/arsenal_market/sales', ['GET'], (ctx: HandlerContext) => {
const db = getDb();
return db.prepare('SELECT * FROM arsenal_market_sales WHERE seller_steam_id = ? ORDER BY created_at DESC').all(ctx.params.steamId);
});
route('player/:steamId/arsenal_market/create', ['POST'], (ctx: HandlerContext) => {
const { instance_id, item_name, quality, upgrade_level, serial, global_serial, price_free } = ctx.body as any;
const listingId = `list_${Date.now()}_${Math.floor(Math.random() * 1000)}`;
const db = getDb();
db.prepare(`
INSERT INTO arsenal_market_listings (listing_id, steam_id, instance_id, item_name, quality, upgrade_level, serial, global_serial, price_free, status)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, 'active')
`).run(listingId, ctx.params.steamId, instance_id || '', item_name || 'Unknown', quality || 'common',
upgrade_level || 0, serial || 0, global_serial || 0, price_free || 0);
return { success: true, listing_id: listingId };
});
route('player/:steamId/arsenal_market/buy', ['POST'], (ctx: HandlerContext) => {
const { listing_id } = ctx.body as any;
if (!listing_id) throw new HttpError(400, 'listing_id required');
const db = getDb();
const listing = db.prepare('SELECT * FROM arsenal_market_listings WHERE listing_id = ?').get(listing_id) as any;
if (!listing) throw new HttpError(404, 'Listing not found');
if (listing.status !== 'active') throw new HttpError(400, 'Listing not active');
db.prepare("UPDATE arsenal_market_listings SET status = 'sold' WHERE listing_id = ?").run(listing_id);
db.prepare('INSERT INTO arsenal_market_sales (listing_id, seller_steam_id, buyer_steam_id, item_name, price_free) VALUES (?, ?, ?, ?, ?)')
.run(listing_id, listing.steam_id, ctx.params.steamId, listing.item_name, listing.price_free);
return { success: true };
});
route('player/:steamId/arsenal_market/cancel', ['POST'], (ctx: HandlerContext) => {
const { listing_id } = ctx.body as any;
if (!listing_id) throw new HttpError(400, 'listing_id required');
const db = getDb();
db.prepare("UPDATE arsenal_market_listings SET status = 'cancelled' WHERE listing_id = ? AND steam_id = ?")
.run(listing_id, ctx.params.steamId);
return { success: true };
});