This commit is contained in:
2026-01-14 14:29:03 +03:00
parent 7d540962a1
commit 4dd87ddecc
17 changed files with 513 additions and 226 deletions

View File

@@ -5,11 +5,11 @@ import (
"log"
"os"
"gorm.io/driver/postgres"
"gorm.io/gorm"
_ "github.com/lib/pq"
"github.com/vinovest/sqlx"
)
var PostgresDatabase *gorm.DB
var PostgresDatabase *sqlx.DB
func getDSN() string {
user := os.Getenv("PSQL_USER")
@@ -24,7 +24,7 @@ func getDSN() string {
func ConnectPostgres() {
var err error
PostgresDatabase, err = gorm.Open(postgres.Open(getDSN()), new(gorm.Config))
PostgresDatabase, err = sqlx.Open("postgres", getDSN())
if err != nil {
log.Fatalln(err)
}

View File

@@ -1,13 +1,34 @@
package psql
import "github.com/shopspring/decimal"
import (
"github.com/shopspring/decimal"
"github.com/vinovest/sqlx"
)
type Fraction struct {
ID int
ID int32
Name string
OwnerID int
OwnerID int `db:"owner_id"`
Owner *User
Money decimal.Decimal
Exp int
Level int
}
type FractionRepository struct {
db *sqlx.DB
}
func NewFractionRepository(db *sqlx.DB) *FractionRepository {
return &FractionRepository{db: db}
}
func (rep *FractionRepository) GetAllFractions() ([]*Fraction, error) {
fractions := make([]*Fraction, 0)
err := rep.db.Select(&fractions, "SELECT * FROM fractions ORDER BY id DESC;")
return fractions, err
}
func (rep *FractionRepository) GetFraction(id int32) (*Fraction, error) {
fraction := new(Fraction)
err := rep.db.Get(fraction, "SELECT * FROM fractions WHERE id = $1", id)
return fraction, err
}

View File

@@ -1,24 +1,34 @@
package psql
import (
"kurumibot/database"
"github.com/shopspring/decimal"
"github.com/vinovest/sqlx"
)
type Group struct {
ID int
Name string
IsAdmin bool
IsVip bool
IsTester bool
Multiplier decimal.Decimal
Sale decimal.Decimal
MaxWaifus int
ID int
Name string
IsAdmin bool `db:"is_admin"`
IsVip bool `db:"is_vip"`
IsTester bool `db:"is_tester"`
Multiplier decimal.Decimal
Sale decimal.Decimal
MaxMultigen int `db:"max_multigen"`
MaxWaifus int `db:"max_waifus"`
}
type GroupRepository struct {
db *sqlx.DB
}
func GetGroupById(id int) (*Group, error) {
group := new(Group)
tx := database.PostgresDatabase.First(group, "id = ?", id)
return group, tx.Error
func NewGroupRepository(db *sqlx.DB) *GroupRepository {
return &GroupRepository{db: db}
}
func (rep *GroupRepository) GetAll() ([]*Group, error) {
groups := make([]*Group, 0)
err := rep.db.Select(&groups, "SELECT * FROM groups ORDER BY id DESC;")
return groups, err
}
func (rep *GroupRepository) GetById(id int) (*Group, error) {
group, err := sqlx.One[Group](rep.db, "SELECT * FROM groups WHERE id = $1", id)
return &group, err
}

88
database/psql/rp.go Normal file
View File

@@ -0,0 +1,88 @@
package psql
import (
"database/sql"
"errors"
"github.com/vinovest/sqlx"
)
type RPGeneralPreset struct {
ID string
Name string
Description string
PreHistory string `db:"pre_history"`
PostHistory string `db:"post_history"`
}
type RPScenarios struct {
ID int
Name string
Prompt string
}
type RPUser struct {
UserID int64 `db:"user_id"`
SelectedPreset string `db:"selected_preset"`
UsedTokens int64 `db:"used_tokens"`
}
type RPRepository struct {
db *sqlx.DB
}
func NewRPRepository(db *sqlx.DB) *RPRepository {
return &RPRepository{db: db}
}
func (rep *RPRepository) GetOrCreateUser(id int64) (*RPUser, error) {
user, err := rep.GetUser(id)
if errors.Is(err, sql.ErrNoRows) {
user, err = rep.CreateUser(id)
}
return user, err
}
func (rep *RPRepository) CreateUser(id int64) (*RPUser, error) {
user := new(RPUser)
err := rep.db.Get(user, "INSERT INTO rp_users(user_id) VALUES ($1) RETURNING *;", id)
return user, err
}
func (rep *RPRepository) GetUser(id int64) (*RPUser, error) {
user := new(RPUser)
err := rep.db.Get(user, "SELECT * FROM rp_users WHERE user_id=$1", id)
return user, err
}
func (rep *RPRepository) UpdateUser(user *RPUser) error {
_, err := rep.db.NamedExec(
"UPDATE rp_users SET selected_preset=:selected_preset, used_tokens=:used_tokens WHERE user_id=:user_id;",
user,
)
return err
}
func (rep *RPRepository) UpdateUserPreset(user *RPUser, presetId string) (*RPGeneralPreset, error) {
preset, err := rep.GetPreset(presetId)
if err != nil {
return preset, err
}
_, err = rep.db.Exec("UPDATE rp_users SET selected_preset=$1 WHERE user_id=$2;", presetId, user.UserID)
return preset, err
}
func (rep *RPRepository) GetUserPreset(user *RPUser) (*RPGeneralPreset, error) {
preset, err := rep.GetPreset(user.SelectedPreset)
if errors.Is(err, sql.ErrNoRows) {
return rep.UpdateUserPreset(user, "soft")
}
return preset, err
}
func (rep *RPRepository) GetAllPresets() ([]*RPGeneralPreset, error) {
presets := make([]*RPGeneralPreset, 0)
err := rep.db.Select(&presets, "SELECT * FROM rp_general_presets;")
return presets, err
}
func (rep *RPRepository) GetPreset(id string) (*RPGeneralPreset, error) {
preset := new(RPGeneralPreset)
err := rep.db.Get(preset, "SELECT * FROM rp_general_presets WHERE id=$1;", id)
return preset, err
}
func (rep *RPRepository) GetAllScenarios() ([]*RPScenarios, error) {
return nil, nil
}

View File

@@ -1,6 +1,9 @@
package psql
import "github.com/shopspring/decimal"
import (
"github.com/shopspring/decimal"
"github.com/vinovest/sqlx"
)
type ShopAuto struct {
ID int
@@ -8,10 +11,6 @@ type ShopAuto struct {
Price decimal.Decimal
}
func (ShopAuto) TableName() string {
return "shop_auto"
}
type ShopBusiness struct {
ID int
Name string
@@ -19,10 +18,6 @@ type ShopBusiness struct {
Income decimal.Decimal
}
func (ShopBusiness) TableName() string {
return "shop_business"
}
type ShopMaid struct {
ID int
Name string
@@ -30,10 +25,6 @@ type ShopMaid struct {
Income decimal.Decimal
}
func (ShopMaid) TableName() string {
return "shop_maid"
}
type ShopMiner struct {
ID int
Name string
@@ -41,6 +32,51 @@ type ShopMiner struct {
Income decimal.Decimal
}
func (ShopMiner) TableName() string {
return "shop_miner"
type ShopRepository struct {
db *sqlx.DB
}
func NewShopRepository(db *sqlx.DB) *ShopRepository {
return &ShopRepository{db: db}
}
func (rep *ShopRepository) GetAllAuto() ([]*ShopAuto, error) {
auto := make([]*ShopAuto, 0)
err := rep.db.Select(&auto, "SELECT * FROM shop_auto ORDER BY id DESC;")
return auto, err
}
func (rep *ShopRepository) GetAuto(id int32) (*ShopAuto, error) {
auto := new(ShopAuto)
err := rep.db.Get(auto, "SELECT * FROM shop_auto WHERE id = $1;", id)
return auto, err
}
func (rep *ShopRepository) GetAllBusinesses() ([]*ShopBusiness, error) {
businesses := make([]*ShopBusiness, 0)
err := rep.db.Select(&businesses, "SELECT * FROM shop_business ORDER BY id DESC;")
return businesses, err
}
func (rep *ShopRepository) GetBusiness(id int32) (*ShopBusiness, error) {
business := new(ShopBusiness)
err := rep.db.Get(business, "SELECT * FROM shop_business WHERE id = $1;", id)
return business, err
}
func (rep *ShopRepository) GetAllMaids() ([]*ShopMaid, error) {
maids := make([]*ShopMaid, 0)
err := rep.db.Select(&maids, "SELECT * FROM shop_maid ORDER BY id DESC;")
return maids, err
}
func (rep *ShopRepository) GetMaid(id int32) (*ShopMaid, error) {
maid := new(ShopMaid)
err := rep.db.Get(maid, "SELECT * FROM shop_maid WHERE id = $1;", id)
return maid, err
}
func (rep *ShopRepository) GetAllMiners() ([]*ShopMiner, error) {
miners := make([]*ShopMiner, 0)
err := rep.db.Select(&miners, "SELECT * FROM shop_miner ORDER BY id DESC;")
return miners, err
}
func (rep *ShopRepository) GetMiner(id int32) (*ShopMiner, error) {
miner := new(ShopMiner)
err := rep.db.Get(miner, "SELECT * FROM shop_miner WHERE id = $1;", id)
return miner, err
}

View File

@@ -1,6 +1,7 @@
package psql
import (
"context"
"database/sql"
"errors"
"kurumibot/database"
@@ -8,78 +9,146 @@ import (
"time"
"github.com/shopspring/decimal"
"gorm.io/gorm"
"github.com/vinovest/sqlx"
)
type User struct {
ID int
Balance decimal.Decimal
Name string
GroupID int `gorm:"default:1"`
Group *Group
Level int `gorm:"default:1"`
Exp int `gorm:"default:0"`
WorkID int `gorm:"default:1"`
Work *Work
WorkTime time.Time
GroupID int `db:"group_id"`
Level int
Exp int
WorkID int `db:"work_id"`
WorkTime time.Time `db:"work_time"`
AutoID sql.NullInt64
Auto *ShopAuto
BusinessID sql.NullInt64
Business *ShopBusiness
MaidID sql.NullInt64
Maid *ShopMaid
MinerID sql.NullInt64
Miner *ShopMiner
AutoID sql.NullInt32 `db:"auto_id"`
BusinessID sql.NullInt32 `db:"business_id"`
MaidID sql.NullInt32 `db:"maid_id"`
MinerID sql.NullInt32 `db:"miner_id"`
IncomeTime time.Time
IncomeTime time.Time `db:"income_time"`
BTC decimal.Decimal
Invested decimal.Decimal
PairID sql.NullInt64
Pair *User
Greeting string `gorm:"size:255,default:Привет"`
Donat int `gorm:"default:0"`
FractionID sql.NullInt64
Fraction *Fraction
PairID sql.NullInt64 `db:"pair_id"`
Greeting string
Donat int
FractionID sql.NullInt32 `db:"fraction_id"`
MoneyIncome decimal.Decimal
ExpIncome int
BtcIncome decimal.Decimal
MoneyIncome decimal.Decimal `db:"money_income"`
ExpIncome int `db:"exp_income"`
BtcIncome decimal.Decimal `db:"btc_income"`
WaifuSearchTime time.Time
WaifuSearchTime time.Time `db:"waifu_search_time"`
Group *Group
Work *Work
Auto *ShopAuto
Business *ShopBusiness
Maid *ShopMaid
Miner *ShopMiner
Pair *User
Fraction *Fraction
}
func GetOrCreateUser(tgId int, name string) (*User, error) {
user, err := GetUser(tgId)
if errors.Is(err, gorm.ErrRecordNotFound) {
if errors.Is(err, sql.ErrNoRows) {
_, err = CreateUser(tgId, name)
if err != nil {
return nil, err
}
return GetUser(tgId)
user, err = GetUser(tgId)
}
return user, err
}
func CreateUser(id int, name string) (*User, error) {
user := &User{
ID: id,
Name: name,
}
tx := database.PostgresDatabase.Create(user)
return user, tx.Error
user := new(User)
err := database.PostgresDatabase.Get(user, "INSERT INTO users (id, name) VALUES (?, ?) RETURNING *;", id, name)
return user, err
}
func GetUser(telegramId int) (*User, error) {
user := new(User)
tx := database.PostgresDatabase.Joins("Group").Joins("Work").Joins("Auto").Joins("Business").Joins("Maid").Joins("Miner").Joins("Fraction").Preload("Pair").Take(user, "users.id=?", telegramId)
return user, tx.Error
err := sqlx.Transact(database.PostgresDatabase, func(ctx context.Context, db sqlx.Queryable) error {
err := database.PostgresDatabase.Get(user, "SELECT * FROM users WHERE id=$1;", telegramId)
if err != nil {
return err
}
user.Group = new(Group)
err = database.PostgresDatabase.Get(user.Group, "SELECT * FROM groups WHERE id=$1;", user.GroupID)
if err != nil {
return err
}
user.Work = new(Work)
err = database.PostgresDatabase.Get(user.Work, "SELECT * FROM works WHERE id=$1;", user.WorkID)
if err != nil {
return err
}
shopRep := NewShopRepository(database.PostgresDatabase)
if user.AutoID.Valid {
user.Auto, err = shopRep.GetAuto(user.AutoID.Int32)
if err != nil {
return err
}
}
if user.BusinessID.Valid {
user.Business, err = shopRep.GetBusiness(user.BusinessID.Int32)
if err != nil {
return err
}
}
if user.MaidID.Valid {
user.Maid, err = shopRep.GetMaid(user.MaidID.Int32)
if err != nil {
return err
}
}
if user.MinerID.Valid {
user.Miner, err = shopRep.GetMiner(user.MinerID.Int32)
if err != nil {
return err
}
}
if user.PairID.Valid {
user.Pair, err = GetUser(int(user.PairID.Int64))
if err != nil {
return err
}
}
if user.FractionID.Valid {
fractionRep := NewFractionRepository(database.PostgresDatabase)
user.Fraction, err = fractionRep.GetFraction(user.FractionID.Int32)
if err != nil {
return err
}
}
return nil
})
return user, err
}
func UpdateUser(user *User) (*User, error) {
_, err := database.PostgresDatabase.NamedExec(
`UPDATE users SET balance=:balance, name=:name, group_id=:group_id, level=:level, exp=:exp,
work_id=:work_id, work_time=:work_time, auto_id=:auto_id, business_id=:business_id,
maid_id=:maid_id, miner_id=:miner_id, income_time=:income_time, btc=:btc, invested=:invested,
pair_id=:pair_id, greeting=:greeting, donat=:donat, fraction_id=:fraction_id,
money_income=:money_income, exp_income=:exp_income, btc_income=:btc_income,
waifu_search_time=:waifu_search_time
WHERE id=:id;`,
user,
)
if err != nil {
return nil, err
}
return GetUser(user.ID)
}
func GetAllUsers() ([]*User, error) {
users := make([]*User, 0)
tx := database.PostgresDatabase.Joins("Group").Joins("Work").Joins("Auto").Joins("Business").Joins("Maid").Joins("Miner").Joins("Fraction").Preload("Pair").Find(&users)
return users, tx.Error
return users, nil
}
func CountLevel(userXp int) (int, int) {

View File

@@ -1,57 +1,106 @@
package psql
import (
"database/sql"
"kurumibot/database"
"github.com/shopspring/decimal"
"github.com/vinovest/sqlx"
)
type Waifu struct {
ID int
OwnerID int
Owner *User
OwnerID sql.NullInt64 `db:"owner_id"`
Name string
Rarity int
ExpBonus decimal.Decimal
MoneyBonus decimal.Decimal
MarketPrice decimal.Decimal
ExpBonus decimal.Decimal `db:"exp_bonus"`
MoneyBonus decimal.Decimal `db:"money_bonus"`
MarketPrice decimal.Decimal `db:"market_price"`
Fandom string
Image string
RpPrompt string
RpPrompt string `db:"rp_prompt"`
Owner *User
}
type WaifuRepository struct {
db *sqlx.DB
}
func NewWaifuRepository(db *sqlx.DB) *WaifuRepository {
return &WaifuRepository{db: db}
}
func GetAllWaifus() ([]*Waifu, error) {
waifus := make([]*Waifu, 0)
tx := database.PostgresDatabase.Joins("Owner").Find(&waifus).Order("id")
return waifus, tx.Error
waifus, err := sqlx.List[*Waifu](
database.PostgresDatabase,
"SELECT waifus.* FROM waifus;",
)
if err != nil {
return nil, err
}
for _, waifu := range waifus {
if !waifu.OwnerID.Valid {
continue
}
waifu.Owner = new(User)
err = database.PostgresDatabase.Get(waifu.Owner, "SELECT * FROM users WHERE id=$1;", waifu.OwnerID.Int64)
}
return waifus, err
}
func GetUserWaifus(userId int) ([]*Waifu, error) {
waifus := make([]*Waifu, 0)
tx := database.PostgresDatabase.Find(&waifus, "owner_id = ?", userId).Order("id")
return waifus, tx.Error
waifus, err := sqlx.List[*Waifu](
database.PostgresDatabase,
"SELECT waifus.* FROM waifus WHERE owner_id=$1;",
userId,
)
if err != nil {
return nil, err
}
user, err := GetUser(userId)
if err != nil {
return nil, err
}
for _, waifu := range waifus {
waifu.Owner = user
}
return waifus, nil
}
func GetFreeWaifus() ([]*Waifu, error) {
waifus := make([]*Waifu, 0)
tx := database.PostgresDatabase.Find(&waifus, "owner_id is null").Order("id")
return waifus, tx.Error
waifus, err := sqlx.List[*Waifu](
database.PostgresDatabase,
"SELECT * FROM waifus WHERE owner_id IS NULL;",
)
return waifus, err
}
func GetFreeWaifusCount() (int64, error) {
var count int64 = 0
tx := database.PostgresDatabase.Model(&Waifu{}).Where("owner_id is null").Count(&count)
return count, tx.Error
err := database.PostgresDatabase.QueryRow("SELECT COUNT(*) FROM waifus WHERE owner_id IS NULL;").Scan(&count)
return count, err
}
func GetFreeWaifusWithRarity(rarity int) ([]*Waifu, error) {
waifus := make([]*Waifu, 0)
tx := database.PostgresDatabase.Find(&waifus, "owner_id is null and rarity = ?", rarity)
return waifus, tx.Error
waifus, err := sqlx.List[*Waifu](
database.PostgresDatabase,
"SELECT * FROM waifus WHERE owner_id IS NULL AND rarity=$1;",
rarity,
)
return waifus, err
}
func GetWaifuById(id int) (*Waifu, error) {
waifu := new(Waifu)
tx := database.PostgresDatabase.Joins("Owner").Find(waifu, id)
return waifu, tx.Error
err := database.PostgresDatabase.Get(waifu, "SELECT * FROM waifus WHERE id=$1;", id)
if err != nil {
return nil, err
}
if !waifu.OwnerID.Valid {
return waifu, err
}
waifu.Owner, err = GetUser(int(waifu.OwnerID.Int64))
return waifu, err
}

View File

@@ -9,20 +9,20 @@ import (
type Work struct {
ID int
Name string
RequiredLevel int
MoneyIncome decimal.Decimal
MinExp int
MaxExp int
RequiredLevel int `db:"required_level"`
MoneyIncome decimal.Decimal `db:"money_income"`
MinExp int `db:"min_exp"`
MaxExp int `db:"max_exp"`
}
func GetWorkById(id int) (*Work, error) {
work := new(Work)
tx := database.PostgresDatabase.First(work, id)
return work, tx.Error
func GetWorkById(id int) (Work, error) {
work := Work{}
err := database.PostgresDatabase.Get(&work, "SELECT * FROM works WHERE id = $1;", id)
return work, err
}
func GetAllWorks() ([]*Work, error) {
works := make([]*Work, 0)
tx := database.PostgresDatabase.Order("id").Find(&works)
return works, tx.Error
func GetAllWorks() ([]Work, error) {
works := make([]Work, 0)
err := database.PostgresDatabase.Select(&works, "SELECT * FROM works;")
return works, err
}