Files
gold_land_server/src/users/users.service.ts
T
safavimohadeseh78andCursor dfb20ca92c
Backend CI / type-check, build, tests (push) Successful in 1m0s
feat: prepare six-lesson trial backend with reliable rewards and operations
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-12 14:35:42 +03:30

110 lines
3.2 KiB
TypeScript

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 {
return this.database.transaction(() => {
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('داده کاربر نامعتبر است')
}
}
}