Initial commit: NestJS backend for Child Gold Land
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,107 @@
|
||||
import {
|
||||
Inject,
|
||||
Injectable,
|
||||
InternalServerErrorException,
|
||||
Logger,
|
||||
forwardRef,
|
||||
} from '@nestjs/common'
|
||||
import { DatabaseService } from '../database/database.service'
|
||||
import { createDefaultUserState } from '../shared/catalog/default-user-state'
|
||||
import type { MeResponse, UserState } from '../shared/types/user.types'
|
||||
import { GoldLandProgressionService } from '../gold-land/services/progression.service'
|
||||
|
||||
@Injectable()
|
||||
export class UsersService {
|
||||
private readonly logger = new Logger(UsersService.name)
|
||||
|
||||
constructor(
|
||||
@Inject(DatabaseService) private readonly database: DatabaseService,
|
||||
@Inject(forwardRef(() => GoldLandProgressionService))
|
||||
private readonly goldLandProgression: GoldLandProgressionService,
|
||||
) {}
|
||||
|
||||
ensureUser(userId: string): UserState {
|
||||
return this.getUserState(userId)
|
||||
}
|
||||
|
||||
getUserState(userId: string): UserState {
|
||||
const row = this.database
|
||||
.getDb()
|
||||
.prepare('SELECT state_json FROM users WHERE id = ?')
|
||||
.get(userId) as { state_json: string } | undefined
|
||||
|
||||
if (row) {
|
||||
return this.parseStateJson(row.state_json, userId)
|
||||
}
|
||||
|
||||
const state = createDefaultUserState(userId)
|
||||
this.database
|
||||
.getDb()
|
||||
.prepare('INSERT INTO users (id, state_json, updated_at) VALUES (?, ?, ?)')
|
||||
.run(userId, JSON.stringify(state), new Date().toISOString())
|
||||
return state
|
||||
}
|
||||
|
||||
saveUserState(state: UserState): UserState {
|
||||
this.database
|
||||
.getDb()
|
||||
.prepare('UPDATE users SET state_json = ?, updated_at = ? WHERE id = ?')
|
||||
.run(JSON.stringify(state), new Date().toISOString(), state.id)
|
||||
return state
|
||||
}
|
||||
|
||||
toMeResponse(state: UserState): MeResponse {
|
||||
return {
|
||||
user: {
|
||||
id: state.id,
|
||||
name: state.name,
|
||||
level: state.level,
|
||||
xp: state.xp,
|
||||
maxXp: state.maxXp,
|
||||
coins: state.coins,
|
||||
missionProgress: state.missionProgress,
|
||||
missionTarget: state.missionTarget,
|
||||
},
|
||||
wallet: {
|
||||
cash: state.cash,
|
||||
goldGrams: state.goldGrams,
|
||||
},
|
||||
progress: {
|
||||
completedChallenges: state.completedChallenges,
|
||||
completedLessons: state.completedLessons,
|
||||
completedGames: state.completedGames,
|
||||
claimedRewards: state.claimedRewards,
|
||||
ownedItems: state.ownedItems,
|
||||
mapLevels: state.mapLevels,
|
||||
totalStars: state.totalStars,
|
||||
maxStars: state.maxStars,
|
||||
},
|
||||
achievements: state.achievements,
|
||||
transactions: state.transactions,
|
||||
market: {
|
||||
selectedRange: state.marketSelectedRange,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
getMe(userId: string): MeResponse {
|
||||
const state = this.goldLandProgression.syncUserProgressionState(userId)
|
||||
return this.toMeResponse(state)
|
||||
}
|
||||
|
||||
updateProfile(userId: string, name: string): MeResponse {
|
||||
const state = this.getUserState(userId)
|
||||
state.name = name.trim()
|
||||
this.saveUserState(state)
|
||||
return this.toMeResponse(state)
|
||||
}
|
||||
|
||||
private parseStateJson(raw: string, userId: string): UserState {
|
||||
try {
|
||||
return JSON.parse(raw) as UserState
|
||||
} catch (error) {
|
||||
this.logger.error(`Invalid state_json for user ${userId}`, error)
|
||||
throw new InternalServerErrorException('داده کاربر نامعتبر است')
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user