initial commit
This commit is contained in:
7
.env
Normal file
7
.env
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
TG_TOKEN=
|
||||||
|
PREFIXES=/;!
|
||||||
|
DEBUG=true
|
||||||
|
USE_REQ_LOG=true
|
||||||
|
PSQL_USER=
|
||||||
|
PSQL_NAME=
|
||||||
|
PSQL_PASS=
|
||||||
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
logs/
|
||||||
|
.idea/
|
||||||
|
config.json
|
||||||
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
[submodule "laniakea"]
|
||||||
|
path = laniakea
|
||||||
|
url = https://git.nix13.pw/ScuroNeko/Laniakea
|
||||||
7
Dockerfile
Normal file
7
Dockerfile
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
FROM golang:1.25-alpine
|
||||||
|
WORKDIR /usr/src/kurumi
|
||||||
|
COPY go.mod go.sum ./
|
||||||
|
RUN go mod download
|
||||||
|
COPY . .
|
||||||
|
RUN go build -v -o /usr/local/bin/kurumi ./
|
||||||
|
CMD ["kurumi"]
|
||||||
5
build.bat
Normal file
5
build.bat
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
@echo off
|
||||||
|
set GOARCH=amd64
|
||||||
|
set GOOS=linux
|
||||||
|
go build .
|
||||||
|
pause
|
||||||
51
database/database.go
Normal file
51
database/database.go
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
package database
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"gorm.io/driver/postgres"
|
||||||
|
"gorm.io/gorm"
|
||||||
|
)
|
||||||
|
|
||||||
|
type config struct {
|
||||||
|
Host string `json:"host"`
|
||||||
|
User string `json:"user"`
|
||||||
|
Password string `json:"password"`
|
||||||
|
Database string `json:"database"`
|
||||||
|
}
|
||||||
|
|
||||||
|
var Database *gorm.DB
|
||||||
|
var conf *config
|
||||||
|
|
||||||
|
func loadConfig() {
|
||||||
|
file, err := os.Open("./config.json")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalln(err)
|
||||||
|
}
|
||||||
|
data, err := io.ReadAll(file)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalln(err)
|
||||||
|
}
|
||||||
|
conf = new(config)
|
||||||
|
err = json.Unmarshal(data, conf)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalln(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func getDSN() string {
|
||||||
|
return fmt.Sprintf("postgresql://%s:%s@%s/%s?sslmode=disable", conf.User, conf.Password, conf.Host, conf.Database)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Connect() {
|
||||||
|
var err error
|
||||||
|
loadConfig()
|
||||||
|
Database, err = gorm.Open(postgres.Open(getDSN()), new(gorm.Config))
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalln(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
13
database/fraction.go
Normal file
13
database/fraction.go
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
package database
|
||||||
|
|
||||||
|
import "github.com/shopspring/decimal"
|
||||||
|
|
||||||
|
type Fraction struct {
|
||||||
|
ID int
|
||||||
|
Name string
|
||||||
|
OwnerID int
|
||||||
|
Owner *User
|
||||||
|
Money decimal.Decimal
|
||||||
|
Exp int
|
||||||
|
Level int
|
||||||
|
}
|
||||||
20
database/groups.go
Normal file
20
database/groups.go
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
package database
|
||||||
|
|
||||||
|
import "github.com/shopspring/decimal"
|
||||||
|
|
||||||
|
type Group struct {
|
||||||
|
ID int
|
||||||
|
Name string
|
||||||
|
IsAdmin bool
|
||||||
|
IsVip bool
|
||||||
|
IsTester bool
|
||||||
|
Multiplier decimal.Decimal
|
||||||
|
Sale decimal.Decimal
|
||||||
|
MaxWaifus int
|
||||||
|
}
|
||||||
|
|
||||||
|
// func GetGroupById(id int) (*Group, error) {
|
||||||
|
// group := new(Group)
|
||||||
|
// // err := Database.Get(group, "select * from groups where id=$1;", id)
|
||||||
|
// return group, err
|
||||||
|
// }
|
||||||
30
database/shop.go
Normal file
30
database/shop.go
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
package database
|
||||||
|
|
||||||
|
import "github.com/shopspring/decimal"
|
||||||
|
|
||||||
|
type ShopAuto struct {
|
||||||
|
ID int
|
||||||
|
Name string
|
||||||
|
Price decimal.Decimal
|
||||||
|
}
|
||||||
|
|
||||||
|
type ShopBusiness struct {
|
||||||
|
ID int
|
||||||
|
Name string
|
||||||
|
Price decimal.Decimal
|
||||||
|
Income decimal.Decimal
|
||||||
|
}
|
||||||
|
|
||||||
|
type ShopMaid struct {
|
||||||
|
ID int
|
||||||
|
Name string
|
||||||
|
Price decimal.Decimal
|
||||||
|
Income decimal.Decimal
|
||||||
|
}
|
||||||
|
|
||||||
|
type ShopMiner struct {
|
||||||
|
ID int
|
||||||
|
Name string
|
||||||
|
Price decimal.Decimal
|
||||||
|
Income decimal.Decimal
|
||||||
|
}
|
||||||
93
database/users.go
Normal file
93
database/users.go
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
package database
|
||||||
|
|
||||||
|
import (
|
||||||
|
"database/sql"
|
||||||
|
"errors"
|
||||||
|
"math"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/shopspring/decimal"
|
||||||
|
"gorm.io/gorm"
|
||||||
|
)
|
||||||
|
|
||||||
|
type User struct {
|
||||||
|
ID int
|
||||||
|
TelegramID int `gorm:"column:tg_id"`
|
||||||
|
Balance decimal.Decimal
|
||||||
|
Name string
|
||||||
|
GroupID int
|
||||||
|
Group *Group
|
||||||
|
Level int
|
||||||
|
WorkID int
|
||||||
|
Work *Work
|
||||||
|
WorkTime time.Time
|
||||||
|
Exp int
|
||||||
|
AutoID int
|
||||||
|
Auto *ShopAuto
|
||||||
|
BusinessID int
|
||||||
|
Business *ShopBusiness
|
||||||
|
MaidID int
|
||||||
|
Maid *ShopMaid
|
||||||
|
MinerID int
|
||||||
|
Miner *ShopMiner
|
||||||
|
IncomeTime time.Time
|
||||||
|
BTC decimal.Decimal
|
||||||
|
Invested decimal.Decimal
|
||||||
|
PairID int
|
||||||
|
Pair *User
|
||||||
|
Greeting string
|
||||||
|
Donat int
|
||||||
|
FractionID sql.NullInt64
|
||||||
|
Fraction *Fraction
|
||||||
|
|
||||||
|
MoneyIncome decimal.Decimal
|
||||||
|
ExpIncome int
|
||||||
|
BtcIncome decimal.Decimal
|
||||||
|
|
||||||
|
WaifuSearchTime time.Time
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetOrCreateUser(tgId int, name string) (*User, error) {
|
||||||
|
user, err := GetUser(tgId)
|
||||||
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||||
|
user, err = CreateUser(tgId, name)
|
||||||
|
}
|
||||||
|
return user, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func CreateUser(tgId int, name string) (*User, error) {
|
||||||
|
user := &User{
|
||||||
|
TelegramID: tgId,
|
||||||
|
Name: name,
|
||||||
|
}
|
||||||
|
tx := Database.Create(user)
|
||||||
|
return user, tx.Error
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetUser(telegramId int) (*User, error) {
|
||||||
|
user := new(User)
|
||||||
|
tx := Database.Joins("Group").Joins("Work").Joins("Auto").Joins("Business").Joins("Maid").Joins("Miner").Joins("Fraction").Preload("Pair").Take(user, "tg_id=?", telegramId)
|
||||||
|
return user, tx.Error
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetAllUsers() ([]*User, error) {
|
||||||
|
users := make([]*User, 0)
|
||||||
|
tx := Database.Joins("Group").Joins("Work").Joins("Auto").Joins("Business").Joins("Maid").Joins("Miner").Joins("Fraction").Preload("Pair").Find(&users)
|
||||||
|
return users, tx.Error
|
||||||
|
}
|
||||||
|
|
||||||
|
func CountLevel(userXp int) (int, int) {
|
||||||
|
xp := 0
|
||||||
|
nextLevel := 2
|
||||||
|
for {
|
||||||
|
xp = int(math.Pow(float64(nextLevel), 3)) * (nextLevel * 3)
|
||||||
|
if xp > userXp {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if nextLevel == 200 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
nextLevel++
|
||||||
|
}
|
||||||
|
return nextLevel - 1, xp
|
||||||
|
}
|
||||||
53
database/waifus.go
Normal file
53
database/waifus.go
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
package database
|
||||||
|
|
||||||
|
import "github.com/shopspring/decimal"
|
||||||
|
|
||||||
|
type Waifu struct {
|
||||||
|
ID int
|
||||||
|
Name string
|
||||||
|
Rarity int
|
||||||
|
ExpBonus decimal.Decimal
|
||||||
|
MoneyBonus decimal.Decimal
|
||||||
|
MarketPrice decimal.Decimal
|
||||||
|
Fandom string
|
||||||
|
Image string
|
||||||
|
|
||||||
|
OwnerID int
|
||||||
|
Owner *User
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetAllWaifus() ([]*Waifu, error) {
|
||||||
|
waifus := make([]*Waifu, 0)
|
||||||
|
tx := Database.Joins("Owner").Find(&waifus).Order("id")
|
||||||
|
return waifus, tx.Error
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetUserWaifus(userId int) ([]*Waifu, error) {
|
||||||
|
waifus := make([]*Waifu, 0)
|
||||||
|
tx := Database.Find(&waifus, "owner_id = ?", userId).Order("id")
|
||||||
|
return waifus, tx.Error
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetFreeWaifus() ([]*Waifu, error) {
|
||||||
|
waifus := make([]*Waifu, 0)
|
||||||
|
tx := Database.Find(&waifus, "owner_id is null").Order("id")
|
||||||
|
return waifus, tx.Error
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetFreeWaifusCount() (int64, error) {
|
||||||
|
var count int64 = 0
|
||||||
|
tx := Database.Model(&Waifu{}).Where("owner_id is null").Count(&count)
|
||||||
|
return count, tx.Error
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetFreeWaifusWithRarity(rarity int) ([]*Waifu, error) {
|
||||||
|
waifus := make([]*Waifu, 0)
|
||||||
|
tx := Database.Find(&waifus, "owner_id is null and rarity = ?", rarity)
|
||||||
|
return waifus, tx.Error
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetWaifuById(id int) (*Waifu, error) {
|
||||||
|
waifu := new(Waifu)
|
||||||
|
tx := Database.Joins("Owner").Find(waifu, id)
|
||||||
|
return waifu, tx.Error
|
||||||
|
}
|
||||||
24
database/works.go
Normal file
24
database/works.go
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
package database
|
||||||
|
|
||||||
|
import "github.com/shopspring/decimal"
|
||||||
|
|
||||||
|
type Work struct {
|
||||||
|
ID int
|
||||||
|
Name string
|
||||||
|
RequiredLevel int
|
||||||
|
MoneyIncome decimal.Decimal
|
||||||
|
MinExp int
|
||||||
|
MaxExp int
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetWorkById(id int) (*Work, error) {
|
||||||
|
work := new(Work)
|
||||||
|
tx := Database.First(work, id)
|
||||||
|
return work, tx.Error
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetAllWorks() ([]*Work, error) {
|
||||||
|
works := make([]*Work, 0)
|
||||||
|
tx := Database.Order("id").Find(&works)
|
||||||
|
return works, tx.Error
|
||||||
|
}
|
||||||
25
go.mod
Normal file
25
go.mod
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
module kurumibot
|
||||||
|
|
||||||
|
go 1.25.0
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/fatih/color v1.18.0
|
||||||
|
github.com/shopspring/decimal v1.4.0
|
||||||
|
gorm.io/driver/postgres v1.6.0
|
||||||
|
gorm.io/gorm v1.30.1
|
||||||
|
)
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/jackc/pgpassfile v1.0.0 // indirect
|
||||||
|
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect
|
||||||
|
github.com/jackc/pgx/v5 v5.7.1 // indirect
|
||||||
|
github.com/jackc/puddle/v2 v2.2.2 // indirect
|
||||||
|
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||||
|
github.com/jinzhu/now v1.1.5 // indirect
|
||||||
|
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||||
|
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||||
|
golang.org/x/crypto v0.31.0 // indirect
|
||||||
|
golang.org/x/sync v0.10.0 // indirect
|
||||||
|
golang.org/x/sys v0.28.0 // indirect
|
||||||
|
golang.org/x/text v0.21.0 // indirect
|
||||||
|
)
|
||||||
49
go.sum
Normal file
49
go.sum
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM=
|
||||||
|
github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU=
|
||||||
|
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
|
||||||
|
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
|
||||||
|
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo=
|
||||||
|
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
|
||||||
|
github.com/jackc/pgx/v5 v5.7.1 h1:x7SYsPBYDkHDksogeSmZZ5xzThcTgRz++I5E+ePFUcs=
|
||||||
|
github.com/jackc/pgx/v5 v5.7.1/go.mod h1:e7O26IywZZ+naJtWWos6i6fvWK+29etgITqrqHLfoZA=
|
||||||
|
github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo=
|
||||||
|
github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
|
||||||
|
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
|
||||||
|
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
|
||||||
|
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
|
||||||
|
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
||||||
|
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
||||||
|
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
||||||
|
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||||
|
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||||
|
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k=
|
||||||
|
github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME=
|
||||||
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
|
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
|
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
|
||||||
|
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||||
|
golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U=
|
||||||
|
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
|
||||||
|
golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
|
||||||
|
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||||
|
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
|
||||||
|
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
|
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
|
||||||
|
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
|
||||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
gorm.io/driver/postgres v1.6.0 h1:2dxzU8xJ+ivvqTRph34QX+WrRaJlmfyPqXmoGVjMBa4=
|
||||||
|
gorm.io/driver/postgres v1.6.0/go.mod h1:vUw0mrGgrTK+uPHEhAdV4sfFELrByKVGnaVRkXDhtWo=
|
||||||
|
gorm.io/gorm v1.30.1 h1:lSHg33jJTBxs2mgJRfRZeLDG+WZaHYCk3Wtfl6Ngzo4=
|
||||||
|
gorm.io/gorm v1.30.1/go.mod h1:8Z33v652h4//uMA76KjeDH8mJXPm1QNCYrMeatR0DOE=
|
||||||
1
laniakea
Submodule
1
laniakea
Submodule
Submodule laniakea added at 13eb3d45de
26
main.go
Normal file
26
main.go
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"kurumibot/database"
|
||||||
|
"kurumibot/plugins"
|
||||||
|
|
||||||
|
"kurumibot/laniakea"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
database.Connect()
|
||||||
|
bot := laniakea.NewBot(&laniakea.BotSettings{
|
||||||
|
Token: "",
|
||||||
|
Debug: true,
|
||||||
|
Prefixes: laniakea.LoadPrefixesFromEnv(),
|
||||||
|
UseRequestLogger: true,
|
||||||
|
LoggerBasePath: "./logs/",
|
||||||
|
})
|
||||||
|
bot = bot.ErrorTemplate("Во время выполнения команды произошла ошибка!\nСообщите об этом разработчику!\n\n%s")
|
||||||
|
plugins.RegisterEconomy(bot)
|
||||||
|
plugins.RegisterWaifus(bot)
|
||||||
|
plugins.RegisterAdmin(bot)
|
||||||
|
|
||||||
|
defer bot.Close()
|
||||||
|
bot.Run()
|
||||||
|
}
|
||||||
28
plugins/admin.go
Normal file
28
plugins/admin.go
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
package plugins
|
||||||
|
|
||||||
|
import (
|
||||||
|
"kurumibot/database"
|
||||||
|
|
||||||
|
"kurumibot/laniakea"
|
||||||
|
)
|
||||||
|
|
||||||
|
func RegisterAdmin(b *laniakea.Bot) {
|
||||||
|
p := laniakea.NewPlugin("Admin")
|
||||||
|
p = p.Command(uploadPhoto, "uploadPhoto")
|
||||||
|
|
||||||
|
b.AddPlugins(p.Build())
|
||||||
|
}
|
||||||
|
|
||||||
|
func uploadPhoto(ctx *laniakea.MsgContext) {
|
||||||
|
user, err := database.GetOrCreateUser(ctx.FromID, ctx.Msg.From.FirstName)
|
||||||
|
if err != nil {
|
||||||
|
ctx.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !user.Group.IsAdmin {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
photoId := ctx.Msg.Photo[0].FileID
|
||||||
|
ctx.AnswerPhoto(photoId, photoId)
|
||||||
|
}
|
||||||
356
plugins/economy.go
Normal file
356
plugins/economy.go
Normal file
@@ -0,0 +1,356 @@
|
|||||||
|
package plugins
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"kurumibot/database"
|
||||||
|
"kurumibot/utils"
|
||||||
|
"math"
|
||||||
|
"math/rand/v2"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"kurumibot/laniakea"
|
||||||
|
|
||||||
|
"github.com/shopspring/decimal"
|
||||||
|
)
|
||||||
|
|
||||||
|
func RegisterEconomy(bot *laniakea.Bot) {
|
||||||
|
economy := laniakea.NewPlugin("Economy")
|
||||||
|
economy = economy.Command(profile, "profile", "профиль")
|
||||||
|
economy = economy.Command(work, "work", "работать")
|
||||||
|
economy = economy.Command(collect, "collect", "собрать")
|
||||||
|
economy = economy.Command(code, "code", "код")
|
||||||
|
|
||||||
|
economy = economy.Command(vacancies, "vacancies", "вакансии")
|
||||||
|
economy = economy.Command(getAJob, "getajob", "устроиться")
|
||||||
|
|
||||||
|
economy = economy.Command(aboutGroup, "group", "о группе")
|
||||||
|
|
||||||
|
economy = economy.Command(about, "about", "о боте")
|
||||||
|
|
||||||
|
go passiveIncome(bot)
|
||||||
|
|
||||||
|
bot.AddPlugins(economy.Build())
|
||||||
|
}
|
||||||
|
|
||||||
|
func about(ctx *laniakea.MsgContext) {
|
||||||
|
out := []string{
|
||||||
|
"Версия Go: 1.23.4",
|
||||||
|
fmt.Sprintf("Версия laniakea: %s", laniakea.VERSION_STRING),
|
||||||
|
}
|
||||||
|
ctx.Answer(strings.Join(out, "\n"))
|
||||||
|
}
|
||||||
|
|
||||||
|
func passiveIncome(b *laniakea.Bot) {
|
||||||
|
for {
|
||||||
|
users, err := database.GetAllUsers()
|
||||||
|
if err != nil {
|
||||||
|
b.Logger().Error(err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, user := range users {
|
||||||
|
if user.Business == nil && user.Maid == nil && user.Miner == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if time.Now().Before(user.IncomeTime.Add(time.Hour * 3)) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
moneyIncome := decimal.NewFromInt(0)
|
||||||
|
expIncome := decimal.NewFromInt(0)
|
||||||
|
btcIncome := decimal.NewFromInt(0)
|
||||||
|
|
||||||
|
if user.Business != nil {
|
||||||
|
moneyIncome = moneyIncome.Add(user.Business.Income).Mul(user.Group.Multiplier)
|
||||||
|
}
|
||||||
|
if user.Maid != nil {
|
||||||
|
expIncome = expIncome.Add(user.Maid.Income).Mul(user.Group.Multiplier)
|
||||||
|
}
|
||||||
|
if user.Miner != nil {
|
||||||
|
btcIncome = btcIncome.Add(user.Miner.Income).Mul(user.Group.Multiplier)
|
||||||
|
}
|
||||||
|
|
||||||
|
waifus, err := database.GetUserWaifus(user.ID)
|
||||||
|
if err != nil {
|
||||||
|
b.Logger().Error(err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
for _, waifu := range waifus {
|
||||||
|
moneyIncome = moneyIncome.Mul(waifu.MoneyBonus)
|
||||||
|
expIncome = expIncome.Mul(waifu.ExpBonus)
|
||||||
|
btcIncome = btcIncome.Mul(waifu.MoneyBonus)
|
||||||
|
}
|
||||||
|
|
||||||
|
expIncome = expIncome.Mul(decimal.NewFromFloat(0.25))
|
||||||
|
moneyIncome = moneyIncome.Mul(decimal.NewFromFloat(0.25))
|
||||||
|
btcIncome = btcIncome.Mul(decimal.NewFromFloat(0.25))
|
||||||
|
|
||||||
|
user.ExpIncome += int(expIncome.IntPart())
|
||||||
|
user.MoneyIncome = user.MoneyIncome.Add(moneyIncome)
|
||||||
|
user.BtcIncome = user.BtcIncome.Add(btcIncome)
|
||||||
|
user.IncomeTime = time.Now().Add(-time.Hour * 2)
|
||||||
|
database.Database.Save(user)
|
||||||
|
|
||||||
|
b.Logger().Debug(fmt.Sprintf("У %d было пассивно собрано. След. сбор через час\n", user.TelegramID))
|
||||||
|
}
|
||||||
|
|
||||||
|
time.Sleep(time.Second * 5)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func profile(ctx *laniakea.MsgContext) {
|
||||||
|
user, err := database.GetOrCreateUser(ctx.FromID, ctx.Update.Message.From.FirstName)
|
||||||
|
if err != nil {
|
||||||
|
ctx.Answer(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
pair := "нет"
|
||||||
|
if user.Pair != nil {
|
||||||
|
pair = user.Pair.Name
|
||||||
|
}
|
||||||
|
|
||||||
|
fraction := "нет"
|
||||||
|
if user.Fraction != nil {
|
||||||
|
fraction = user.Fraction.Name
|
||||||
|
}
|
||||||
|
_, needXp := database.CountLevel(user.Exp)
|
||||||
|
|
||||||
|
out := []string{
|
||||||
|
fmt.Sprintf("🖤%s, %s🖤", user.Greeting, user.Name),
|
||||||
|
fmt.Sprintf("🆔ID: %d", user.ID),
|
||||||
|
fmt.Sprintf("🔰Фракция: %s", fraction),
|
||||||
|
fmt.Sprintf("📊Группа: %s (ID: %d, x%.1f)", user.Group.Name, user.Group.ID, user.Group.Multiplier.InexactFloat64()),
|
||||||
|
fmt.Sprintf("❤️Пара: %s", pair),
|
||||||
|
fmt.Sprintf("💡Уровень: %d (%d опыта, %d опыта до повышения)", user.Level, user.Exp, needXp-user.Exp),
|
||||||
|
fmt.Sprintf("💴Баланс: %s¥ %s, %s₿", utils.DecimalComma(&user.Balance), utils.Short(user.Balance.String()), utils.DecimalComma(&user.BTC)),
|
||||||
|
fmt.Sprintf("💼Работа: %s (ID: %d)", user.Work.Name, user.Work.ID),
|
||||||
|
fmt.Sprintf("🚘Авто: %s (ID: %d)", user.Auto.Name, user.Auto.ID),
|
||||||
|
fmt.Sprintf("🏢Бизнес: %s (ID: %d)", user.Business.Name, user.Business.ID),
|
||||||
|
fmt.Sprintf("👩🦳Горничная: %s (ID: %d)", user.Maid.Name, user.Maid.ID),
|
||||||
|
fmt.Sprintf("🖥Майнер: %s (ID: %d)", user.Miner.Name, user.Miner.ID),
|
||||||
|
}
|
||||||
|
ctx.Answer(strings.Join(out, "\n"))
|
||||||
|
}
|
||||||
|
|
||||||
|
func work(ctx *laniakea.MsgContext) {
|
||||||
|
user, err := database.GetOrCreateUser(ctx.FromID, ctx.Update.Message.From.FirstName)
|
||||||
|
if err != nil {
|
||||||
|
ctx.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if time.Now().Before(user.WorkTime.Add(time.Minute * 10)) {
|
||||||
|
nextTime := time.Since(user.WorkTime.Add(time.Minute * 10))
|
||||||
|
seconds := int(math.Round(math.Abs(nextTime.Seconds())))
|
||||||
|
minutes := seconds / 60
|
||||||
|
seconds -= minutes * 60
|
||||||
|
ctx.Answer(fmt.Sprintf("Приходи через %02d:%02d", minutes, seconds))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
work := user.Work
|
||||||
|
exp := rand.IntN(work.MaxExp-work.MinExp) + work.MinExp
|
||||||
|
// Count exp
|
||||||
|
expToAdd := decimal.NewFromInt(int64(exp)).Mul(user.Group.Multiplier)
|
||||||
|
// Count money
|
||||||
|
moneyToAdd := work.MoneyIncome.Mul(user.Group.Multiplier)
|
||||||
|
|
||||||
|
waifus, err := database.GetUserWaifus(user.ID)
|
||||||
|
if err != nil {
|
||||||
|
ctx.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for _, waifu := range waifus {
|
||||||
|
expToAdd = expToAdd.Mul(waifu.ExpBonus)
|
||||||
|
moneyToAdd = moneyToAdd.Mul(waifu.MoneyBonus)
|
||||||
|
}
|
||||||
|
user.Exp += int(expToAdd.IntPart())
|
||||||
|
user.Balance = user.Balance.Add(moneyToAdd)
|
||||||
|
user.WorkTime = time.Now()
|
||||||
|
user.Level, _ = database.CountLevel(user.Exp)
|
||||||
|
database.Database.Save(user)
|
||||||
|
ctx.Answer(fmt.Sprintf("Ты заработал %s¥ и %d опыта.\nПриходи через 10 минут.", utils.DecimalComma(&work.MoneyIncome), expToAdd.IntPart()))
|
||||||
|
}
|
||||||
|
|
||||||
|
func collect(ctx *laniakea.MsgContext) {
|
||||||
|
user, err := database.GetOrCreateUser(ctx.FromID, ctx.Update.Message.From.FirstName)
|
||||||
|
if err != nil {
|
||||||
|
ctx.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if user.Business == nil && user.Maid == nil && user.Miner == nil {
|
||||||
|
ctx.Answer("Нечего собирать!")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if time.Now().Before(user.IncomeTime.Add(time.Hour * 2)) {
|
||||||
|
nextTime := time.Since(user.IncomeTime.Add(time.Hour * 2))
|
||||||
|
seconds := int(math.Round(math.Abs(nextTime.Seconds())))
|
||||||
|
minutes := seconds / 60
|
||||||
|
seconds -= minutes * 60
|
||||||
|
hours := minutes / 60
|
||||||
|
minutes -= hours * 60
|
||||||
|
ctx.Answer(fmt.Sprintf("Приходи через %02d:%02d:%02d", hours, minutes, seconds))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
moneyIncome := decimal.NewFromInt(0)
|
||||||
|
expIncome := decimal.NewFromInt(0)
|
||||||
|
btcIncome := decimal.NewFromInt(0)
|
||||||
|
|
||||||
|
if user.Business != nil {
|
||||||
|
moneyIncome = moneyIncome.Add(user.Business.Income).Mul(user.Group.Multiplier)
|
||||||
|
}
|
||||||
|
if user.Maid != nil {
|
||||||
|
expIncome = expIncome.Add(user.Maid.Income).Mul(user.Group.Multiplier)
|
||||||
|
}
|
||||||
|
if user.Miner != nil {
|
||||||
|
btcIncome = btcIncome.Add(user.Miner.Income).Mul(user.Group.Multiplier)
|
||||||
|
}
|
||||||
|
|
||||||
|
waifus, err := database.GetUserWaifus(user.ID)
|
||||||
|
if err != nil {
|
||||||
|
ctx.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, waifu := range waifus {
|
||||||
|
moneyIncome = moneyIncome.Mul(waifu.MoneyBonus)
|
||||||
|
expIncome = expIncome.Mul(waifu.ExpBonus)
|
||||||
|
btcIncome = btcIncome.Mul(waifu.MoneyBonus)
|
||||||
|
}
|
||||||
|
|
||||||
|
incomeText := []string{}
|
||||||
|
|
||||||
|
if moneyIncome.IntPart() > 0 {
|
||||||
|
incomeText = append(incomeText, fmt.Sprintf("%s¥", utils.DecimalComma(&moneyIncome)))
|
||||||
|
}
|
||||||
|
if expIncome.IntPart() > 0 {
|
||||||
|
incomeText = append(incomeText, fmt.Sprintf("%d опыта", expIncome.IntPart()))
|
||||||
|
}
|
||||||
|
if btcIncome.InexactFloat64() > 0 {
|
||||||
|
incomeText = append(incomeText, fmt.Sprintf("%.6f₿", btcIncome.InexactFloat64()))
|
||||||
|
}
|
||||||
|
|
||||||
|
passiveIncomeText := []string{}
|
||||||
|
if user.MoneyIncome.IntPart() > 0 {
|
||||||
|
user.Balance = user.Balance.Add(user.MoneyIncome)
|
||||||
|
passiveIncomeText = append(passiveIncomeText, fmt.Sprintf("%s¥", utils.DecimalComma(&user.MoneyIncome)))
|
||||||
|
user.MoneyIncome = decimal.NewFromInt(0)
|
||||||
|
}
|
||||||
|
if user.ExpIncome > 0 {
|
||||||
|
user.Exp += user.ExpIncome
|
||||||
|
passiveIncomeText = append(passiveIncomeText, fmt.Sprintf("%d опыта", user.ExpIncome))
|
||||||
|
user.ExpIncome = 0
|
||||||
|
}
|
||||||
|
if user.BtcIncome.InexactFloat64() > 0 {
|
||||||
|
user.BTC = user.BTC.Add(user.BtcIncome)
|
||||||
|
passiveIncomeText = append(passiveIncomeText, fmt.Sprintf("%.6f₿", user.BtcIncome.InexactFloat64()))
|
||||||
|
user.BtcIncome = decimal.NewFromFloat(0.0000000)
|
||||||
|
}
|
||||||
|
|
||||||
|
user.Balance = user.Balance.Add(moneyIncome)
|
||||||
|
user.Exp += int(expIncome.IntPart())
|
||||||
|
user.Level, _ = database.CountLevel(user.Exp)
|
||||||
|
user.BTC = user.BTC.Add(btcIncome)
|
||||||
|
user.IncomeTime = time.Now()
|
||||||
|
|
||||||
|
database.Database.Save(user)
|
||||||
|
|
||||||
|
out := []string{
|
||||||
|
fmt.Sprintf("Ты собрал %s.", strings.Join(incomeText, ", ")),
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(passiveIncomeText) > 0 {
|
||||||
|
out = append(out, fmt.Sprintf("Пока тебя не было, было собрано %s.", strings.Join(passiveIncomeText, ", ")))
|
||||||
|
}
|
||||||
|
|
||||||
|
out = append(out, "Приходи через 02:00:00")
|
||||||
|
|
||||||
|
ctx.Answer(strings.Join(out, "\n"))
|
||||||
|
}
|
||||||
|
|
||||||
|
func code(ctx *laniakea.MsgContext) {
|
||||||
|
// user, err := database.Get
|
||||||
|
}
|
||||||
|
|
||||||
|
func vacancies(ctx *laniakea.MsgContext) {
|
||||||
|
works, err := database.GetAllWorks()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
ctx.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
out := []string{
|
||||||
|
"Список вакансий:",
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, work := range works {
|
||||||
|
out = append(out, fmt.Sprintf("%d) %s", work.ID, work.Name))
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.Answer(strings.Join(out, "\n"))
|
||||||
|
}
|
||||||
|
|
||||||
|
func getAJob(ctx *laniakea.MsgContext) {
|
||||||
|
if len(ctx.Args) == 0 {
|
||||||
|
ctx.Answer("Недостаточно аргументов")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
user, err := database.GetOrCreateUser(ctx.FromID, ctx.Msg.From.FirstName)
|
||||||
|
if err != nil {
|
||||||
|
ctx.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
workId, err := strconv.Atoi(ctx.Args[0])
|
||||||
|
if err != nil {
|
||||||
|
ctx.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
work, err := database.GetWorkById(workId)
|
||||||
|
if err != nil {
|
||||||
|
ctx.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if user.Level < work.RequiredLevel {
|
||||||
|
ctx.Answer("Уровень слишком низкий для этой работы!")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
user.WorkID = workId
|
||||||
|
user.Work = work
|
||||||
|
database.Database.Save(user)
|
||||||
|
ctx.Answer("Ты успешно устроился на работу!")
|
||||||
|
}
|
||||||
|
|
||||||
|
func aboutGroup(ctx *laniakea.MsgContext) {
|
||||||
|
user, err := database.GetOrCreateUser(ctx.FromID, ctx.Msg.From.FirstName)
|
||||||
|
if err != nil {
|
||||||
|
ctx.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
group := user.Group
|
||||||
|
out := []string{
|
||||||
|
fmt.Sprintf("%s, %s!", user.Greeting, user.Name),
|
||||||
|
fmt.Sprintf("📝Твоя группа: %s", group.Name),
|
||||||
|
fmt.Sprintf("📉Твоя скидка: %.0f%%", 100-group.Sale.InexactFloat64()*100),
|
||||||
|
fmt.Sprintf("📈Твой множитель: x%.2f", group.Multiplier.InexactFloat64()),
|
||||||
|
fmt.Sprintf("👩🏼Максимум вайфу: %d", group.MaxWaifus),
|
||||||
|
}
|
||||||
|
if group.IsVip {
|
||||||
|
out = append(out, "🎏Доступ к ВИП функциям: ✅")
|
||||||
|
}
|
||||||
|
if group.IsAdmin {
|
||||||
|
out = append(out, "🖥️Доступ к админ функциям: ✅")
|
||||||
|
}
|
||||||
|
if group.IsVip {
|
||||||
|
out = append(out, "🔓Бета-тестер: ✅")
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.Answer(strings.Join(out, "\n"))
|
||||||
|
}
|
||||||
7
plugins/relations.go
Normal file
7
plugins/relations.go
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
package plugins
|
||||||
|
|
||||||
|
import "kurumibot/laniakea"
|
||||||
|
|
||||||
|
func RegisterRelations(b *laniakea.Bot) {
|
||||||
|
|
||||||
|
}
|
||||||
175
plugins/waifus.go
Normal file
175
plugins/waifus.go
Normal file
@@ -0,0 +1,175 @@
|
|||||||
|
package plugins
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"kurumibot/database"
|
||||||
|
"kurumibot/utils"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"kurumibot/laniakea"
|
||||||
|
)
|
||||||
|
|
||||||
|
func RegisterWaifus(bot *laniakea.Bot) {
|
||||||
|
waifus := laniakea.NewPlugin("Waifus")
|
||||||
|
|
||||||
|
waifus.Command(myWaifu, "mywaifu", "моивайфу")
|
||||||
|
waifus.Command(sellWaifu, "sellwaifu")
|
||||||
|
waifus.Command(waifuList, "wlist", "waifulist", "влист", "вайфулист")
|
||||||
|
waifus.Command(waifuInfo, "winfo", "waifuinfo", "винфо")
|
||||||
|
waifus.Command(waifuSearch, "wsearch", "waifusearch", "впоиск")
|
||||||
|
|
||||||
|
bot.AddPlugins(waifus.Build())
|
||||||
|
}
|
||||||
|
|
||||||
|
func myWaifu(ctx *laniakea.MsgContext) {
|
||||||
|
user, err := database.GetUser(ctx.FromID)
|
||||||
|
if err != nil {
|
||||||
|
ctx.Answer(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
out := []string{
|
||||||
|
fmt.Sprintf("%s, %s!", user.Greeting, user.Name),
|
||||||
|
"Список твоих вайфу:",
|
||||||
|
}
|
||||||
|
|
||||||
|
waifus, err := database.GetUserWaifus(user.ID)
|
||||||
|
if err != nil {
|
||||||
|
ctx.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for _, w := range waifus {
|
||||||
|
s := fmt.Sprintf("*%s* из \"*%s*\" (%d☆, ID: %d)", w.Name, w.Fandom, w.Rarity, w.ID)
|
||||||
|
out = append(out, s)
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.Answer(strings.Join(out, "\n"))
|
||||||
|
}
|
||||||
|
|
||||||
|
func sellWaifu(ctx *laniakea.MsgContext) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func waifuList(ctx *laniakea.MsgContext) {
|
||||||
|
waifus, err := database.GetAllWaifus()
|
||||||
|
if err != nil {
|
||||||
|
ctx.Answer(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
out := []string{}
|
||||||
|
|
||||||
|
for _, w := range waifus {
|
||||||
|
var owner string
|
||||||
|
if w.Owner == nil {
|
||||||
|
owner = "нет"
|
||||||
|
} else {
|
||||||
|
owner = w.Owner.Name
|
||||||
|
}
|
||||||
|
s := fmt.Sprintf("*%s* из \"*%s*\" (%d☆, ID: %d) Владелец: %v", w.Name, w.Fandom, w.Rarity, w.ID, owner)
|
||||||
|
out = append(out, s)
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.Answer(strings.Join(out, "\n"))
|
||||||
|
}
|
||||||
|
|
||||||
|
func waifuInfo(ctx *laniakea.MsgContext) {
|
||||||
|
rawArgs := strings.TrimSpace(ctx.Text)
|
||||||
|
args := strings.Split(rawArgs, " ")
|
||||||
|
if len(args) != 1 {
|
||||||
|
ctx.Answer("Не указан ID вайфу!")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
waifuId, err := strconv.Atoi(args[0])
|
||||||
|
if err != nil {
|
||||||
|
ctx.Answer("Во время выполнения команды произошла ошибка!")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
waifu, err := database.GetWaifuById(waifuId)
|
||||||
|
if err != nil {
|
||||||
|
ctx.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
out := []string{
|
||||||
|
fmt.Sprintf("*%s* из \"*%s*\"", waifu.Name, waifu.Fandom),
|
||||||
|
fmt.Sprintf("Редкость: %d☆", waifu.Rarity),
|
||||||
|
fmt.Sprintf("Бонус к деньгам: x%.2f", waifu.MoneyBonus.InexactFloat64()),
|
||||||
|
fmt.Sprintf("Бонус к опыту: x%.2f", waifu.ExpBonus.InexactFloat64()),
|
||||||
|
fmt.Sprintf("Рыночная стоимость: %s¥", utils.DecimalComma(&waifu.MarketPrice)),
|
||||||
|
}
|
||||||
|
if len(waifu.Image) > 0 {
|
||||||
|
ctx.AnswerPhoto(waifu.Image, strings.Join(out, "\n"))
|
||||||
|
} else {
|
||||||
|
ctx.Answer(strings.Join(out, "\n"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func waifuSearch(ctx *laniakea.MsgContext) {
|
||||||
|
user, err := database.GetOrCreateUser(ctx.FromID, ctx.Msg.From.FirstName)
|
||||||
|
if err != nil {
|
||||||
|
ctx.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if time.Now().Before(user.WaifuSearchTime.Add(time.Hour * 4)) {
|
||||||
|
ctx.Answer("Вайфу можно искать раз в 4 часа.")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
count, err := database.GetFreeWaifusCount()
|
||||||
|
if err != nil {
|
||||||
|
ctx.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if count == 0 {
|
||||||
|
ctx.Answer("Не осталось свободных вайфу... :(\nПопробуй позже или купи на рынке!")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
rand := utils.RandRange(0, 100)
|
||||||
|
if 10 < rand && rand < 90 {
|
||||||
|
ctx.Answer("Ты ничего не нашел!")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var freeWaifus []*database.Waifu
|
||||||
|
rarity := 3
|
||||||
|
if rand == 0 {
|
||||||
|
rarity = 5
|
||||||
|
} else if rand > 0 && rand < 7 {
|
||||||
|
rarity = 4
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println(rarity)
|
||||||
|
|
||||||
|
freeWaifus, err = database.GetFreeWaifusWithRarity(rarity)
|
||||||
|
if err != nil {
|
||||||
|
ctx.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(freeWaifus) == 0 {
|
||||||
|
ctx.Answer("Ты ничего не нашел!")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
findedWaifuIndex := utils.RandRange(0, len(freeWaifus))
|
||||||
|
waifu := freeWaifus[findedWaifuIndex]
|
||||||
|
out := []string{
|
||||||
|
"Ты нашел новую вайфу!",
|
||||||
|
fmt.Sprintf("*%s* из \"*%s*\"", waifu.Name, waifu.Fandom),
|
||||||
|
fmt.Sprintf("Редкость: %d☆", waifu.Rarity),
|
||||||
|
fmt.Sprintf("Бонус к деньгам: x%.2f", waifu.MoneyBonus.InexactFloat64()),
|
||||||
|
fmt.Sprintf("Бонус к опыту: x%.2f", waifu.ExpBonus.InexactFloat64()),
|
||||||
|
fmt.Sprintf("Рыночная стоимость: %s¥", utils.DecimalComma(&waifu.MarketPrice)),
|
||||||
|
}
|
||||||
|
if len(waifu.Image) > 0 {
|
||||||
|
ctx.AnswerPhoto(waifu.Image, strings.Join(out, "\n"))
|
||||||
|
} else {
|
||||||
|
ctx.Answer(strings.Join(out, "\n"))
|
||||||
|
}
|
||||||
|
}
|
||||||
104
utils/humanize.go
Normal file
104
utils/humanize.go
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
package utils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"math/big"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/shopspring/decimal"
|
||||||
|
)
|
||||||
|
|
||||||
|
var NumberNames = map[int]string{
|
||||||
|
1: "тыс.",
|
||||||
|
2: "млн.",
|
||||||
|
3: "млрд.",
|
||||||
|
4: "трлн.",
|
||||||
|
5: "квадрлн.",
|
||||||
|
6: "квинтлн.",
|
||||||
|
7: "секстлн.",
|
||||||
|
8: "септлн.",
|
||||||
|
9: "октлн.",
|
||||||
|
10: "нонилн.",
|
||||||
|
11: "децилн.",
|
||||||
|
12: "ундецилн.",
|
||||||
|
13: "дуодецилн.",
|
||||||
|
}
|
||||||
|
|
||||||
|
func Short(n string) string {
|
||||||
|
d, err := decimal.NewFromString(n)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalln(err)
|
||||||
|
}
|
||||||
|
comma := DecimalComma(&d)
|
||||||
|
sp := strings.Split(comma, "'")
|
||||||
|
if len(sp) == 0 {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("(%s %s)", sp[0], NumberNames[len(sp)-1])
|
||||||
|
}
|
||||||
|
|
||||||
|
// order of magnitude (to a max order)
|
||||||
|
func oomm(n, b *big.Int, maxmag int) (float64, int) {
|
||||||
|
mag := 0
|
||||||
|
m := &big.Int{}
|
||||||
|
for n.Cmp(b) >= 0 {
|
||||||
|
n.DivMod(n, b, m)
|
||||||
|
mag++
|
||||||
|
if mag == maxmag && maxmag >= 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return float64(n.Int64()) + (float64(m.Int64()) / float64(b.Int64())), mag
|
||||||
|
}
|
||||||
|
|
||||||
|
// total order of magnitude
|
||||||
|
// (same as above, but with no upper limit)
|
||||||
|
func oom(n, b *big.Int) (float64, int) {
|
||||||
|
mag := 0
|
||||||
|
m := &big.Int{}
|
||||||
|
for n.Cmp(b) >= 0 {
|
||||||
|
n.DivMod(n, b, m)
|
||||||
|
mag++
|
||||||
|
}
|
||||||
|
return float64(n.Int64()) + (float64(m.Int64()) / float64(b.Int64())), mag
|
||||||
|
}
|
||||||
|
|
||||||
|
func BigComma(b *big.Int) string {
|
||||||
|
sign := ""
|
||||||
|
if b.Sign() < 0 {
|
||||||
|
sign = "-"
|
||||||
|
b.Abs(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
athousand := big.NewInt(1000)
|
||||||
|
c := (&big.Int{}).Set(b)
|
||||||
|
_, m := oom(c, athousand)
|
||||||
|
parts := make([]string, m+1)
|
||||||
|
j := len(parts) - 1
|
||||||
|
|
||||||
|
mod := &big.Int{}
|
||||||
|
for b.Cmp(athousand) >= 0 {
|
||||||
|
b.DivMod(b, athousand, mod)
|
||||||
|
parts[j] = strconv.FormatInt(mod.Int64(), 10)
|
||||||
|
switch len(parts[j]) {
|
||||||
|
case 2:
|
||||||
|
parts[j] = "0" + parts[j]
|
||||||
|
case 1:
|
||||||
|
parts[j] = "00" + parts[j]
|
||||||
|
}
|
||||||
|
j--
|
||||||
|
}
|
||||||
|
parts[j] = strconv.Itoa(int(b.Int64()))
|
||||||
|
return sign + strings.Join(parts[j:], "'")
|
||||||
|
}
|
||||||
|
|
||||||
|
func DecimalComma(d *decimal.Decimal) string {
|
||||||
|
if d.IsInteger() {
|
||||||
|
return BigComma(d.BigInt())
|
||||||
|
}
|
||||||
|
fmt.Println(d.String())
|
||||||
|
exp := strings.Split(d.String(), ".")[1]
|
||||||
|
return BigComma(d.BigInt()) + "." + exp
|
||||||
|
}
|
||||||
7
utils/utils.go
Normal file
7
utils/utils.go
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
package utils
|
||||||
|
|
||||||
|
import "math/rand/v2"
|
||||||
|
|
||||||
|
func RandRange(min, max int) int {
|
||||||
|
return rand.IntN(max-min) + min
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user