update card

This commit is contained in:
Zhang Minghan 2023-09-09 11:15:38 +08:00
parent e34df4146b
commit 6b6e9a16b0
11 changed files with 264 additions and 1 deletions

View File

@ -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)

69
api/card.go Normal file
View File

@ -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,
})
}

1
go.mod
View File

@ -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

2
go.sum
View File

@ -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=

View File

@ -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)

View File

@ -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},

2
plugin/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
.idea
.vscode

109
plugin/card.php Normal file
View File

@ -0,0 +1,109 @@
<?php
include 'utils.php';
$dark = get('theme', 'light') === 'dark';
$message = get('message', 'hi');
$web = get('web', 'false') === 'false';
$sign = get('sign', 'false') === 'true';
$resp = fetch($message, $web);
if (!$resp) {
include 'error.php';
exit;
}
$msg = str_replace("&hellip;", "-",
str_replace("<br>", "<br></br>", $resp['message']));
$msgHeight = substr_count($resp['message'], "\n") * 20 + strlen($msg) * 0.15 + substr_count($resp['message'], "<img src=") * 320 + 20;
$height = 90 + $msgHeight;
$header = $dark ? "#fff" : "#0a0a0a";
$background = $dark ? "#000" : "#fffefe";
ob_start('compress');
?>
<svg width="580" viewBox="0 0 420 <?php echo $height + 1 ?>" fill="none" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" role="img" aria-labelledby="descId">
<title id="titleId">ChatGPT</title>
<desc id="descId">ChatGPT Card</desc>
<style>
.header {
font: 600 26px 'Segoe UI', Ubuntu, Sans-Serif !important;
animation: fadeInAnimation 0.8s ease-in-out forwards;
}
.openai {
fill: <?php echo $header ?>;
}
@supports (appearance: auto) {
.header {
font-size: 16px;
}
}
.stat {
font: 600 14px 'Segoe UI', Ubuntu, "Helvetica Neue", Sans-Serif;
fill: <?php echo $header ?>;
}
@supports (appearance: auto) {
.stat {
font-size: 12px;
}
}
.stagger {
opacity: 0;
animation: fadeInAnimation 0.3s ease-in-out forwards;
}
.object {
width: calc(100% - 64px);
}
@keyframes fadeInAnimation {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
</style>
<rect data-testid="card-bg" x="0.5" y="0.5" rx="4.5" height="99%" stroke="#e4e2e2" width="99%" fill="<?php echo $background ?>" stroke-opacity="1"/>
<g data-testid="card-title" transform="translate(30, 25)">
<?php if ($sign) { ?>
<g class="stagger" transform="translate(0, 0)">
<text class="stat" x="330" y="-2">chatnio</text>
</g>
<?php } ?>
<g transform="translate(0, 0)">
<svg class="openai" width="20" height="20" y="6" role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>OpenAI</title><path d="M22.2819 9.8211a5.9847 5.9847 0 0 0-.5157-4.9108 6.0462 6.0462 0 0 0-6.5098-2.9A6.0651 6.0651 0 0 0 4.9807 4.1818a5.9847 5.9847 0 0 0-3.9977 2.9 6.0462 6.0462 0 0 0 .7427 7.0966 5.98 5.98 0 0 0 .511 4.9107 6.051 6.051 0 0 0 6.5146 2.9001A5.9847 5.9847 0 0 0 13.2599 24a6.0557 6.0557 0 0 0 5.7718-4.2058 5.9894 5.9894 0 0 0 3.9977-2.9001 6.0557 6.0557 0 0 0-.7475-7.0729zm-9.022 12.6081a4.4755 4.4755 0 0 1-2.8764-1.0408l.1419-.0804 4.7783-2.7582a.7948.7948 0 0 0 .3927-.6813v-6.7369l2.02 1.1686a.071.071 0 0 1 .038.052v5.5826a4.504 4.504 0 0 1-4.4945 4.4944zm-9.6607-4.1254a4.4708 4.4708 0 0 1-.5346-3.0137l.142.0852 4.783 2.7582a.7712.7712 0 0 0 .7806 0l5.8428-3.3685v2.3324a.0804.0804 0 0 1-.0332.0615L9.74 19.9502a4.4992 4.4992 0 0 1-6.1408-1.6464zM2.3408 7.8956a4.485 4.485 0 0 1 2.3655-1.9728V11.6a.7664.7664 0 0 0 .3879.6765l5.8144 3.3543-2.0201 1.1685a.0757.0757 0 0 1-.071 0l-4.8303-2.7865A4.504 4.504 0 0 1 2.3408 7.872zm16.5963 3.8558L13.1038 8.364 15.1192 7.2a.0757.0757 0 0 1 .071 0l4.8303 2.7913a4.4944 4.4944 0 0 1-.6765 8.1042v-5.6772a.79.79 0 0 0-.407-.667zm2.0107-3.0231l-.142-.0852-4.7735-2.7818a.7759.7759 0 0 0-.7854 0L9.409 9.2297V6.8974a.0662.0662 0 0 1 .0284-.0615l4.8303-2.7866a4.4992 4.4992 0 0 1 6.6802 4.66zM8.3065 12.863l-2.02-1.1638a.0804.0804 0 0 1-.038-.0567V6.0742a4.4992 4.4992 0 0 1 7.3757-3.4537l-.142.0805L8.704 5.459a.7948.7948 0 0 0-.3927.6813zm1.0976-2.3654l2.602-1.4998 2.6069 1.4998v2.9994l-2.5974 1.4997-2.6067-1.4997Z"/></svg>
<text x="28" y="24" class="stat header" data-testid="question"><?php echo $message ?></text>
</g>
</g>
<g data-testid="main-card" transform="translate(0, 48)">
<svg x="0" y="0">
<g transform="translate(0, 0)">
<g class="stagger" style="animation-delay: 600ms">
<foreignObject class="stat object" x="30" y="10" height="<?php echo $msgHeight ?>" data-testid="message">
<style>
.data * {
font: 400 12px 'Segoe UI', Ubuntu, Sans-Serif;
font-weight: normal;
color: <?php echo $header ?>;
}
.data h1, .data h2, .data h3 {
font-weight: bold;
}
.data img {
height: 180px;
}
</style>
<body xmlns="http://www.w3.org/1999/xhtml" class="data">
<?php echo $msg ?>
</body>
</foreignObject>
</g>
</g>
</svg>
</g>
</svg>
<?php
ob_end_flush();
?>

47
plugin/error.php Normal file
View File

@ -0,0 +1,47 @@
<?php
include_once 'utils.php';
$dark = isset($_GET['theme']) && $_GET['theme'] === 'dark';
$header = $dark ? "#fff" : "#434d58";
$background = $dark ? "#000" : "#fffefe";
ob_start('compress');
?>
<svg width="540" viewBox="0 0 660 216" fill="none" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="descId">
<title id="titleId">Error</title>
<desc id="descId">Error Card</desc>
<style>
.header {
font: 600 18px 'Segoe UI', Ubuntu, Sans-Serif;
fill: <?php echo $header ?>;
animation: fadeInAnimation 0.8s ease-in-out forwards
}
@supports(appearance: auto) {
.header {
font-size: 16px
}
}
#rect-mask rect {
animation: fadeInAnimation 1s ease-in-out forwards
}
@keyframes fadeInAnimation {
from {
opacity: 0
}
to {
opacity: 1
}
}
</style>
<rect data-testid="card-bg" x="0.5" y="0.5" rx="4.5" height="99%" stroke="#e4e2e2" width="659" fill="<?php echo $background; ?>" stroke-opacity="1"/>
<g data-testid="card-title" transform="translate(200, 108)">
<g transform="translate(0, 0)">
<text x="0" y="0" class="header" data-testid="header">Sorry, there is something wrong...</text>
</g>
</g>
</svg>
<?php
ob_end_flush();
?>

BIN
plugin/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

31
plugin/utils.php Normal file
View File

@ -0,0 +1,31 @@
<?php
header('Content-Type: image/svg+xml');
header('Cache-Control: no-cache');
function compress($buffer): array|string|null
{
$search = array('/>[^\S ]+/', '/[^\S ]+</', '/(\s)+/', '/> </', '/:\s+/', '/\{\s+/', '/\s+}/');
$replace = array('>', '<', '\\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;
}