Files
pquickmemo/main.go
2026-01-05 16:44:08 +08:00

167 lines
3.6 KiB
Go

package main
import (
"encoding/json"
"fmt"
"net/http"
"os"
"slices"
"time"
"github.com/caarlos0/env/v11"
"github.com/gin-gonic/gin"
)
func ping(c *gin.Context) {
c.String(http.StatusOK, "Pong!")
}
func authMiddleware(appConfig *AppConfig) gin.HandlerFunc {
return func(ctx *gin.Context) {
if appConfig.Secret != "" {
if ctx.Request.Header.Get("PQM_AUTH") != appConfig.Secret {
ctx.Abort()
ctx.String(http.StatusForbidden, "拜拜")
return
}
}
ctx.Next()
}
}
type AppConfig struct {
Secret string `env:"PQM_SECRET"`
DataPath string `env:"PQM_DATA_PATH" envDefault:"data.json"`
}
type PMemo struct {
Content string `json:"content"`
CreatedDate time.Time `json:"created_date"`
}
type PMemoFilter struct {
Till time.Time `json:"till"`
}
type AppData struct {
Memos []PMemo `json:"memos"`
}
func SaveData(appConfig *AppConfig, data *AppData) error {
dat, err := json.Marshal(data)
if err != nil {
return err
}
err = os.WriteFile(appConfig.DataPath, dat, os.FileMode(0o666))
if err != nil {
return err
}
return nil
}
func LoadData(appConfig *AppConfig) AppData {
var appData AppData
dat, err := os.ReadFile(appConfig.DataPath)
if err != nil {
appData = AppData{Memos: []PMemo{}}
SaveData(appConfig, &appData)
return appData
}
err = json.Unmarshal(dat, &appData)
if err != nil {
appData = AppData{Memos: []PMemo{}}
}
return appData
}
func main() {
var config AppConfig
err := env.Parse(&config)
if err != nil {
fmt.Println("读取环境变量出错啦!")
panic(err)
}
appData := LoadData(&config)
r := gin.Default()
r.Use(authMiddleware(&config))
r.GET("/", func(ctx *gin.Context) {
ping(ctx)
})
r.GET("/all", func(ctx *gin.Context) {
ctx.AsciiJSON(http.StatusOK, appData)
})
r.PUT("/create", func(ctx *gin.Context) {
var content string
if err := ctx.BindPlain(&content); err != nil {
ctx.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
memo := PMemo{
Content: content,
CreatedDate: time.Now(),
}
appData.Memos = append(appData.Memos, memo)
if err := SaveData(&config, &appData); err != nil {
ctx.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
ctx.JSON(http.StatusOK, gin.H{"error": "ok", "data": memo})
})
r.DELETE("/all", func(ctx *gin.Context) {
appData.Memos = []PMemo{}
if err := SaveData(&config, &appData); err != nil {
ctx.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
ctx.JSON(http.StatusOK, gin.H{"error": "ok"})
})
r.POST("/filtered", func(ctx *gin.Context) {
var filter PMemoFilter
if err := ctx.BindJSON(&filter); err != nil {
ctx.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
memos := slices.Collect(func(yield func(PMemo) bool) {
for _, memo := range appData.Memos {
if filter.Till.After(memo.CreatedDate) {
if !yield(memo) {
return
}
}
}
})
ctx.JSON(http.StatusOK, gin.H{"error": "ok", "data": gin.H{"memos": memos}})
})
r.DELETE("/filtered", func(ctx *gin.Context) {
var filter PMemoFilter
if err := ctx.BindJSON(&filter); err != nil {
ctx.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
appData.Memos = slices.Collect(func(yield func(PMemo) bool) {
for _, memo := range appData.Memos {
if !filter.Till.After(memo.CreatedDate) {
if !yield(memo) {
return
}
}
}
})
if err := SaveData(&config, &appData); err != nil {
ctx.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
ctx.JSON(http.StatusOK, gin.H{"error": "ok", "data": appData})
})
r.Run()
}