feat: add game and payments handlers

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
achmad
2026-05-29 16:36:44 +07:00
parent 62611a3685
commit 88c69f534c
2 changed files with 108 additions and 0 deletions
+57
View File
@@ -0,0 +1,57 @@
import { route, HandlerContext, HttpError } from '@/lib/router';
import { getDb } from '@/lib/db';
route('game/start', ['POST'], (ctx: HandlerContext) => {
const { steam_id, hero, hero_level, difficulty, player_name, match_id, session_id, session_participants } = ctx.body as any;
if (!steam_id) throw new HttpError(400, 'steam_id required');
const db = getDb();
const gameId = `game_${Date.now()}_${Math.floor(Math.random() * 100000)}`;
const newMatchId = match_id || Math.floor(Math.random() * 100000000);
db.prepare('INSERT OR REPLACE INTO game_sessions (game_id, match_id, session_id, status) VALUES (?, ?, ?, \'active\')')
.run(gameId, newMatchId, session_id || '');
return { game_id: gameId, match_id: newMatchId };
});
route('game/heartbeat', ['POST'], (ctx: HandlerContext) => {
return { success: true };
});
route('game', ['POST'], (ctx: HandlerContext) => {
const { steam_id, result, duration, kills, deaths, score, outgoing_damage, incoming_damage,
hero, hero_level, items, modifiers, aghanim_scepter, aghanim_shard, gold_earned,
difficulty, session_id, game_id } = ctx.body as any;
if (!steam_id) throw new HttpError(400, 'steam_id required');
const db = getDb();
db.prepare(`
INSERT INTO game_history (steam_id, game_id, result, duration, kills, deaths, score,
outgoing_damage, incoming_damage, hero, hero_level, items, modifiers,
aghanim_scepter, aghanim_shard, gold_earned, difficulty, session_id)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
`).run(steam_id, game_id || null, result || 'loss', duration || 0, kills || 0, deaths || 0,
score || 0, outgoing_damage || 0, incoming_damage || 0, hero || '', hero_level || 1,
items || '', modifiers || '', aghanim_scepter ? 1 : 0, aghanim_shard ? 1 : 0,
gold_earned || 0, difficulty || 'normal', session_id || '');
if (game_id) {
db.prepare("UPDATE game_sessions SET status = 'completed' WHERE game_id = ?").run(game_id);
}
return { success: true };
});
route('game/:id/players', ['GET'], (ctx: HandlerContext) => {
const db = getDb();
const session = db.prepare('SELECT * FROM game_sessions WHERE game_id = ? OR match_id = ?')
.get(ctx.params.id, parseInt(ctx.params.id) || 0) as any;
if (!session) return { players: [] };
const players = db.prepare(
'SELECT DISTINCT steam_id, hero, hero_level, result FROM game_history WHERE match_id = ? OR game_id = ?'
).all(session.match_id, session.game_id);
return { party_players: players, players };
});
+51
View File
@@ -0,0 +1,51 @@
import { route, HandlerContext, HttpError } from '@/lib/router';
import { getDb } from '@/lib/db';
// POST /payments/robokassa/link — Auto-grant purchased currency
route('payments/robokassa/link', ['POST'], (ctx: HandlerContext) => {
const { steam_id, amount_rub } = ctx.body as any;
if (!steam_id) throw new HttpError(400, 'steam_id required');
const db = getDb();
const donateShards = (amount_rub || 100) * 10;
db.prepare('UPDATE players SET donate_currency = donate_currency + ?, updated_at = datetime(\'now\') WHERE steam_id = ?')
.run(donateShards, steam_id);
return {
ok: true,
payment_url: '',
donate_shards: donateShards,
inv_id: Math.floor(Math.random() * 100000),
};
});
// POST /payments/bundles/link — Auto-grant bundle items
route('payments/bundles/link', ['POST'], (ctx: HandlerContext) => {
const { steam_id, bundle_id } = ctx.body as any;
if (!steam_id) throw new HttpError(400, 'steam_id required');
const db = getDb();
db.prepare('UPDATE players SET free_currency = free_currency + 500, donate_currency = donate_currency + 200, updated_at = datetime(\'now\') WHERE steam_id = ?')
.run(steam_id);
return {
ok: true,
payment_url: '',
inv_id: Math.floor(Math.random() * 100000),
message: 'Bundle granted',
};
});
// GET /payments/deals?steam_id= — Return deal catalog
route('payments/deals', ['GET'], (ctx: HandlerContext) => {
return {
ok: true,
bundles: [
{ id: 'starter_bundle', name: 'Starter Pack', description: 'Get started with 500 shards', price_free: 0, price_donate: 0, items: [{ item_id: 'starter_pack', name: 'Starter Pack' }] },
{ id: 'hero_bundle_1', name: 'Hero Bundle I', description: 'Unlock a random hero', price_free: 1000, price_donate: 0, items: [{ item_id: 'hero_bundle_1', name: 'Hero Bundle' }] },
],
daily: { available: true, items: [] },
weekly: { available: true, items: [] },
player_created_at_unix: Math.floor(Date.now() / 1000),
};
});