feat: add command calc

This commit is contained in:
2025-12-20 00:03:43 +08:00
parent b1c19872fe
commit 25f2a5b92c
4 changed files with 120 additions and 0 deletions

1
go.mod
View File

@@ -3,6 +3,7 @@ module github.com/awfufu/go-hurobot
go 1.25.5
require (
github.com/Knetic/govaluate v3.0.0+incompatible
github.com/awfufu/qbot v0.2.2
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510
gopkg.in/yaml.v3 v3.0.1

2
go.sum
View File

@@ -1,3 +1,5 @@
github.com/Knetic/govaluate v3.0.0+incompatible h1:7o6+MAPhYTCF0+fdvoz1xDedhRb4f6s9Tn1Tt7/WTEg=
github.com/Knetic/govaluate v3.0.0+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
github.com/awfufu/qbot v0.2.2 h1:rl7+j6JNjGzjjO5AHNqRXdM09Gwc+mQGsgBerJYVfVg=
github.com/awfufu/qbot v0.2.2/go.mod h1:t6pYm54N7/YrxoMYFerZe2qx0t505iPeQQpTJvTNY+8=
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4=

116
internal/cmds/calc.go Normal file
View File

@@ -0,0 +1,116 @@
package cmds
import (
"fmt"
"math"
"github.com/Knetic/govaluate"
"github.com/awfufu/qbot"
)
const calcHelpMsg string = `Calculates the result of a mathematical expression.
Usage: /calc -l|<expression>
Options:
-l List supported functions
Example: /calc 1+1`
var calcCommand *Command = &Command{
Name: "calc",
HelpMsg: calcHelpMsg,
Permission: getCmdPermLevel("calc"),
NeedRawMsg: false,
MinArgs: 2,
Exec: calcExec,
}
func unaryMathOp(op func(float64) float64) func(args ...any) (any, error) {
return func(args ...any) (any, error) {
if len(args) != 1 {
return nil, fmt.Errorf("expected 1 argument")
}
val, ok := args[0].(float64)
if !ok {
return nil, fmt.Errorf("argument must be a number")
}
return op(val), nil
}
}
func binaryMathOp(op func(float64, float64) float64) func(args ...any) (any, error) {
return func(args ...any) (any, error) {
if len(args) != 2 {
return nil, fmt.Errorf("expected 2 arguments")
}
val1, ok1 := args[0].(float64)
val2, ok2 := args[1].(float64)
if !ok1 || !ok2 {
return nil, fmt.Errorf("arguments must be numbers")
}
return op(val1, val2), nil
}
}
var calcFunctions = map[string]govaluate.ExpressionFunction{
"sin": unaryMathOp(math.Sin),
"cos": unaryMathOp(math.Cos),
"tan": unaryMathOp(math.Tan),
"asin": unaryMathOp(math.Asin),
"acos": unaryMathOp(math.Acos),
"atan": unaryMathOp(math.Atan),
"sqrt": unaryMathOp(math.Sqrt),
"cbrt": unaryMathOp(math.Cbrt),
"abs": unaryMathOp(math.Abs),
"ceil": unaryMathOp(math.Ceil),
"floor": unaryMathOp(math.Floor),
"round": unaryMathOp(math.Round),
"ln": unaryMathOp(math.Log),
"log2": unaryMathOp(math.Log2),
"log10": unaryMathOp(math.Log10),
"exp": unaryMathOp(math.Exp),
"pow": binaryMathOp(math.Pow),
"max": binaryMathOp(math.Max),
"min": binaryMathOp(math.Min),
}
func calcExec(b *qbot.Sender, msg *qbot.Message) {
exprString := ""
for _, item := range msg.Array[1:] {
if item.Type() == qbot.TextType {
exprString += item.Text()
} else {
b.SendGroupMsg(msg.GroupID, "invalid expression")
return
}
}
if exprString == "-l" {
var functionsList string
for k := range calcFunctions {
functionsList += k + ", "
}
functionsList = functionsList[:len(functionsList)-2]
b.SendGroupMsg(msg.GroupID, "supported functions: "+functionsList)
return
}
expression, err := govaluate.NewEvaluableExpressionWithFunctions(exprString, calcFunctions)
if err != nil {
b.SendGroupMsg(msg.GroupID, fmt.Sprintf("%v", err))
return
}
result, err := expression.Evaluate(map[string]any{
"pi": math.Pi,
"PI": math.Pi,
"π": math.Pi,
"e": math.E,
"E": math.E,
})
if err != nil {
b.SendGroupMsg(msg.GroupID, fmt.Sprintf("%v", err))
return
}
b.SendGroupMsg(msg.GroupID, fmt.Sprintf("%v", result))
}

View File

@@ -39,6 +39,7 @@ func init() {
"sh": shCommand,
"specialtitle": specialtitleCommand,
"which": whichCommand,
"calc": calcCommand,
}
}