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 ARG GIT_COMMIT
WORKDIR /usr/src/ymgb WORKDIR /usr/src/ymgb
COPY go.mod go.sum ./ COPY go.mod go.sum ./
#COPY ./laniakea ./laniakea COPY ./laniakea ./laniakea
RUN --mount=type=cache,target=/go/pkg/mod go mod download -x RUN --mount=type=cache,target=/go/pkg/mod go mod download -x
COPY ./database ./database COPY ./database ./database
COPY ./plugins ./plugins COPY ./plugins ./plugins

View File

@@ -1,9 +1,32 @@
export GIT_COMMIT := $(shell git rev-parse --short HEAD 2>/dev/null || echo "unknown") 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") export BUILD_TIME := $(shell date "+%H:%M:%S %d.%m.%Y")
build: # Проверка наличия golangci-lint
@echo "Building commit $(GIT_COMMIT)" GO_LINT := $(shell command -v golangci-lint 2>/dev/null)
@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 . 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 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" "git.nix13.pw/scuroneko/extypes"
"go.mongodb.org/mongo-driver/v2/bson" "go.mongodb.org/mongo-driver/v2/bson"
"go.mongodb.org/mongo-driver/v2/mongo"
"go.mongodb.org/mongo-driver/v2/mongo/options" "go.mongodb.org/mongo-driver/v2/mongo/options"
) )
@@ -32,15 +33,17 @@ func GetConsoleLogs(db *database.Context) ([]ConsoleLogEntry, error) {
col := database.GetMongoCollection(db, "logs") col := database.GetMongoCollection(db, "logs")
opts := options.Find() opts := options.Find()
opts.SetLimit(5) 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) cursor, err := col.Find(ctx, bson.D{}, opts)
if err != nil { if err != nil {
return nil, err return nil, err
} }
defer cursor.Close(ctx) defer func(cursor *mongo.Cursor, ctx context.Context) {
_ = cursor.Close(ctx)
}(cursor, ctx)
result := make([]ConsoleLogEntry, 0) result := make([]ConsoleLogEntry, 0)
err = cursor.All(ctx, &result) err = cursor.All(ctx, &result)
return result, nil return result, err
} }
type MessageLogEntry struct { type MessageLogEntry struct {
@@ -64,13 +67,15 @@ func GetMessageLogs(db *database.Context) (extypes.Slice[*MessageLogEntry], erro
col := database.GetMongoCollection(db, "msg_logs") col := database.GetMongoCollection(db, "msg_logs")
opts := options.Find() opts := options.Find()
opts.SetLimit(5) 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) cursor, err := col.Find(ctx, bson.D{}, opts)
if err != nil { if err != nil {
return nil, err 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) result := make(extypes.Slice[*MessageLogEntry], 0)
err = cursor.All(ctx, &result) err = cursor.All(ctx, &result)
return result, nil return result, err
} }

9
go.mod
View File

@@ -1,21 +1,22 @@
module ymgb module ymgb
go 1.26.0 go 1.26.1
require ( require (
git.nix13.pw/scuroneko/extypes v1.2.1 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 git.nix13.pw/scuroneko/slog v1.0.2
github.com/google/uuid v1.6.0 github.com/google/uuid v1.6.0
github.com/joho/godotenv v1.5.1 github.com/joho/godotenv v1.5.1
github.com/lib/pq v1.11.2 github.com/lib/pq v1.11.2
github.com/redis/go-redis/v9 v9.18.0 github.com/redis/go-redis/v9 v9.18.0
github.com/shopspring/decimal v1.4.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 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/extypes v1.2.1 => ../go-extypes
//replace git.nix13.pw/scuroneko/slog v1.0.2 => ../slog //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.1 h1:YpjwWWlNmGIDyXOn8zLzqiD+9TyIlPhGFG96P39uBpw=
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= 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 h1:IYrOjnWKL2EAuJYtYNa+luB1vBe6paE8VY/YD+5/RpQ=
git.nix13.pw/scuroneko/extypes v1.2.1/go.mod h1:uZVs8Yo3RrYAG9dMad6qR6lsYY67t+459D9c65QAYAw= 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 h1:vZyUROygxC2d5FJHUQM/30xFEHY1JT/aweDZXA4rm2g=
git.nix13.pw/scuroneko/slog v1.0.2/go.mod h1:3Qm2wzkR5KjwOponMfG7TcGSDjmYaFqRAmLvSPTuWJI= 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= 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/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 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= 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.2 h1:t/IahCJqO71GJYnhOcACiUXlMiiMomMHtxtUthdcBfo=
github.com/vinovest/sqlx v1.7.1/go.mod h1:3fAv74r4iDMv2PpFomADb+vex5ukzfYn4GseC9KngD8= 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 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c=
github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
github.com/xdg-go/scram v1.2.0 h1:bYKF2AEwG5rqd1BumT4gAnvwU/M9nBp2pTSxeZw7Wvs= github.com/xdg-go/scram v1.2.0 h1:bYKF2AEwG5rqd1BumT4gAnvwU/M9nBp2pTSxeZw7Wvs=

10
main.go
View File

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

View File

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

View File

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

View File

@@ -1,6 +1,7 @@
package plugins package plugins
import ( import (
"database/sql"
"encoding/json" "encoding/json"
"fmt" "fmt"
"path/filepath" "path/filepath"
@@ -11,7 +12,6 @@ import (
"git.nix13.pw/scuroneko/laniakea" "git.nix13.pw/scuroneko/laniakea"
"git.nix13.pw/scuroneko/laniakea/tgapi" "git.nix13.pw/scuroneko/laniakea/tgapi"
"git.nix13.pw/scuroneko/laniakea/utils"
"github.com/vinovest/sqlx" "github.com/vinovest/sqlx"
) )
@@ -58,7 +58,9 @@ func execSql(ctx *laniakea.MsgContext, db *database.Context) {
ctx.Error(err) ctx.Error(err)
return return
} }
defer r.Close() defer func(r *sql.Rows) {
_ = r.Close()
}(r)
for r.Next() { for r.Next() {
a := make(map[string]any) a := make(map[string]any)
if err = sqlx.MapScan(r, a); err != nil { if err = sqlx.MapScan(r, a); err != nil {
@@ -96,7 +98,9 @@ func uploadPhoto(ctx *laniakea.MsgContext, _ *database.Context) {
return return
} }
u := tgapi.NewUploader(ctx.Api) u := tgapi.NewUploader(ctx.Api)
defer u.Close() defer func(u *tgapi.Uploader) {
_ = u.Close()
}(u)
content, err := ctx.Api.GetFileByLink(f.FilePath) content, err := ctx.Api.GetFileByLink(f.FilePath)
if err != nil { if err != nil {
ctx.Error(err) ctx.Error(err)
@@ -111,5 +115,5 @@ func uploadPhoto(ctx *laniakea.MsgContext, _ *database.Context) {
ctx.Error(err) ctx.Error(err)
return 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{ out := []string{
fmt.Sprintf("Привет, _%s_!", ctx.From.FirstName), fmt.Sprintf("Привет, _%s_!", ctx.From.FirstName),
fmt.Sprintf("*Выбранная вайфу*: %s", waifu.Name), 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("*Выбранная модель*: %s", rpUser.Model.Name),
fmt.Sprintf("*Использовано токенов*: %d", rpUser.UsedTokens), fmt.Sprintf("*Использовано токенов*: %d", rpUser.UsedTokens),
fmt.Sprintf("*Настройки сжатия*: %d %s", rpUser.CompressLimit, compressText), 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") kb.AddCallbackButtonStyle("Закрыть", laniakea.ButtonStyleDanger, "general.close")
if ctx.CallbackMsgId > 0 { if ctx.CallbackMsgId > 0 {
ctx.EditCallback(strings.Join(out, "\n"), kb) ctx.EditCallbackMarkdown(laniakea.EscapePunctuation(strings.Join(out, "\n")), kb)
ctx.AnswerCbQuery() ctx.AnswerCbQuery()
} else { } 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 { for i, preset := range presets {
out[i] = fmt.Sprintf( out[i] = fmt.Sprintf(
"*%s* - %s", "*%s* - %s",
laniakea.EscapeMarkdown(preset.Name), preset.Description, laniakea.EscapeMarkdownV2(preset.Name), preset.Description,
) )
kb.AddCallbackButton(preset.Name, "rp.preset_set", preset.ID) kb.AddCallbackButton(preset.Name, "rp.preset_set", preset.ID)
} }
kb.AddLine() kb.AddLine()
kb.AddCallbackButtonStyle("Назад", laniakea.ButtonStyleDanger, "rp.info") kb.AddCallbackButtonStyle("Назад", laniakea.ButtonStyleDanger, "rp.info")
ctx.EditCallback(strings.Join(out, "\n"), kb) ctx.EditCallbackMarkdown(strings.Join(out, "\n"), kb)
ctx.AnswerCbQuery() ctx.AnswerCbQuery()
} }
func rpPresetSet(ctx *laniakea.MsgContext, db *database.Context) { func rpPresetSet(ctx *laniakea.MsgContext, db *database.Context) {
@@ -270,7 +270,7 @@ func rpModelList(ctx *laniakea.MsgContext, db *database.Context) {
} }
kb.AddLine() kb.AddLine()
kb.AddCallbackButtonStyle("Назад", laniakea.ButtonStyleDanger, "rp.info") kb.AddCallbackButtonStyle("Назад", laniakea.ButtonStyleDanger, "rp.info")
ctx.EditCallback(strings.Join(out, "\n"), kb) ctx.EditCallbackMarkdown(laniakea.EscapePunctuation(strings.Join(out, "\n")), kb)
ctx.AnswerCbQuery() ctx.AnswerCbQuery()
} }
func rpModelSet(ctx *laniakea.MsgContext, db *database.Context) { func rpModelSet(ctx *laniakea.MsgContext, db *database.Context) {
@@ -424,7 +424,6 @@ func newChatStage2(ctx *laniakea.MsgContext, db *database.Context) {
"Выбери сценарий:", "Выбери сценарий:",
} }
kb := laniakea.NewInlineKeyboard(2) kb := laniakea.NewInlineKeyboard(2)
scenariosIds := make(extypes.Slice[int], 0)
for _, scenario := range scenarios { for _, scenario := range scenarios {
isSelected := selectedScenariosIds.Index(scenario.ID) >= 0 isSelected := selectedScenariosIds.Index(scenario.ID) >= 0
prefix := "" 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)) out = append(out, fmt.Sprintf("%s*%s* - %s", prefix, scenario.Name, scenario.Description))
if isSelected { if isSelected {
scenariosIds = selectedScenariosIds.Remove(scenario.ID) selectedScenariosIds = selectedScenariosIds.Remove(scenario.ID)
} else { } else {
scenariosIds = selectedScenariosIds.Push(scenario.ID) selectedScenariosIds = selectedScenariosIds.Push(scenario.ID)
} }
kb.AddCallbackButtonStyle( kb.AddCallbackButtonStyle(
fmt.Sprintf("%s%s", prefix, scenario.Name), style, 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 { if len(selectedScenariosIds) == 0 {
scenariosIds = append(scenariosIds, 0) selectedScenariosIds = selectedScenariosIds.Push(0)
} }
kb.AddCallbackButtonStyle("Создать", laniakea.ButtonStyleSuccess, "rp.new_chat", utils.AppendToInt(settingId, selectedScenariosIds)...) kb.AddCallbackButtonStyle("Создать", laniakea.ButtonStyleSuccess, "rp.new_chat", utils.AppendToInt(settingId, selectedScenariosIds)...)
kb.AddLine() kb.AddLine()
@@ -657,18 +656,14 @@ func generate(ctx *laniakea.MsgContext, db *database.Context) {
m := ctx.Keyboard("Генерация запущена...", kb) m := ctx.Keyboard("Генерация запущена...", kb)
ctx.SendAction(tgapi.ChatActionTyping) ctx.SendAction(tgapi.ChatActionTyping)
api := openai.NewOpenAIAPI(ai.GPTBaseUrl, "", rpUser.Model.Key) api := openai.NewOpenAIAPI(ai.GPTBaseUrl, "", rpUser.Model.Key)
defer api.Close()
res, err := api.CreateCompletionStream(messages, userMessage, 0.5) res, err := api.CreateCompletionStream(messages, userMessage, 0.5)
if err != nil { if err != nil {
_ = api.Close()
ctx.Error(err) ctx.Error(err)
return return
} }
answerContent := "" answerContent := ""
type DraftQueue struct {
message string
mu sync.Mutex
}
draft := ctx.NewDraft() draft := ctx.NewDraft()
var mu sync.Mutex var mu sync.Mutex
buffer := strings.Builder{} // накапливаем фрагменты buffer := strings.Builder{} // накапливаем фрагменты
@@ -729,13 +724,11 @@ func generate(ctx *laniakea.MsgContext, db *database.Context) {
mu.Lock() mu.Lock()
buffer.WriteString(content) buffer.WriteString(content)
mu.Unlock() mu.Unlock()
// Если нужна искусственная задержка, оставьте:
// time.Sleep(time.Millisecond * 50)
} }
// Завершаем горутину и отправляем последнюю порцию // Завершаем горутину и отправляем последнюю порцию
close(done) close(done)
_ = api.Close()
if answerContent == "" { if answerContent == "" {
if m != nil { if m != nil {
m.Delete() m.Delete()
@@ -775,18 +768,18 @@ func generate(ctx *laniakea.MsgContext, db *database.Context) {
kb = laniakea.NewInlineKeyboard(1) kb = laniakea.NewInlineKeyboard(1)
kb.AddCallbackButtonStyle("🔄 Перегенерировать 🔄", laniakea.ButtonStyleSuccess, "rp.regenerate", counter+2) kb.AddCallbackButtonStyle("🔄 Перегенерировать 🔄", laniakea.ButtonStyleSuccess, "rp.regenerate", counter+2)
//kb.AddButton(laniakea.NewInlineKbButton("Тест").SetStyle(laniakea.ButtonStyleSuccess).SetIconCustomEmojiId("5375155835846534814").SetCallbackData("rp.test")) ctx.Keyboard(answerContent, kb)
ctx.Keyboard(laniakea.EscapeMarkdown(answerContent), kb)
// Auto compress // Auto compress
compressMethod := rpUser.CompressMethod compressMethod := rpUser.CompressMethod
if compressMethod == "messages" { switch compressMethod {
case "messages":
if counter+2 >= rpUser.CompressLimit { if counter+2 >= rpUser.CompressLimit {
m = ctx.Answer("Запущено сжатие чата…") m = ctx.Answer("Запущено сжатие чата…")
_compress(ctx, db) _compress(ctx, db)
m.Delete() m.Delete()
} }
} else if compressMethod == "tokens" { case "tokens":
if tokens >= rpUser.CompressLimit*1000 { if tokens >= rpUser.CompressLimit*1000 {
m = ctx.Answer("Запущено сжатие чата…") m = ctx.Answer("Запущено сжатие чата…")
_compress(ctx, db) _compress(ctx, db)
@@ -844,7 +837,9 @@ func regenerateResponse(ctx *laniakea.MsgContext, db *database.Context) {
} }
api := openai.NewOpenAIAPI(ai.GPTBaseUrl, "", rpUser.Model.Key) 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)
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 := laniakea.NewInlineKeyboard(1)
kb.AddCallbackButtonStyle("🔄 Перегенерировать 🔄", laniakea.ButtonStyleSuccess, "rp.regenerate", count) 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) { 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) 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) res, err := ai.CompressChat(api, messages)
if err != nil { if err != nil {
ctx.Error(err) ctx.Error(err)
@@ -949,7 +946,7 @@ func _compress(ctx *laniakea.MsgContext, db *database.Context) {
for _, m := range history { for _, m := range history {
if m.Role == "assistant" { if m.Role == "assistant" {
tokens += len(m.Message) tokens += len(m.Message)
err = mdb.UpdateRPChatHistory(db, chatId, m.Role, m.Message, index) _ = mdb.UpdateRPChatHistory(db, chatId, m.Role, m.Message, index)
index++ index++
} else { } else {
break break
@@ -1007,12 +1004,13 @@ func compressSettingStage2(ctx *laniakea.MsgContext, _ *database.Context) {
"При выборе слишком больших значений, некоторые детали могут теряться.", "При выборе слишком больших значений, некоторые детали могут теряться.",
} }
kb := laniakea.NewInlineKeyboard(3) kb := laniakea.NewInlineKeyboard(3)
if method == "messages" { switch method {
case "messages":
out = append(out, "Выбери количество сообщений, после которых будет происходить сжатие чата") out = append(out, "Выбери количество сообщений, после которых будет происходить сжатие чата")
for _, i := range messagesMethodCount { for _, i := range messagesMethodCount {
kb.AddCallbackButton(strconv.Itoa(i), "rp.compress_setting", method, i) kb.AddCallbackButton(strconv.Itoa(i), "rp.compress_setting", method, i)
} }
} else if method == "tokens" { case "tokens":
out = append(out, "Выбери количество токенов, после которых будет происходить сжатие чата") out = append(out, "Выбери количество токенов, после которых будет происходить сжатие чата")
for _, i := range tokenMethodCount { for _, i := range tokenMethodCount {
kb.AddCallbackButton(strconv.Itoa(i), "rp.compress_setting", method, i) 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) { 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{ out := []string{
fmt.Sprintf("Версия Go: %s", runtime.Version()[2:]), 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("Время сборки: %s", utils.BuildTime),
fmt.Sprintf("Git хеш: %s", utils.GitCommit), fmt.Sprintf("Git хеш: %s", utils.GitCommit),
} }

View File

@@ -40,18 +40,18 @@ func Short(n string) string {
} }
// order of magnitude (to a max order) // order of magnitude (to a max order)
func oomm(n, b *big.Int, maxmag int) (float64, int) { //func oomm(n, b *big.Int, maxmag int) (float64, int) {
mag := 0 // mag := 0
m := &big.Int{} // m := &big.Int{}
for n.Cmp(b) >= 0 { // for n.Cmp(b) >= 0 {
n.DivMod(n, b, m) // n.DivMod(n, b, m)
mag++ // mag++
if mag == maxmag && maxmag >= 0 { // if mag == maxmag && maxmag >= 0 {
break // break
} // }
} // }
return float64(n.Int64()) + (float64(m.Int64()) / float64(b.Int64())), mag // return float64(n.Int64()) + (float64(m.Int64()) / float64(b.Int64())), mag
} //}
// total order of magnitude // total order of magnitude
// (same as above, but with no upper limit) // (same as above, but with no upper limit)

View File

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