From 6938f05efba642cd0697af65dcaba2ba87506f71 Mon Sep 17 00:00:00 2001 From: mcoo <26184088+mcoo@users.noreply.github.com> Date: Sun, 30 Apr 2023 20:45:26 +0800 Subject: [PATCH] fix: pkg name err --- go.mod | 6 +- main.go | 8 +- plugin/S/S.go | 2 +- plugin/S/S_host.go | 2 +- plugin/admin.go | 8 +- plugin/builder/cmd/build.go | 2 +- plugin/builder/cmd/new.go | 144 +++++++++++++++++++++++ plugin/builder/main.go | 3 +- plugin/callOPQApi.go | 6 +- plugin/httpApi.go | 4 +- plugin/plugin.go | 12 +- plugin/repository/repository.go | 2 +- plugins/animeCharacter/animeCharacter.go | 6 +- plugins/example/example.go | 4 +- plugins/signPlugin/signPlugin.go | 8 +- plugins/systemInfo/systemInfo.go | 6 +- proto/generate/generate.go | 29 +++-- proto/library/systemInfo/systemInfo.go | 4 +- proto/opq_host.pb.go | 101 +++++++++++++++- web/docs/index.md | 2 +- 20 files changed, 304 insertions(+), 55 deletions(-) create mode 100644 plugin/builder/cmd/new.go diff --git a/go.mod b/go.mod index a0c6d8e..7524506 100644 --- a/go.mod +++ b/go.mod @@ -1,14 +1,16 @@ -module Yui +module github.com/opq-osc/Yui go 1.19 require ( github.com/charmbracelet/log v0.2.1 github.com/ethereum/go-ethereum v1.11.6 + github.com/go-toolsmith/astcopy v1.1.0 github.com/google/uuid v1.3.0 github.com/imroc/req/v3 v3.33.2 github.com/knqyf263/go-plugin v0.7.1-0.20230420183704-82cf9090ca1e github.com/mailru/easyjson v0.7.7 + github.com/manifoldco/promptui v0.9.0 github.com/mcoo/OPQBot v0.2.2-0.20230415115049-02b00e2cf9e1 github.com/opq-osc/OPQBot/v2 v2.0.0-20230427091225-f73faded2e3b github.com/robfig/cron/v3 v3.0.1 @@ -26,6 +28,7 @@ require ( github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect github.com/btcsuite/btcd/btcec/v2 v2.2.0 // indirect github.com/charmbracelet/lipgloss v0.7.1 // indirect + github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect github.com/fsnotify/fsnotify v1.6.0 // indirect github.com/go-logfmt/logfmt v0.6.0 // indirect @@ -72,6 +75,7 @@ require ( github.com/yusufpapurcu/wmi v1.2.2 // indirect golang.org/x/crypto v0.4.0 // indirect golang.org/x/exp v0.0.0-20230206171751-46f607a40771 // indirect + golang.org/x/exp/typeparams v0.0.0-20230203172020-98cc5a0785f9 // indirect golang.org/x/mod v0.10.0 // indirect golang.org/x/net v0.9.0 // indirect golang.org/x/sys v0.7.0 // indirect diff --git a/main.go b/main.go index 6a573da..ea77e9e 100644 --- a/main.go +++ b/main.go @@ -1,12 +1,12 @@ package main import ( - _ "Yui/config" - "Yui/cron" - "Yui/opq" - "Yui/plugin" "context" "github.com/charmbracelet/log" + _ "github.com/opq-osc/Yui/config" + "github.com/opq-osc/Yui/cron" + "github.com/opq-osc/Yui/opq" + "github.com/opq-osc/Yui/plugin" "github.com/spf13/viper" ) diff --git a/plugin/S/S.go b/plugin/S/S.go index cd51cce..c3d622f 100644 --- a/plugin/S/S.go +++ b/plugin/S/S.go @@ -3,9 +3,9 @@ package S import ( - "Yui/proto" "context" "github.com/opq-osc/OPQBot/v2/events" + "github.com/opq-osc/Yui/proto" ) func LogInfo(ctx context.Context, msg string) { diff --git a/plugin/S/S_host.go b/plugin/S/S_host.go index 3d3b783..21b39b8 100644 --- a/plugin/S/S_host.go +++ b/plugin/S/S_host.go @@ -3,9 +3,9 @@ package S import ( - "Yui/opq" "github.com/opq-osc/OPQBot/v2/apiBuilder" "github.com/opq-osc/OPQBot/v2/events" + "github.com/opq-osc/Yui/opq" ) func GetApi(event events.IEvent) apiBuilder.IMainFunc { diff --git a/plugin/admin.go b/plugin/admin.go index 990e738..8dc4b99 100644 --- a/plugin/admin.go +++ b/plugin/admin.go @@ -1,13 +1,13 @@ package plugin import ( - "Yui/plugin/S" - "Yui/plugin/meta" - "Yui/plugin/repository" - "Yui/session" "context" "fmt" "github.com/opq-osc/OPQBot/v2/events" + "github.com/opq-osc/Yui/plugin/S" + "github.com/opq-osc/Yui/plugin/meta" + "github.com/opq-osc/Yui/plugin/repository" + "github.com/opq-osc/Yui/session" "github.com/spf13/cast" "github.com/spf13/viper" "strings" diff --git a/plugin/builder/cmd/build.go b/plugin/builder/cmd/build.go index c64e9ce..8366991 100644 --- a/plugin/builder/cmd/build.go +++ b/plugin/builder/cmd/build.go @@ -4,7 +4,6 @@ Copyright © 2023 NAME HERE package cmd import ( - "Yui/plugin/meta" "bytes" "crypto/ecdsa" "crypto/rand" @@ -14,6 +13,7 @@ import ( "encoding/hex" "encoding/json" "github.com/ethereum/go-ethereum/crypto" + "github.com/opq-osc/Yui/plugin/meta" "github.com/spf13/cobra" "github.com/spf13/viper" "io" diff --git a/plugin/builder/cmd/new.go b/plugin/builder/cmd/new.go new file mode 100644 index 0000000..3bf94c5 --- /dev/null +++ b/plugin/builder/cmd/new.go @@ -0,0 +1,144 @@ +/* +Copyright © 2023 NAME HERE +*/ +package cmd + +import ( + "encoding/json" + "github.com/manifoldco/promptui" + "github.com/opq-osc/Yui/plugin/meta" + "github.com/spf13/cobra" + "os" + "os/exec" + "path/filepath" + "strings" +) + +// newCmd represents the new command +var newCmd = &cobra.Command{ + Use: "new", + Short: "创建一个新的插件", + Long: `创建一个新的插件`, + RunE: func(cmd *cobra.Command, args []string) error { + prompt := promptui.Prompt{ + Label: "plugin name", + } + var err error + pluginInfo := &meta.PluginMeta{} + pluginInfo.PluginName, err = prompt.Run() + if err != nil { + return err + } + prompt = promptui.Prompt{Label: "plugin description"} + pluginInfo.Description, err = prompt.Run() + if err != nil { + return err + } + prompt = promptui.Prompt{Label: "author"} + pluginInfo.Author, err = prompt.Run() + if err != nil { + return err + } + prompt = promptui.Prompt{Label: "author url"} + pluginInfo.Url, err = prompt.Run() + if err != nil { + return err + } + err = os.MkdirAll(pluginInfo.PluginName, 0777) + if err != nil { + return err + } + goFile = strings.ReplaceAll(goFile, "{{.pluginName}}", pluginInfo.PluginName) + err = os.WriteFile(filepath.Join(pluginInfo.PluginName, pluginInfo.PluginName+".go"), []byte(goFile), 0777) + if err != nil { + return err + } + GoCmd := exec.Command("go", "mod", "init", pluginInfo.PluginName) + GoCmd.Dir = "./" + pluginInfo.PluginName + GoCmd.Stderr = os.Stderr + err = GoCmd.Run() + if err != nil { + return err + } + GoCmd = exec.Command("go", "mod", "tidy") + GoCmd.Dir = "./" + pluginInfo.PluginName + GoCmd.Stderr = os.Stderr + err = GoCmd.Run() + if err != nil { + return err + } + metaInfo, err := json.Marshal(pluginInfo) + if err != nil { + return err + } + err = os.WriteFile(filepath.Join(pluginInfo.PluginName, "meta.json"), []byte(metaInfo), 0777) + if err != nil { + return err + } + return nil + }, +} + +func init() { + rootCmd.AddCommand(newCmd) + + // Here you will define your flags and configuration settings. + + // Cobra supports Persistent Flags which will work for this command + // and all subcommands, e.g.: + // newCmd.PersistentFlags().String("foo", "", "A help for foo") + + // Cobra supports local flags which will only run when this command + // is called directly, e.g.: + // newCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle") +} + +var goFile = `//go:build tinygo.wasm + +package main + +import ( + "github.com/opq-osc/Yui/plugin/meta" + "github.com/opq-osc/Yui/proto" + "context" + "github.com/knqyf263/go-plugin/types/known/emptypb" +) + +type {{.pluginName}} struct { +} + +func (p {{.pluginName}}) OnRemoteCallEvent(ctx context.Context, req *proto.RemoteCallReq) (*proto.RemoteCallReply, error) { + //TODO implement me + panic("implement me") +} + +func (p {{.pluginName}}) OnCronEvent(ctx context.Context, req *proto.CronEventReq) (*emptypb.Empty, error) { + return &emptypb.Empty{}, nil +} + +func (p {{.pluginName}}) OnFriendMsg(ctx context.Context, msg *proto.CommonMsg) (*emptypb.Empty, error) { + return &emptypb.Empty{}, nil +} + +func (p {{.pluginName}}) OnPrivateMsg(ctx context.Context, msg *proto.CommonMsg) (*emptypb.Empty, error) { + return &emptypb.Empty{}, nil +} + +func (p {{.pluginName}}) OnGroupMsg(ctx context.Context, msg *proto.CommonMsg) (*emptypb.Empty, error) { + return &emptypb.Empty{}, nil +} +func (p {{.pluginName}}) Unload(ctx context.Context, _ *emptypb.Empty) (*emptypb.Empty, error) { + return &emptypb.Empty{}, nil + +} +func (p {{.pluginName}}) Init(ctx context.Context, _ *emptypb.Empty) (*proto.InitReply, error) { + return &proto.InitReply{ + Ok: true, + Message: "Success", + }, nil +} + +func main() { + proto.RegisterEvent({{.pluginName}}{}) +} +` diff --git a/plugin/builder/main.go b/plugin/builder/main.go index 3d77d13..5362f05 100644 --- a/plugin/builder/main.go +++ b/plugin/builder/main.go @@ -1,10 +1,9 @@ /* Copyright © 2023 NAME HERE - */ package main -import "Yui/plugin/builder/cmd" +import "github.com/opq-osc/Yui/plugin/builder/cmd" func main() { cmd.Execute() diff --git a/plugin/callOPQApi.go b/plugin/callOPQApi.go index 4d3c79d..000b78a 100644 --- a/plugin/callOPQApi.go +++ b/plugin/callOPQApi.go @@ -1,12 +1,12 @@ package plugin import ( - "Yui/opq" - "Yui/plugin/meta" - "Yui/proto" "context" "fmt" "github.com/opq-osc/OPQBot/v2/apiBuilder" + "github.com/opq-osc/Yui/opq" + "github.com/opq-osc/Yui/plugin/meta" + "github.com/opq-osc/Yui/proto" ) func (p *Plugin) SendFriendMsg(ctx context.Context, request *proto.MsgReq) (*proto.SendReply, error) { diff --git a/plugin/httpApi.go b/plugin/httpApi.go index 3a81109..0ff8c4c 100644 --- a/plugin/httpApi.go +++ b/plugin/httpApi.go @@ -1,12 +1,12 @@ package plugin import ( - "Yui/plugin/meta" - "Yui/proto" "context" "fmt" "github.com/charmbracelet/log" "github.com/imroc/req/v3" + "github.com/opq-osc/Yui/plugin/meta" + "github.com/opq-osc/Yui/proto" "github.com/spf13/viper" ) diff --git a/plugin/plugin.go b/plugin/plugin.go index e6b2a62..efe9b26 100644 --- a/plugin/plugin.go +++ b/plugin/plugin.go @@ -1,12 +1,6 @@ package plugin import ( - "Yui/cron" - "Yui/opq" - "Yui/plugin/meta" - "Yui/proto" - "Yui/proto/library/systemInfo" - systemInfoExport "Yui/proto/library/systemInfo/export" "bytes" "context" "crypto/ecdsa" @@ -19,6 +13,12 @@ import ( "github.com/ethereum/go-ethereum/crypto" "github.com/knqyf263/go-plugin/types/known/emptypb" "github.com/opq-osc/OPQBot/v2/events" + "github.com/opq-osc/Yui/cron" + "github.com/opq-osc/Yui/opq" + "github.com/opq-osc/Yui/plugin/meta" + "github.com/opq-osc/Yui/proto" + "github.com/opq-osc/Yui/proto/library/systemInfo" + systemInfoExport "github.com/opq-osc/Yui/proto/library/systemInfo/export" cron2 "github.com/robfig/cron/v3" "github.com/spf13/viper" "github.com/tetratelabs/wazero" diff --git a/plugin/repository/repository.go b/plugin/repository/repository.go index 7bccc0e..13fc8ad 100644 --- a/plugin/repository/repository.go +++ b/plugin/repository/repository.go @@ -1,11 +1,11 @@ package repository import ( - "Yui/plugin/meta" "context" "encoding/json" "fmt" "github.com/imroc/req/v3" + "github.com/opq-osc/Yui/plugin/meta" "github.com/spf13/viper" ) diff --git a/plugins/animeCharacter/animeCharacter.go b/plugins/animeCharacter/animeCharacter.go index e45fcf2..b3f3f7c 100644 --- a/plugins/animeCharacter/animeCharacter.go +++ b/plugins/animeCharacter/animeCharacter.go @@ -3,12 +3,12 @@ package main import ( - "Yui/plugin/S" - "Yui/plugins/animeCharacter/config" - "Yui/proto" "context" "fmt" "github.com/knqyf263/go-plugin/types/known/emptypb" + "github.com/opq-osc/Yui/plugin/S" + "github.com/opq-osc/Yui/plugins/animeCharacter/config" + "github.com/opq-osc/Yui/proto" "github.com/tidwall/gjson" "math/rand" "time" diff --git a/plugins/example/example.go b/plugins/example/example.go index 9c97682..1a5897b 100644 --- a/plugins/example/example.go +++ b/plugins/example/example.go @@ -3,12 +3,12 @@ package main import ( - "Yui/plugin/meta" - "Yui/proto" "context" "encoding/base64" "github.com/google/uuid" "github.com/knqyf263/go-plugin/types/known/emptypb" + "github.com/opq-osc/Yui/plugin/meta" + "github.com/opq-osc/Yui/proto" "os" ) diff --git a/plugins/signPlugin/signPlugin.go b/plugins/signPlugin/signPlugin.go index b546054..38ba392 100644 --- a/plugins/signPlugin/signPlugin.go +++ b/plugins/signPlugin/signPlugin.go @@ -3,13 +3,13 @@ package main import ( - "Yui/plugin/S" - anime "Yui/plugins/animeCharacter/config" - "Yui/plugins/signPlugin/config" - "Yui/proto" "context" "fmt" "github.com/knqyf263/go-plugin/types/known/emptypb" + "github.com/opq-osc/Yui/plugin/S" + anime "github.com/opq-osc/Yui/plugins/animeCharacter/config" + "github.com/opq-osc/Yui/plugins/signPlugin/config" + "github.com/opq-osc/Yui/proto" "strconv" "strings" "time" diff --git a/plugins/systemInfo/systemInfo.go b/plugins/systemInfo/systemInfo.go index cf26d9a..2394cee 100644 --- a/plugins/systemInfo/systemInfo.go +++ b/plugins/systemInfo/systemInfo.go @@ -3,11 +3,11 @@ package main import ( - "Yui/plugin/S" - "Yui/proto" - "Yui/proto/library/systemInfo/export" "context" "fmt" + "github.com/opq-osc/Yui/plugin/S" + "github.com/opq-osc/Yui/proto" + "github.com/opq-osc/Yui/proto/library/systemInfo/export" "github.com/knqyf263/go-plugin/types/known/emptypb" ) diff --git a/proto/generate/generate.go b/proto/generate/generate.go index ebd1ae8..cf2168d 100644 --- a/proto/generate/generate.go +++ b/proto/generate/generate.go @@ -1,6 +1,7 @@ package main import ( + "github.com/go-toolsmith/astcopy" "go/ast" "go/format" "go/parser" @@ -21,21 +22,23 @@ func main() { case *ast.FuncDecl: if v.Recv != nil { if v.Name.Name == "Load" { - v.Name.Name = "LoadWithBytes" - v.Type.Params.List[1].Names[0].Name = "b" - v.Type.Params.List[1].Type.(*ast.Ident).Name = "[]byte" - v.Body.List = v.Body.List[2:] - } - } - case *ast.GenDecl: - if v.Tok.String() == "import" { - for i, j := range v.Specs { - imp := j.(*ast.ImportSpec) - if imp.Name.Name == "os" { - v.Specs = append(v.Specs[:i], v.Specs[i+1:]...) - } + newFunc := astcopy.FuncDecl(v) + newFunc.Name.Name = "LoadWithBytes" + newFunc.Type.Params.List[1].Names[0].Name = "b" + newFunc.Type.Params.List[1].Type.(*ast.Ident).Name = "[]byte" + newFunc.Body.List = newFunc.Body.List[2:] + cursor.InsertAfter(newFunc) } } + //case *ast.GenDecl: + // if v.Tok.String() == "import" { + // for i, j := range v.Specs { + // imp := j.(*ast.ImportSpec) + // if imp.Name.Name == "os" { + // v.Specs = append(v.Specs[:i], v.Specs[i+1:]...) + // } + // } + // } } return true diff --git a/proto/library/systemInfo/systemInfo.go b/proto/library/systemInfo/systemInfo.go index 7760e54..88b8c98 100644 --- a/proto/library/systemInfo/systemInfo.go +++ b/proto/library/systemInfo/systemInfo.go @@ -1,11 +1,11 @@ package systemInfo import ( - "Yui/plugin/meta" - "Yui/proto/library/systemInfo/export" "context" "fmt" "github.com/knqyf263/go-plugin/types/known/emptypb" + "github.com/opq-osc/Yui/plugin/meta" + "github.com/opq-osc/Yui/proto/library/systemInfo/export" "github.com/shirou/gopsutil/v3/cpu" "github.com/shirou/gopsutil/v3/mem" ) diff --git a/proto/opq_host.pb.go b/proto/opq_host.pb.go index 4e699a9..c34a97a 100644 --- a/proto/opq_host.pb.go +++ b/proto/opq_host.pb.go @@ -17,6 +17,7 @@ import ( wazero "github.com/tetratelabs/wazero" api "github.com/tetratelabs/wazero/api" sys "github.com/tetratelabs/wazero/sys" + os "os" ) const ( @@ -354,7 +355,11 @@ type event interface { Event } -func (p *EventPlugin) LoadWithBytes(ctx context.Context, b []byte, hostFunctions Api) (event, error) { +func (p *EventPlugin) Load(ctx context.Context, pluginPath string, hostFunctions Api) (event, error) { + b, err := os.ReadFile(pluginPath) + if err != nil { + return nil, err + } // Create a new runtime so that multiple modules will not conflict r, err := p.newRuntime(ctx) @@ -453,6 +458,100 @@ func (p *EventPlugin) LoadWithBytes(ctx context.Context, b []byte, hostFunctions onremotecallevent: onremotecallevent, }, nil } +func (p *EventPlugin) LoadWithBytes(ctx context.Context, b []byte, hostFunctions Api) (event, error) { + + r, err := p.newRuntime(ctx) + if err != nil { + return nil, err + } + + h := _api{hostFunctions} + + if err := h.Instantiate(ctx, r); err != nil { + return nil, err + } + + code, err := r.CompileModule(ctx, b) + if err != nil { + return nil, err + } + + module, err := r.InstantiateModule(ctx, code, p.moduleConfig) + if err != nil { + + if exitErr, ok := err.(*sys.ExitError); ok && exitErr.ExitCode() != 0 { + return nil, fmt.Errorf("unexpected exit_code: %d", exitErr.ExitCode()) + } else if !ok { + return nil, err + } + } + + apiVersion := module.ExportedFunction("event_api_version") + if apiVersion == nil { + return nil, errors.New("event_api_version is not exported") + } + results, err := apiVersion.Call(ctx) + if err != nil { + return nil, err + } else if len(results) != 1 { + return nil, errors.New("invalid event_api_version signature") + } + if results[0] != EventPluginAPIVersion { + return nil, fmt.Errorf("API version mismatch, host: %d, plugin: %d", EventPluginAPIVersion, results[0]) + } + + init := module.ExportedFunction("event_init") + if init == nil { + return nil, errors.New("event_init is not exported") + } + ongroupmsg := module.ExportedFunction("event_on_group_msg") + if ongroupmsg == nil { + return nil, errors.New("event_on_group_msg is not exported") + } + onfriendmsg := module.ExportedFunction("event_on_friend_msg") + if onfriendmsg == nil { + return nil, errors.New("event_on_friend_msg is not exported") + } + onprivatemsg := module.ExportedFunction("event_on_private_msg") + if onprivatemsg == nil { + return nil, errors.New("event_on_private_msg is not exported") + } + unload := module.ExportedFunction("event_unload") + if unload == nil { + return nil, errors.New("event_unload is not exported") + } + oncronevent := module.ExportedFunction("event_on_cron_event") + if oncronevent == nil { + return nil, errors.New("event_on_cron_event is not exported") + } + onremotecallevent := module.ExportedFunction("event_on_remote_call_event") + if onremotecallevent == nil { + return nil, errors.New("event_on_remote_call_event is not exported") + } + + malloc := module.ExportedFunction("malloc") + if malloc == nil { + return nil, errors.New("malloc is not exported") + } + + free := module.ExportedFunction("free") + if free == nil { + return nil, errors.New("free is not exported") + } + return &eventPlugin{ + runtime: r, + module: module, + malloc: malloc, + free: free, + init: init, + ongroupmsg: ongroupmsg, + onfriendmsg: onfriendmsg, + onprivatemsg: onprivatemsg, + unload: unload, + oncronevent: oncronevent, + onremotecallevent: onremotecallevent, + }, nil +} func (p *eventPlugin) Close(ctx context.Context) (err error) { if r := p.runtime; r != nil { diff --git a/web/docs/index.md b/web/docs/index.md index 553550d..ddaaf80 100644 --- a/web/docs/index.md +++ b/web/docs/index.md @@ -14,7 +14,7 @@ hero: link: /guide/开始 - theme: alt text: GitHub - link: + link: https://github.com/opq-osc/Yui features: - icon: 🍭 title: 简单,易用