Files
MonkeyCode/backend/internal/extension/usecase/extension.go
2025-07-23 17:13:24 +08:00

125 lines
2.9 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package usecase
import (
"context"
"fmt"
"io"
"log/slog"
"net/http"
"os"
"strings"
"sync"
"github.com/chaitin/MonkeyCode/backend/config"
"github.com/chaitin/MonkeyCode/backend/db"
"github.com/chaitin/MonkeyCode/backend/domain"
"github.com/chaitin/MonkeyCode/backend/pkg/cvt"
"github.com/chaitin/MonkeyCode/backend/pkg/version"
"github.com/chaitin/MonkeyCode/backend/pkg/vsix"
)
type ExtensionUsecase struct {
logger *slog.Logger
repo domain.ExtensionRepo
config *config.Config
mu sync.Mutex
}
func NewExtensionUsecase(
repo domain.ExtensionRepo,
config *config.Config,
logger *slog.Logger,
) domain.ExtensionUsecase {
e := &ExtensionUsecase{
repo: repo,
config: config,
mu: sync.Mutex{},
logger: logger,
}
return e
}
// GetByVersion implements domain.ExtensionUsecase.
func (e *ExtensionUsecase) GetByVersion(ctx context.Context, version string) (*domain.Extension, error) {
ee, err := e.repo.GetByVersion(ctx, version)
if err != nil {
return nil, err
}
return cvt.From(ee, &domain.Extension{}), nil
}
// Latest implements domain.ExtensionUsecase.
func (e *ExtensionUsecase) Latest(ctx context.Context) (*domain.Extension, error) {
ee, err := e.repo.Latest(ctx)
if err != nil {
return nil, err
}
return cvt.From(ee, &domain.Extension{}), nil
}
func (e *ExtensionUsecase) SyncLatest() {
e.innerSync()
}
func (e *ExtensionUsecase) innerSync() {
v := strings.ReplaceAll(version.Version, "v", "")
logger := e.logger.With("fn", "syncLatest").With("current", v)
latest, err := e.repo.Latest(context.Background())
if err != nil {
if strings.Contains(err.Error(), "extension not found") {
latest = &db.Extension{}
} else {
logger.With("error", err).Error("获取最新插件版本失败")
return
}
}
if v == latest.Version {
return
}
e.download(v)
}
func (e *ExtensionUsecase) download(version string) {
logger := e.logger.With("fn", "download")
url := fmt.Sprintf("%s/monkeycode/vsixs/monkeycode-%s.vsix", e.config.Extension.Baseurl, version)
logger.With("url", url).With("version", version).Debug("发现新版本开始下载")
resp, err := http.Get(url)
if err != nil {
logger.With("error", err).Error("下载插件失败")
return
}
defer resp.Body.Close()
filename := fmt.Sprintf("/app/static/monkeycode-%s.vsix", version)
f, err := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE, 0644)
if err != nil {
logger.With("error", err).Error("创建文件失败")
return
}
_, err = io.Copy(f, resp.Body)
if err != nil {
logger.With("error", err).Error("复制文件内容失败")
return
}
f.Close()
logger.Debug("下载插件成功")
if err := vsix.ValidateVsix(filename); err != nil {
logger.With("error", err).Error("校验插件失败")
os.Remove(filename)
return
}
if _, err := e.repo.Save(context.Background(), &db.Extension{
Version: version,
Path: filename,
}); err != nil {
logger.With("error", err).Error("保存插件版本信息失败")
os.Remove(filename)
return
}
}