From acc9d1473dd21a6caddfc34e7ec8eca4176dcafa Mon Sep 17 00:00:00 2001 From: Yiwen-Chan Date: Sat, 17 Apr 2021 14:24:07 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=8E=A8=20=E4=BC=98=E5=8C=96=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=E7=BB=93=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- runcode/code_runner.go | 258 +++++++++++++++++++++++------------------ 1 file changed, 142 insertions(+), 116 deletions(-) diff --git a/runcode/code_runner.go b/runcode/code_runner.go index bae2ea2e..8b206d35 100644 --- a/runcode/code_runner.go +++ b/runcode/code_runner.go @@ -1,142 +1,168 @@ package runcode import ( - "encoding/json" "fmt" - zero "github.com/wdvxdr1123/ZeroBot" "io/ioutil" "net/http" "net/url" "strings" "time" + + "github.com/tidwall/gjson" + zero "github.com/wdvxdr1123/ZeroBot" + "github.com/wdvxdr1123/ZeroBot/message" ) -func init() { - runAllow := true - runTypes := map[string][2]string{ - "Py2": {"0","py"}, - "Ruby": {"1","rb"}, - "PHP": {"3","php"}, - "Go": {"6","go"}, - "C": {"7","c"}, - "C++": {"7","cpp"}, - "Java": {"8","java"}, - "Rust": {"9","rs"}, - "C#": {"10","cs"}, - "Perl": {"14","pl"}, - "Python": {"15","py3"}, - "Swift": {"16","swift"}, - "Lua": {"17","lua"}, +func init() { + RunAllow := true + table := map[string][2]string{ + "py2": {"0", "py"}, + "ruby": {"1", "rb"}, + "rb": {"1", "rb"}, + "php": {"3", "php"}, + "javascript": {"4", "js"}, + "js": {"4", "js"}, + "node.js": {"4", "js"}, + "scala": {"5", "scala"}, + "go": {"6", "go"}, + "c": {"7", "c"}, + "c++": {"7", "cpp"}, + "cpp": {"7", "cpp"}, + "java": {"8", "java"}, + "rust": {"9", "rs"}, + "rs": {"9", "rs"}, + "c#": {"10", "cs"}, + "cs": {"10", "cs"}, + "csharp": {"10", "cs"}, + "shell": {"10", "sh"}, + "bash": {"10", "sh"}, + "erlang": {"12", "erl"}, + "perl": {"14", "pl"}, + "python": {"15", "py3"}, + "py": {"15", "py3"}, + "swift": {"16", "swift"}, + "lua": {"17", "lua"}, + "pascal": {"18", "pas"}, + "kotlin": {"19", "kt"}, + "kt": {"19", "kt"}, + "r": {"80", "r"}, + "vb": {"84", "vb"}, + "typescript": {"1010", "ts"}, + "ts": {"1010", "ts"}, } - zero.OnCommand("runList").Handle(func(ctx *zero.Ctx) { - ctx.Send(`[使用说明] -Run 语种<<< -代码块 ->>> -[支持语种] -Go || Python || Java || C/C++ || C# || Lua -Rust || PHP || Perl || Ruby || Swift || Py2`) - }) - - zero.OnCommand("runOpen").Handle(func(ctx *zero.Ctx) { - if ctx.Event.UserID == 213864964{ - runAllow = true - ctx.Send(fmt.Sprintf( - "[CQ:at,qq=%d]在线运行代码功能已启用", - ctx.Event.UserID, + zero.OnFullMatch(">runcode help").SetBlock(true).FirstPriority(). + Handle(func(ctx *zero.Ctx) { + ctx.SendChain(message.Text( + "使用说明: ", "\n", + ">runcode [language] [code block]", "\n", + "支持语种: ", "\n", + "Go || Python || C/C++ || C# || Java || Lua ", "\n", + "JavaScript || TypeScript || PHP || Shell ", "\n", + "Kotlin || Rust || Erlang || Ruby || Swift ", "\n", + "R || VB || Py2 || Perl || Pascal || Scala ", "\n", )) - } - }) + }) + zero.OnFullMatch(">runcode on", zero.AdminPermission).SetBlock(true).FirstPriority(). + Handle(func(ctx *zero.Ctx) { + RunAllow = true + ctx.SendChain( + message.Text("> ", ctx.Event.Sender.NickName, "\n"), + message.Text("在线运行代码功能已启用"), + ) + }) - zero.OnCommand("runClose").Handle(func(ctx *zero.Ctx) { - if ctx.Event.UserID == 213864964{ - runAllow = false - ctx.Send(fmt.Sprintf( - "[CQ:at,qq=%d]在线运行代码功能已禁用", - ctx.Event.UserID, - )) - } - }) + zero.OnFullMatch(">runcode off", zero.AdminPermission).SetBlock(true).FirstPriority(). + Handle(func(ctx *zero.Ctx) { + RunAllow = false + ctx.SendChain( + message.Text("> ", ctx.Event.Sender.NickName, "\n"), + message.Text("在线运行代码功能已禁用"), + ) + }) - zero.OnRegex("(?is:Run (.+?)<<<(.+?)>>>)").Handle(func(ctx *zero.Ctx) { - if runAllow==false{ - ctx.Send(fmt.Sprintf( - "[CQ:at,qq=%d]在线运行代码功能已被禁用", - ctx.Event.UserID, - )) - return - } - getType := ctx.State["regex_matched"].([]string)[1] - if runType,exist:=runTypes[getType];exist{ - println("正在尝试执行",getType,"代码块") - getCode := ctx.State["regex_matched"].([]string)[2] - getCode = strings.Replace(getCode,"[","[",-1) - getCode = strings.Replace(getCode,"]","]",-1) - - res := runCode(getCode,runType) - if res["errors"] == "\n\n"{ - ctx.Send(fmt.Sprintf( - "[CQ:at,qq=%d]本次%s语言代码执行结果如下:\n%s", - ctx.Event.UserID, - getType, - res["output"][:len(res["output"])-1], - )) - }else { - ctx.Send(fmt.Sprintf( - "[CQ:at,qq=%d]本次%s语言代码执行失败:%s", - ctx.Event.UserID, - getType, - res["errors"], - )) + zero.OnRegex(`>runcode\s(.+?)\s([\s\S]+)`).SetBlock(true).SecondPriority(). + Handle(func(ctx *zero.Ctx) { + language := ctx.State["regex_matched"].([]string)[1] + language = strings.ToLower(language) + if runType, exist := table[language]; !exist { + // 不支持语言 + ctx.SendChain( + message.Text("> ", ctx.Event.Sender.NickName, "\n"), + message.Text("语言不是受支持的编程语种呢~"), + ) + return + } else { + if RunAllow == false { + // 运行代码被禁用 + ctx.SendChain( + message.Text("> ", ctx.Event.Sender.NickName, "\n"), + message.Text("在线运行代码功能已被禁用"), + ) + return + } + // 执行运行 + block := ctx.State["regex_matched"].([]string)[2] + block = message.UnescapeCQCodeText(block) + if output, err := runCode(block, runType); err != nil { + // 运行失败 + ctx.SendChain( + message.Text("> ", ctx.Event.Sender.NickName, "\n"), + message.Text("ERROR: ", err), + ) + return + } else { + // 运行成功 + ctx.SendChain( + message.Text("> ", ctx.Event.Sender.NickName, "\n"), + message.Text(output), + ) + return + } } - }else { - ctx.Send(fmt.Sprintf( - "[CQ:at,qq=%d][%s]语言不是受支持的编程语种呢~", - ctx.Event.UserID, - getType, - )) - } - }) + }) } -func runCode(code string,runType [2]string) map[string]string { - //对菜鸟api发送数据并返回结果 - result := map[string]string{} +func runCode(code string, runType [2]string) (string, error) { + // 对菜鸟api发送数据并返回结果 api := "https://tool.runoob.com/compile2.php" - headers := map[string]string{ - "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8", - "Referer": "https://c.runoob.com/", - "User-Agent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:87.0) Gecko/20100101 Firefox/87.0", - } - data := map[string]string{ - "code": code, - "token": "4381fe197827ec87cbac9552f14ec62a", - "stdin": "", - "language": runType[0], - "fileext": runType[1], - } - json.Unmarshal(netPost(api,data,headers),&result) - return result -} -func netPost(api string,data map[string]string,headers map[string]string) []byte { - //发送POST请求获取返回数据 + header := http.Header{ + "Content-Type": []string{"application/x-www-form-urlencoded; charset=UTF-8"}, + "Referer": []string{"https://c.runoob.com/"}, + "User-Agent": []string{"Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:87.0) Gecko/20100101 Firefox/87.0"}, + } + + val := url.Values{ + "code": []string{code}, + "token": []string{"4381fe197827ec87cbac9552f14ec62a"}, + "stdin": []string{""}, + "language": []string{runType[0]}, + "fileext": []string{runType[1]}, + } + // 发送请求 client := &http.Client{ Timeout: time.Duration(6 * time.Second), } - - param := url.Values{} - for key,value := range data{ - param.Set(key,value) + request, _ := http.NewRequest("POST", api, strings.NewReader(val.Encode())) + request.Header = header + body, err := client.Do(request) + if err != nil { + return "", err } - - request,_ := http.NewRequest("POST",api,strings.NewReader(param.Encode())) - for key,value := range headers{ - request.Header.Add(key,value) + defer body.Body.Close() + if body.StatusCode != http.StatusOK { + return "", fmt.Errorf("code %d", body.StatusCode) } - res,_ := client.Do(request) - defer res.Body.Close() - result,_ := ioutil.ReadAll(res.Body) - return result -} \ No newline at end of file + res, err := ioutil.ReadAll(body.Body) + if err != nil { + return "", err + } + // 结果处理 + content := gjson.ParseBytes(res) + if e := content.Get("errors").Str; e != "\n\n" { + return "", fmt.Errorf(e) + } + output := content.Get("output").Str + return output[:len(output)-1], nil +}