many changes; using dev laniakea

This commit is contained in:
2026-03-06 14:36:06 +03:00
parent 3ceffa23ae
commit f3f15dad78
13 changed files with 134 additions and 86 deletions

View File

@@ -3,7 +3,7 @@ ARG BUILD_TIME
ARG GIT_COMMIT
WORKDIR /usr/src/ymgb
COPY go.mod go.sum ./
#COPY ./laniakea ./laniakea
COPY ./laniakea ./laniakea
RUN --mount=type=cache,target=/go/pkg/mod go mod download -x
COPY ./database ./database
COPY ./plugins ./plugins

View File

@@ -1,9 +1,32 @@
export GIT_COMMIT := $(shell git rev-parse --short HEAD 2>/dev/null || echo "unknown")
export BUILD_TIME := $(shell date "+%H:%M:%S %d.%m.%Y")
build:
@echo "Building commit $(GIT_COMMIT)"
@echo "Build time $(BUILD_TIME)"
go mod tidy -v -x
docker build --build-arg GIT_COMMIT --build-arg BUILD_TIME -t git.nix13.pw/scuroneko/yaemikobot:dev -f ./Dockerfile .
# Проверка наличия golangci-lint
GO_LINT := $(shell command -v golangci-lint 2>/dev/null)
# Цель: запуск всех проверок кода
check:
@echo "🔍 Running code checks..."
@go mod tidy -v
@go vet ./...
@if [ -n "$(GO_LINT)" ]; then \
echo "✅ golangci-lint found, running..." && \
golangci-lint run --timeout=5m --verbose; \
else \
echo "⚠️ golangci-lint not installed. Install with: curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v1.57.2"; \
fi
@go test -race -v ./... 2>/dev/null || echo "⚠️ Tests skipped or failed (run manually with 'go test -race ./...')"
# Цель: сборка и пуш образа (зависимит от check)
build: check
@echo "🏗️ Building commit $(GIT_COMMIT)"
@echo "⏰ Build time $(BUILD_TIME)"
docker buildx build --build-arg GIT_COMMIT="$(GIT_COMMIT)" --build-arg BUILD_TIME="$(BUILD_TIME)" -t git.nix13.pw/scuroneko/yaemikobot:dev --file ./Dockerfile .
docker push git.nix13.pw/scuroneko/yaemikobot:dev
# Дополнительно: чистка
clean:
@echo "🧹 Cleaning..."
@go clean -modcache -cache -i
.PHONY: check build clean

View File

@@ -7,6 +7,7 @@ import (
"git.nix13.pw/scuroneko/extypes"
"go.mongodb.org/mongo-driver/v2/bson"
"go.mongodb.org/mongo-driver/v2/mongo"
"go.mongodb.org/mongo-driver/v2/mongo/options"
)
@@ -32,15 +33,17 @@ func GetConsoleLogs(db *database.Context) ([]ConsoleLogEntry, error) {
col := database.GetMongoCollection(db, "logs")
opts := options.Find()
opts.SetLimit(5)
opts.SetSort(bson.D{{"_id", 1}})
opts.SetSort(bson.D{{Key: "_id", Value: 1}})
cursor, err := col.Find(ctx, bson.D{}, opts)
if err != nil {
return nil, err
}
defer cursor.Close(ctx)
defer func(cursor *mongo.Cursor, ctx context.Context) {
_ = cursor.Close(ctx)
}(cursor, ctx)
result := make([]ConsoleLogEntry, 0)
err = cursor.All(ctx, &result)
return result, nil
return result, err
}
type MessageLogEntry struct {
@@ -64,13 +67,15 @@ func GetMessageLogs(db *database.Context) (extypes.Slice[*MessageLogEntry], erro
col := database.GetMongoCollection(db, "msg_logs")
opts := options.Find()
opts.SetLimit(5)
opts.SetSort(bson.D{{"_id", 1}})
opts.SetSort(bson.D{{Key: "_id", Value: 1}})
cursor, err := col.Find(ctx, bson.D{}, opts)
if err != nil {
return nil, err
}
defer cursor.Close(ctx)
defer func(cursor *mongo.Cursor, ctx context.Context) {
_ = cursor.Close(ctx)
}(cursor, ctx)
result := make(extypes.Slice[*MessageLogEntry], 0)
err = cursor.All(ctx, &result)
return result, nil
return result, err
}

9
go.mod
View File

@@ -1,21 +1,22 @@
module ymgb
go 1.26.0
go 1.26.1
require (
git.nix13.pw/scuroneko/extypes v1.2.1
git.nix13.pw/scuroneko/laniakea v1.0.0-beta.8
git.nix13.pw/scuroneko/laniakea v1.0.0-beta.11
git.nix13.pw/scuroneko/slog v1.0.2
github.com/google/uuid v1.6.0
github.com/joho/godotenv v1.5.1
github.com/lib/pq v1.11.2
github.com/redis/go-redis/v9 v9.18.0
github.com/shopspring/decimal v1.4.0
github.com/vinovest/sqlx v1.7.1
github.com/vinovest/sqlx v1.7.2
go.mongodb.org/mongo-driver/v2 v2.5.0
)
//replace git.nix13.pw/scuroneko/laniakea v1.0.0-beta.8 => ./laniakea
replace git.nix13.pw/scuroneko/laniakea v1.0.0-beta.11 => ./laniakea
//replace git.nix13.pw/scuroneko/extypes v1.2.1 => ../go-extypes
//replace git.nix13.pw/scuroneko/slog v1.0.2 => ../slog

10
go.sum
View File

@@ -1,9 +1,7 @@
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
filippo.io/edwards25519 v1.1.1 h1:YpjwWWlNmGIDyXOn8zLzqiD+9TyIlPhGFG96P39uBpw=
filippo.io/edwards25519 v1.1.1/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
git.nix13.pw/scuroneko/extypes v1.2.1 h1:IYrOjnWKL2EAuJYtYNa+luB1vBe6paE8VY/YD+5/RpQ=
git.nix13.pw/scuroneko/extypes v1.2.1/go.mod h1:uZVs8Yo3RrYAG9dMad6qR6lsYY67t+459D9c65QAYAw=
git.nix13.pw/scuroneko/laniakea v1.0.0-beta.8 h1:A0O0iXZ7iW0E2Bc9xE9lxrpPoIfc6080anfOHPOSim8=
git.nix13.pw/scuroneko/laniakea v1.0.0-beta.8/go.mod h1:DZgCqOazRzoa+f/GSNuKnTB2wIZ1eJD3cGf34Qya31U=
git.nix13.pw/scuroneko/slog v1.0.2 h1:vZyUROygxC2d5FJHUQM/30xFEHY1JT/aweDZXA4rm2g=
git.nix13.pw/scuroneko/slog v1.0.2/go.mod h1:3Qm2wzkR5KjwOponMfG7TcGSDjmYaFqRAmLvSPTuWJI=
github.com/alitto/pond/v2 v2.6.2 h1:Sphe40g0ILeM1pA2c2K+Th0DGU+pt0A/Kprr+WB24Pw=
@@ -52,8 +50,8 @@ github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp
github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME=
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
github.com/vinovest/sqlx v1.7.1 h1:kdq4v0N9kRLpytWGSWOw4aulOGdQPmIoMR6Y+cTBxow=
github.com/vinovest/sqlx v1.7.1/go.mod h1:3fAv74r4iDMv2PpFomADb+vex5ukzfYn4GseC9KngD8=
github.com/vinovest/sqlx v1.7.2 h1:t/IahCJqO71GJYnhOcACiUXlMiiMomMHtxtUthdcBfo=
github.com/vinovest/sqlx v1.7.2/go.mod h1:o49uG4W/ZYZompljKx5GZ7qx6OFklPjSHXP63nSmND8=
github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c=
github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
github.com/xdg-go/scram v1.2.0 h1:bYKF2AEwG5rqd1BumT4gAnvwU/M9nBp2pTSxeZw7Wvs=

10
main.go
View File

@@ -1,6 +1,8 @@
package main
import (
"log"
"git.nix13.pw/scuroneko/laniakea"
"ymgb/database"
@@ -10,6 +12,7 @@ import (
)
func main() {
log.Println(laniakea.EscapeMarkdownV2("Загрузка..."))
_ = godotenv.Load(".env", ".env.production", ".env.ai")
database.ConnectPostgres()
@@ -17,7 +20,12 @@ func main() {
database.ConnectRedis()
bot := laniakea.NewBot[database.Context](laniakea.LoadOptsFromEnv())
defer bot.Close()
defer func(bot *laniakea.Bot[database.Context]) {
err := bot.Close()
if err != nil {
panic(err)
}
}(bot)
bot = bot.ErrorTemplate("Во время выполнения команды произошла ошибка!\nСообщите об этом разработчику!\n\n%s")
bot = bot.DatabaseContext(&database.Context{
Postgres: database.PostgresDatabase,

View File

@@ -39,7 +39,7 @@ func NewOpenAIAPI(baseURL, token, model string) *API {
proxy, err := url.Parse(os.Getenv("HTTPS_PROXY"))
if err != nil {
logger.Error(err)
logger.Close()
_ = logger.Close()
return nil
}
t := &http.Transport{}
@@ -99,15 +99,11 @@ func (r *Request[P]) doWithContext(ctx context.Context, api *API) (io.ReadCloser
}
if res.StatusCode == 504 || res.StatusCode == 400 || res.StatusCode == 502 {
api.logger.Warn(fmt.Sprintf("[%d] %s", res.StatusCode, res.Status))
res.Body.Close()
_ = res.Body.Close()
return nil, fmt.Errorf("[%d] %s", res.StatusCode, res.Status)
}
return res.Body, nil
}
func (r *Request[P]) do(api *API) (io.ReadCloser, error) {
ctx := context.Background()
return r.doWithContext(ctx, api)
}
func (r *Request[P]) DoWithContext(ctx context.Context, api *API) (AIResponse, error) {
var zero AIResponse
@@ -115,7 +111,9 @@ func (r *Request[P]) DoWithContext(ctx context.Context, api *API) (AIResponse, e
if err != nil {
return zero, err
}
defer body.Close()
defer func(body io.ReadCloser) {
_ = body.Close()
}(body)
data, err := io.ReadAll(body)
if err != nil {
return zero, err
@@ -140,7 +138,9 @@ func (r *Request[P]) DoStreamWithContext(ctx context.Context, api *API) (iter.Se
reader := bufio.NewReader(body)
return func(yield func(AIResponse, error) bool) {
defer body.Close()
defer func(body io.ReadCloser) {
_ = body.Close()
}(body)
var zero AIResponse
for {
line, err := reader.ReadString('\n')
@@ -152,9 +152,7 @@ func (r *Request[P]) DoStreamWithContext(ctx context.Context, api *API) (iter.Se
continue
}
if strings.HasPrefix(line, "data: ") {
line = line[len("data: "):]
}
line = strings.TrimPrefix(line, "data: ")
line = strings.Trim(strings.Trim(strings.TrimSpace(line), "\r"), "\n")
if strings.HasPrefix(line, "[DONE]") {
return
@@ -192,7 +190,7 @@ func (api *API) handleAIError(body []byte) error {
if !ok {
return errors.New("unknown error code")
}
return errors.New(fmt.Sprintf("%v", code))
return fmt.Errorf("%v", code)
}
return errors.New(string(body))
}

View File

@@ -5,8 +5,8 @@ import (
"iter"
)
var MaxRetriesErr = fmt.Errorf("max retries exceeded")
var BadResponseErr = fmt.Errorf("bad_response_status_code")
var ErrMaxRetries = fmt.Errorf("max retries exceeded")
var ErrBadResponse = fmt.Errorf("bad_response_status_code")
type CreateCompletionReq struct {
Model string `json:"model"`

View File

@@ -1,6 +1,7 @@
package plugins
import (
"database/sql"
"encoding/json"
"fmt"
"path/filepath"
@@ -11,7 +12,6 @@ import (
"git.nix13.pw/scuroneko/laniakea"
"git.nix13.pw/scuroneko/laniakea/tgapi"
"git.nix13.pw/scuroneko/laniakea/utils"
"github.com/vinovest/sqlx"
)
@@ -58,7 +58,9 @@ func execSql(ctx *laniakea.MsgContext, db *database.Context) {
ctx.Error(err)
return
}
defer r.Close()
defer func(r *sql.Rows) {
_ = r.Close()
}(r)
for r.Next() {
a := make(map[string]any)
if err = sqlx.MapScan(r, a); err != nil {
@@ -96,7 +98,9 @@ func uploadPhoto(ctx *laniakea.MsgContext, _ *database.Context) {
return
}
u := tgapi.NewUploader(ctx.Api)
defer u.Close()
defer func(u *tgapi.Uploader) {
_ = u.Close()
}(u)
content, err := ctx.Api.GetFileByLink(f.FilePath)
if err != nil {
ctx.Error(err)
@@ -111,5 +115,5 @@ func uploadPhoto(ctx *laniakea.MsgContext, _ *database.Context) {
ctx.Error(err)
return
}
ctx.Answer(utils.EscapeMarkdown(msg.Photo.Last().FileID))
ctx.Answer(msg.Photo.Last().FileID)
}

View File

@@ -111,7 +111,7 @@ func rpInfo(ctx *laniakea.MsgContext, db *database.Context) {
out := []string{
fmt.Sprintf("Привет, _%s_!", ctx.From.FirstName),
fmt.Sprintf("*Выбранная вайфу*: %s", waifu.Name),
fmt.Sprintf("*Выбранный пресет*: %s", laniakea.EscapeMarkdown(rpUser.Preset.Name)),
fmt.Sprintf("*Выбранный пресет*: %s", laniakea.EscapeMarkdownV2(rpUser.Preset.Name)),
fmt.Sprintf("*Выбранная модель*: %s", rpUser.Model.Name),
fmt.Sprintf("*Использовано токенов*: %d", rpUser.UsedTokens),
fmt.Sprintf("*Настройки сжатия*: %d %s", rpUser.CompressLimit, compressText),
@@ -133,10 +133,10 @@ func rpInfo(ctx *laniakea.MsgContext, db *database.Context) {
kb.AddCallbackButtonStyle("Закрыть", laniakea.ButtonStyleDanger, "general.close")
if ctx.CallbackMsgId > 0 {
ctx.EditCallback(strings.Join(out, "\n"), kb)
ctx.EditCallbackMarkdown(laniakea.EscapePunctuation(strings.Join(out, "\n")), kb)
ctx.AnswerCbQuery()
} else {
ctx.Keyboard(strings.Join(out, "\n"), kb)
ctx.KeyboardMarkdown(laniakea.EscapePunctuation(strings.Join(out, "\n")), kb)
}
}
@@ -218,13 +218,13 @@ func rpPresetsList(ctx *laniakea.MsgContext, db *database.Context) {
for i, preset := range presets {
out[i] = fmt.Sprintf(
"*%s* - %s",
laniakea.EscapeMarkdown(preset.Name), preset.Description,
laniakea.EscapeMarkdownV2(preset.Name), preset.Description,
)
kb.AddCallbackButton(preset.Name, "rp.preset_set", preset.ID)
}
kb.AddLine()
kb.AddCallbackButtonStyle("Назад", laniakea.ButtonStyleDanger, "rp.info")
ctx.EditCallback(strings.Join(out, "\n"), kb)
ctx.EditCallbackMarkdown(strings.Join(out, "\n"), kb)
ctx.AnswerCbQuery()
}
func rpPresetSet(ctx *laniakea.MsgContext, db *database.Context) {
@@ -270,7 +270,7 @@ func rpModelList(ctx *laniakea.MsgContext, db *database.Context) {
}
kb.AddLine()
kb.AddCallbackButtonStyle("Назад", laniakea.ButtonStyleDanger, "rp.info")
ctx.EditCallback(strings.Join(out, "\n"), kb)
ctx.EditCallbackMarkdown(laniakea.EscapePunctuation(strings.Join(out, "\n")), kb)
ctx.AnswerCbQuery()
}
func rpModelSet(ctx *laniakea.MsgContext, db *database.Context) {
@@ -424,7 +424,6 @@ func newChatStage2(ctx *laniakea.MsgContext, db *database.Context) {
"Выбери сценарий:",
}
kb := laniakea.NewInlineKeyboard(2)
scenariosIds := make(extypes.Slice[int], 0)
for _, scenario := range scenarios {
isSelected := selectedScenariosIds.Index(scenario.ID) >= 0
prefix := ""
@@ -435,18 +434,18 @@ func newChatStage2(ctx *laniakea.MsgContext, db *database.Context) {
}
out = append(out, fmt.Sprintf("%s*%s* - %s", prefix, scenario.Name, scenario.Description))
if isSelected {
scenariosIds = selectedScenariosIds.Remove(scenario.ID)
selectedScenariosIds = selectedScenariosIds.Remove(scenario.ID)
} else {
scenariosIds = selectedScenariosIds.Push(scenario.ID)
selectedScenariosIds = selectedScenariosIds.Push(scenario.ID)
}
kb.AddCallbackButtonStyle(
fmt.Sprintf("%s%s", prefix, scenario.Name), style,
"rp.new_chat_s2", utils.AppendToInt(settingId, scenariosIds)...,
"rp.new_chat_s2", utils.AppendToInt(settingId, selectedScenariosIds)...,
)
}
if len(scenariosIds) == 0 {
scenariosIds = append(scenariosIds, 0)
if len(selectedScenariosIds) == 0 {
selectedScenariosIds = selectedScenariosIds.Push(0)
}
kb.AddCallbackButtonStyle("Создать", laniakea.ButtonStyleSuccess, "rp.new_chat", utils.AppendToInt(settingId, selectedScenariosIds)...)
kb.AddLine()
@@ -657,18 +656,14 @@ func generate(ctx *laniakea.MsgContext, db *database.Context) {
m := ctx.Keyboard("Генерация запущена...", kb)
ctx.SendAction(tgapi.ChatActionTyping)
api := openai.NewOpenAIAPI(ai.GPTBaseUrl, "", rpUser.Model.Key)
defer api.Close()
res, err := api.CreateCompletionStream(messages, userMessage, 0.5)
if err != nil {
_ = api.Close()
ctx.Error(err)
return
}
answerContent := ""
type DraftQueue struct {
message string
mu sync.Mutex
}
draft := ctx.NewDraft()
var mu sync.Mutex
buffer := strings.Builder{} // накапливаем фрагменты
@@ -729,13 +724,11 @@ func generate(ctx *laniakea.MsgContext, db *database.Context) {
mu.Lock()
buffer.WriteString(content)
mu.Unlock()
// Если нужна искусственная задержка, оставьте:
// time.Sleep(time.Millisecond * 50)
}
// Завершаем горутину и отправляем последнюю порцию
close(done)
_ = api.Close()
if answerContent == "" {
if m != nil {
m.Delete()
@@ -775,18 +768,18 @@ func generate(ctx *laniakea.MsgContext, db *database.Context) {
kb = laniakea.NewInlineKeyboard(1)
kb.AddCallbackButtonStyle("🔄 Перегенерировать 🔄", laniakea.ButtonStyleSuccess, "rp.regenerate", counter+2)
//kb.AddButton(laniakea.NewInlineKbButton("Тест").SetStyle(laniakea.ButtonStyleSuccess).SetIconCustomEmojiId("5375155835846534814").SetCallbackData("rp.test"))
ctx.Keyboard(laniakea.EscapeMarkdown(answerContent), kb)
ctx.Keyboard(answerContent, kb)
// Auto compress
compressMethod := rpUser.CompressMethod
if compressMethod == "messages" {
switch compressMethod {
case "messages":
if counter+2 >= rpUser.CompressLimit {
m = ctx.Answer("Запущено сжатие чата…")
_compress(ctx, db)
m.Delete()
}
} else if compressMethod == "tokens" {
case "tokens":
if tokens >= rpUser.CompressLimit*1000 {
m = ctx.Answer("Запущено сжатие чата…")
_compress(ctx, db)
@@ -844,7 +837,9 @@ func regenerateResponse(ctx *laniakea.MsgContext, db *database.Context) {
}
api := openai.NewOpenAIAPI(ai.GPTBaseUrl, "", rpUser.Model.Key)
defer api.Close()
defer func(api *openai.API) {
_ = api.Close()
}(api)
messages = messages.Pop(count - 2)
messages = messages.Pop(count - 2)
@@ -864,7 +859,7 @@ func regenerateResponse(ctx *laniakea.MsgContext, db *database.Context) {
kb := laniakea.NewInlineKeyboard(1)
kb.AddCallbackButtonStyle("🔄 Перегенерировать 🔄", laniakea.ButtonStyleSuccess, "rp.regenerate", count)
ctx.EditCallback(laniakea.EscapeMarkdown(res.Choices[0].Message.Content), kb)
ctx.EditCallback(res.Choices[0].Message.Content, kb)
}
func compress(ctx *laniakea.MsgContext, db *database.Context) {
@@ -911,7 +906,9 @@ func _compress(ctx *laniakea.MsgContext, db *database.Context) {
}
api := openai.NewOpenAIAPI(ai.GPTBaseUrl, "", user.Model.Key)
defer api.Close()
defer func(api *openai.API) {
_ = api.Close()
}(api)
res, err := ai.CompressChat(api, messages)
if err != nil {
ctx.Error(err)
@@ -949,7 +946,7 @@ func _compress(ctx *laniakea.MsgContext, db *database.Context) {
for _, m := range history {
if m.Role == "assistant" {
tokens += len(m.Message)
err = mdb.UpdateRPChatHistory(db, chatId, m.Role, m.Message, index)
_ = mdb.UpdateRPChatHistory(db, chatId, m.Role, m.Message, index)
index++
} else {
break
@@ -1007,12 +1004,13 @@ func compressSettingStage2(ctx *laniakea.MsgContext, _ *database.Context) {
"При выборе слишком больших значений, некоторые детали могут теряться.",
}
kb := laniakea.NewInlineKeyboard(3)
if method == "messages" {
switch method {
case "messages":
out = append(out, "Выбери количество сообщений, после которых будет происходить сжатие чата")
for _, i := range messagesMethodCount {
kb.AddCallbackButton(strconv.Itoa(i), "rp.compress_setting", method, i)
}
} else if method == "tokens" {
case "tokens":
out = append(out, "Выбери количество токенов, после которых будет происходить сжатие чата")
for _, i := range tokenMethodCount {
kb.AddCallbackButton(strconv.Itoa(i), "rp.compress_setting", method, i)

View File

@@ -20,9 +20,18 @@ func RegisterService() *laniakea.Plugin[database.Context] {
}
func about(ctx *laniakea.MsgContext, _ *database.Context) {
formatVersion := func() string {
parts := strings.Split(laniakea.VersionString, "-")
main := parts[0]
if len(parts) > 1 {
beta := strings.Join(strings.Split(parts[1], "."), " ")
return main + " " + beta
}
return main
}
out := []string{
fmt.Sprintf("Версия Go: %s", runtime.Version()[2:]),
fmt.Sprintf("Версия Laniakea: %s", laniakea.VersionString),
fmt.Sprintf("Версия Laniakea: %s", formatVersion()),
fmt.Sprintf("Время сборки: %s", utils.BuildTime),
fmt.Sprintf("Git хеш: %s", utils.GitCommit),
}

View File

@@ -40,18 +40,18 @@ func Short(n string) string {
}
// 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
}
//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)

View File

@@ -44,7 +44,9 @@ func (a *Hysteria2API) AddUser(username, password string) {
if err != nil {
return
}
defer resp.Body.Close()
defer func(Body io.ReadCloser) {
_ = Body.Close()
}(resp.Body)
body, _ := io.ReadAll(resp.Body)
log.Println(string(body))
}
@@ -60,7 +62,9 @@ func (a *Hysteria2API) GetConnectLink(id int, pass string) (string, error) {
if err != nil {
return "", err
}
defer resp.Body.Close()
defer func(Body io.ReadCloser) {
_ = Body.Close()
}(resp.Body)
data, err := io.ReadAll(resp.Body)
if err != nil {