From 6b6e9a16b09faaede3e7c555e1bbc99e11fcf6f2 Mon Sep 17 00:00:00 2001 From: Zhang Minghan Date: Sat, 9 Sep 2023 11:15:38 +0800 Subject: [PATCH] update card --- api/anonymous.go | 2 +- api/card.go | 69 ++++++++++++++++++++++++++ go.mod | 1 + go.sum | 2 + main.go | 1 + middleware/throttle.go | 1 + plugin/.gitignore | 2 + plugin/card.php | 109 +++++++++++++++++++++++++++++++++++++++++ plugin/error.php | 47 ++++++++++++++++++ plugin/favicon.ico | Bin 0 -> 8945 bytes plugin/utils.php | 31 ++++++++++++ 11 files changed, 264 insertions(+), 1 deletion(-) create mode 100644 api/card.go create mode 100644 plugin/.gitignore create mode 100644 plugin/card.php create mode 100644 plugin/error.php create mode 100644 plugin/favicon.ico create mode 100644 plugin/utils.php diff --git a/api/anonymous.go b/api/anonymous.go index 38662ad..cb0b63f 100644 --- a/api/anonymous.go +++ b/api/anonymous.go @@ -78,7 +78,7 @@ func GetAnonymousResponseWithCache(c *gin.Context, message string, web bool) (st return "", "There was something wrong...", err } - cache.Set(c, fmt.Sprintf(":chatgpt:%s", message), utils.ToJson(AnonymousResponseCache{ + cache.Set(c, fmt.Sprintf(":chatgpt-%v:%s", web, message), utils.ToJson(AnonymousResponseCache{ Keyword: key, Message: res, }), time.Hour*48) diff --git a/api/card.go b/api/card.go new file mode 100644 index 0000000..f1560d8 --- /dev/null +++ b/api/card.go @@ -0,0 +1,69 @@ +package api + +import ( + "github.com/gin-gonic/gin" + "github.com/russross/blackfriday/v2" + "net/http" + "strings" +) + +const maxColumnPerLine = 50 + +func ProcessMarkdownLine(source []byte) string { + segment := strings.Split(string(source), "\n") + var result []rune + for _, line := range segment { + data := []rune(line) + length := len([]rune(line)) + if length < maxColumnPerLine { + result = append(result, data...) + result = append(result, '\n') + } else { + for i := 0; i < length; i += maxColumnPerLine { + if i+maxColumnPerLine < length { + result = append(result, data[i:i+maxColumnPerLine]...) + result = append(result, '\n') + } else { + result = append(result, data[i:]...) + result = append(result, '\n') + } + } + } + } + return string(result) +} + +func MarkdownConvert(text string) string { + if text == "" { + return "" + } + + result := blackfriday.Run([]byte(text)) + return string(result) +} + +func CardAPI(c *gin.Context) { + var body AnonymousRequestBody + if err := c.ShouldBindJSON(&body); err != nil { + c.JSON(http.StatusBadRequest, gin.H{ + "error": "invalid request body", + }) + } + message := strings.TrimSpace(body.Message) + if len(message) == 0 { + c.JSON(http.StatusBadRequest, gin.H{ + "error": "message is empty", + }) + return + } + + key, res, err := GetAnonymousResponseWithCache(c, message, body.Web) + if err != nil { + res = "There was something wrong..." + } + + c.JSON(http.StatusOK, gin.H{ + "message": MarkdownConvert(res), + "keyword": key, + }) +} diff --git a/go.mod b/go.mod index ba6cf29..6f42afd 100644 --- a/go.mod +++ b/go.mod @@ -36,6 +36,7 @@ require ( github.com/modern-go/reflect2 v1.0.2 // indirect github.com/pelletier/go-toml/v2 v2.0.8 // indirect github.com/pkoukk/tiktoken-go v0.1.5 // indirect + github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/spf13/afero v1.9.5 // indirect github.com/spf13/cast v1.5.1 // indirect github.com/spf13/jwalterweatherman v1.1.0 // indirect diff --git a/go.sum b/go.sum index 65db482..0ad7135 100644 --- a/go.sum +++ b/go.sum @@ -203,6 +203,8 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= +github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/spf13/afero v1.9.5 h1:stMpOSZFs//0Lv29HduCmli3GUfpFoF3Y1Q/aXj/wVM= github.com/spf13/afero v1.9.5/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ= github.com/spf13/cast v1.5.1 h1:R+kOtfhWQE6TVQzY+4D7wJLBgkdVasCEFxSUBYBYIlA= diff --git a/main.go b/main.go index 30b3105..4d388a1 100644 --- a/main.go +++ b/main.go @@ -24,6 +24,7 @@ func main() { app.Use(auth.Middleware()) app.POST("/anonymous", api.AnonymousAPI) + app.POST("/card", api.CardAPI) app.GET("/chat", api.ChatAPI) app.POST("/login", auth.LoginAPI) app.POST("/state", auth.StateAPI) diff --git a/middleware/throttle.go b/middleware/throttle.go index e0bf987..753739e 100644 --- a/middleware/throttle.go +++ b/middleware/throttle.go @@ -28,6 +28,7 @@ func (l *Limiter) RateLimit(ctx *gin.Context, rds *redis.Client, ip string, path var limits = map[string]Limiter{ "/login": {Duration: 10, Count: 5}, "/anonymous": {Duration: 60, Count: 15}, + "/card": {Duration: 1, Count: 5}, "/user": {Duration: 1, Count: 1}, "/package": {Duration: 1, Count: 2}, "/quota": {Duration: 1, Count: 2}, diff --git a/plugin/.gitignore b/plugin/.gitignore new file mode 100644 index 0000000..706fd07 --- /dev/null +++ b/plugin/.gitignore @@ -0,0 +1,2 @@ +.idea +.vscode diff --git a/plugin/card.php b/plugin/card.php new file mode 100644 index 0000000..f494e6c --- /dev/null +++ b/plugin/card.php @@ -0,0 +1,109 @@ +", "

", $resp['message'])); +$msgHeight = substr_count($resp['message'], "\n") * 20 + strlen($msg) * 0.15 + substr_count($resp['message'], " + + ChatGPT + ChatGPT Card + + + + + + chatnio + + + + OpenAI + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/plugin/error.php b/plugin/error.php new file mode 100644 index 0000000..4283d76 --- /dev/null +++ b/plugin/error.php @@ -0,0 +1,47 @@ + + + + Error + Error Card + + + + + Sorry, there is something wrong... + + + + + \ No newline at end of file diff --git a/plugin/favicon.ico b/plugin/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..688435b916fb8356243c82148602d76ed8160b12 GIT binary patch literal 8945 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[^\S ]+/', '/[^\S ]+ ', '<', '\\1', '><', ':', '{', '}'); + return preg_replace($search, $replace, $buffer); +} + +function fetch($message, $web): array|string|null +{ + $opts = array('http' => + array( + 'method' => 'POST', + 'header' => 'Content-type: application/json', + 'content' => json_encode(array('message' => $message, 'web' => $web)) + ) + ); + + $context = stream_context_create($opts); + $response = @file_get_contents("http://localhost:8094/card", false, $context); + $ok = $response !== false; + return $ok ? json_decode($response, true) : null; +} + +function get($param, $default = null) +{ + return $_GET[$param] ?? $default; +}