æ·feat: commplete init process

This commit is contained in:
engigu
2023-12-30 17:40:20 +08:00
parent 9307bec4ab
commit 77af985b76
92 changed files with 12054 additions and 2 deletions
+62
View File
@@ -0,0 +1,62 @@
package app
import (
"fmt"
"github.com/astaxie/beego/validation"
"github.com/gin-gonic/gin"
"github.com/go-playground/validator/v10"
"message-nest/pkg/e"
"message-nest/pkg/util"
"net/http"
"strings"
)
// BindAndValid binds and validates data
func BindAndValid(c *gin.Context, form interface{}) (int, int) {
err := c.Bind(form)
if err != nil {
return http.StatusBadRequest, e.INVALID_PARAMS
}
valid := validation.Validation{}
check, err := valid.Valid(form)
if err != nil {
return http.StatusInternalServerError, e.ERROR
}
if !check {
MarkErrors(valid.Errors)
return http.StatusBadRequest, e.INVALID_PARAMS
}
return http.StatusOK, e.SUCCESS
}
func CommonPlaygroundValid(obj interface{}) (int, string) {
if err := util.CustomerValidate.Struct(obj); err != nil {
errs := err.(validator.ValidationErrors)
errMsg := BuildValidationErrors(errs)
return http.StatusBadRequest, errMsg
}
return http.StatusOK, ""
}
func BindJsonAndPlayValid(c *gin.Context, req interface{}) (int, string) {
err := c.ShouldBindJSON(req)
if err != nil {
return http.StatusBadRequest, err.Error()
} else {
return CommonPlaygroundValid(req)
}
}
func BuildValidationErrors(errors []validator.FieldError) string {
var errorMsgBuilder strings.Builder
for i, err := range errors {
if i > 0 {
errorMsgBuilder.WriteString("; ")
}
message := err.Translate(util.Trans)
errorMsgBuilder.WriteString(fmt.Sprintf("%s", message))
}
return errorMsgBuilder.String()
}
+27
View File
@@ -0,0 +1,27 @@
package app
import (
"fmt"
"github.com/astaxie/beego/validation"
"github.com/gin-gonic/gin"
"message-nest/pkg/logging"
)
// MarkErrors logs error logs
func MarkErrors(errors []*validation.Error) {
for _, err := range errors {
logging.Logger.Error(err.Key, err.Message)
}
return
}
// 从请求中获取当前用户
func GetCurrentUserName(c *gin.Context) string {
userName, ok := c.Get("currentUserName")
if !ok {
return ""
} else {
return fmt.Sprintf("%s", userName)
}
}
+37
View File
@@ -0,0 +1,37 @@
package app
import (
"github.com/gin-gonic/gin"
"net/http"
"message-nest/pkg/e"
)
type Gin struct {
C *gin.Context
}
type Response struct {
Code int `json:"code"`
Msg string `json:"msg"`
Data interface{} `json:"data"`
}
// Response setting gin.JSON
func (g *Gin) Response(httpCode, errCode int, data interface{}) {
g.C.JSON(httpCode, Response{
Code: errCode,
Msg: e.GetMsg(errCode),
Data: data,
})
return
}
func (g *Gin) CResponse(errCode int, Msg string, data interface{}) {
g.C.JSON(http.StatusOK, Response{
Code: errCode,
Msg: Msg,
Data: data,
})
return
}
+38
View File
@@ -0,0 +1,38 @@
package e
const (
SUCCESS = 200
ERROR = 500
INVALID_PARAMS = 400
ERROR_EXIST_TAG = 10001
ERROR_EXIST_TAG_FAIL = 10002
ERROR_NOT_EXIST_TAG = 10003
ERROR_GET_TAGS_FAIL = 10004
ERROR_COUNT_TAG_FAIL = 10005
ERROR_ADD_TAG_FAIL = 10006
ERROR_EDIT_TAG_FAIL = 10007
ERROR_DELETE_TAG_FAIL = 10008
ERROR_EXPORT_TAG_FAIL = 10009
ERROR_IMPORT_TAG_FAIL = 10010
ERROR_NOT_EXIST_ARTICLE = 10011
ERROR_CHECK_EXIST_ARTICLE_FAIL = 10012
ERROR_ADD_ARTICLE_FAIL = 10013
ERROR_DELETE_ARTICLE_FAIL = 10014
ERROR_EDIT_ARTICLE_FAIL = 10015
ERROR_COUNT_ARTICLE_FAIL = 10016
ERROR_GET_ARTICLES_FAIL = 10017
ERROR_GET_ARTICLE_FAIL = 10018
ERROR_GEN_ARTICLE_POSTER_FAIL = 10019
ERROR_AUTH_CHECK_TOKEN_FAIL = 20001
ERROR_AUTH_CHECK_TOKEN_TIMEOUT = 20002
ERROR_AUTH_TOKEN = 20003
ERROR_AUTH = 20004
ERROR_AUTH_NO_TOKEN = 20005
ERROR_UPLOAD_SAVE_IMAGE_FAIL = 30001
ERROR_UPLOAD_CHECK_IMAGE_FAIL = 30002
ERROR_UPLOAD_CHECK_IMAGE_FORMAT = 30003
)
+44
View File
@@ -0,0 +1,44 @@
package e
var MsgFlags = map[int]string{
SUCCESS: "ok",
ERROR: "fail",
INVALID_PARAMS: "请求参数错误",
ERROR_EXIST_TAG: "已存在该标签名称",
ERROR_EXIST_TAG_FAIL: "获取已存在标签失败",
ERROR_NOT_EXIST_TAG: "该标签不存在",
ERROR_GET_TAGS_FAIL: "获取所有标签失败",
ERROR_COUNT_TAG_FAIL: "统计标签失败",
ERROR_ADD_TAG_FAIL: "新增标签失败",
ERROR_EDIT_TAG_FAIL: "修改标签失败",
ERROR_DELETE_TAG_FAIL: "删除标签失败",
ERROR_EXPORT_TAG_FAIL: "导出标签失败",
ERROR_IMPORT_TAG_FAIL: "导入标签失败",
ERROR_NOT_EXIST_ARTICLE: "该文章不存在",
ERROR_ADD_ARTICLE_FAIL: "新增文章失败",
ERROR_DELETE_ARTICLE_FAIL: "删除文章失败",
ERROR_CHECK_EXIST_ARTICLE_FAIL: "检查文章是否存在失败",
ERROR_EDIT_ARTICLE_FAIL: "修改文章失败",
ERROR_COUNT_ARTICLE_FAIL: "统计文章失败",
ERROR_GET_ARTICLES_FAIL: "获取多个文章失败",
ERROR_GET_ARTICLE_FAIL: "获取单个文章失败",
ERROR_GEN_ARTICLE_POSTER_FAIL: "生成文章海报失败",
ERROR_AUTH_CHECK_TOKEN_FAIL: "Token鉴权失败",
ERROR_AUTH_CHECK_TOKEN_TIMEOUT: "Token已超时",
ERROR_AUTH_TOKEN: "Token生成失败",
ERROR_AUTH_NO_TOKEN: "Token缺失",
ERROR_AUTH: "Token错误",
ERROR_UPLOAD_SAVE_IMAGE_FAIL: "保存图片失败",
ERROR_UPLOAD_CHECK_IMAGE_FAIL: "检查图片失败",
ERROR_UPLOAD_CHECK_IMAGE_FORMAT: "校验图片错误,图片格式或大小有问题",
}
// GetMsg get error information based on Code
func GetMsg(code int) string {
msg, ok := MsgFlags[code]
if ok {
return msg
}
return MsgFlags[ERROR]
}
+15
View File
@@ -0,0 +1,15 @@
package logging
import (
"github.com/sirupsen/logrus"
"os"
)
var Logger = logrus.New()
func Setup() {
Logger := logrus.New()
Logger.SetFormatter(&logrus.JSONFormatter{})
Logger.SetOutput(os.Stdout)
Logger.SetLevel(logrus.InfoLevel)
}
+9
View File
@@ -0,0 +1,9 @@
package message
type DTalkMessage struct {
WebhookUrl string
}
func (d *DTalkMessage) send(content string) {
}
+39
View File
@@ -0,0 +1,39 @@
package message
import (
"fmt"
"gopkg.in/gomail.v2"
)
type EmailMessage struct {
Server string
Port int
Account string
Passwd string
GM *gomail.Dialer
}
func (e *EmailMessage) Init(host string, port int, account string, passwd string) {
e.Server = host
e.Port = port
e.Account = account
e.Passwd = passwd
e.GM = gomail.NewDialer(host, port, account, passwd)
}
func (e *EmailMessage) SendTextMessage(toEmail string, title string, content string) string {
m := gomail.NewMessage()
m.SetHeader("From", e.Account)
m.SetHeader("To", toEmail)
m.SetHeader("Subject", title)
m.SetBody("text/html", content)
if err := e.GM.DialAndSend(m); err != nil {
return fmt.Sprintf("邮件发送失败: %s", err)
}
return ""
}
func (e *EmailMessage) SendHtmlMessage(toEmail string, title string, content string) string {
return e.SendTextMessage(toEmail, title, content)
}
+97
View File
@@ -0,0 +1,97 @@
package setting
import (
"log"
"time"
"github.com/go-ini/ini"
)
type App struct {
JwtSecret string
PageSize int
PrefixUrl string
RuntimeRootPath string
ImageSavePath string
ImageMaxSize int
ImageAllowExts []string
ExportSavePath string
QrCodeSavePath string
FontSavePath string
LogSavePath string
LogSaveName string
LogFileExt string
TimeFormat string
LogKeepNum int
CleanTaskLogID string
}
var AppSetting = &App{}
type Server struct {
RunMode string
HttpPort int
ReadTimeout time.Duration
WriteTimeout time.Duration
}
var ServerSetting = &Server{}
type Database struct {
Type string
User string
Password string
Host string
Name string
TablePrefix string
}
var DatabaseSetting = &Database{}
type Redis struct {
Host string
Password string
MaxIdle int
MaxActive int
IdleTimeout time.Duration
}
var RedisSetting = &Redis{}
var cfg *ini.File
// Setup initialize the configuration instance
func Setup() {
var err error
cfg, err = ini.Load("conf/app.ini")
if err != nil {
log.Fatalf("setting.Setup, fail to parse 'conf/app.ini': %v", err)
}
mapTo("app", AppSetting)
mapTo("server", ServerSetting)
mapTo("database", DatabaseSetting)
mapTo("redis", RedisSetting)
AppSetting.ImageMaxSize = AppSetting.ImageMaxSize * 1024 * 1024
ServerSetting.ReadTimeout = ServerSetting.ReadTimeout * time.Second
ServerSetting.WriteTimeout = ServerSetting.WriteTimeout * time.Second
RedisSetting.IdleTimeout = RedisSetting.IdleTimeout * time.Second
// 默认值
AppSetting.LogKeepNum = 1000
AppSetting.CleanTaskLogID = "00000000-0000-0000-0000-000000000001"
}
// mapTo map section
func mapTo(section string, v interface{}) {
err := cfg.Section(section).MapTo(v)
if err != nil {
log.Fatalf("Cfg.MapTo %s err: %v", section, err)
}
}
+18
View File
@@ -0,0 +1,18 @@
package table
import (
"fmt"
"message-nest/pkg/setting"
)
var InsTableName string
var WayTableName string
var LogsTableName string
var TasksTableName string
func Setup() {
InsTableName = fmt.Sprintf("%ssend_tasks_ins", setting.DatabaseSetting.TablePrefix)
WayTableName = fmt.Sprintf("%ssend_ways", setting.DatabaseSetting.TablePrefix)
LogsTableName = fmt.Sprintf("%ssend_tasks_logs", setting.DatabaseSetting.TablePrefix)
TasksTableName = fmt.Sprintf("%ssend_tasks", setting.DatabaseSetting.TablePrefix)
}
+19
View File
@@ -0,0 +1,19 @@
package util
import (
"time"
)
func TimeStampToYmdMHD(stamp int) string {
timestamp := int64(stamp)
timeObj := time.Unix(timestamp, 0)
formattedTime := timeObj.Format("2006-01-02 15:04:05")
return formattedTime
}
func GetNowTimeStampToYmdMHD() string {
now := time.Now().Unix()
timeObj := time.Unix(now, 0)
formattedTime := timeObj.Format("2006-01-02 15:04:05")
return formattedTime
}
+50
View File
@@ -0,0 +1,50 @@
package util
import (
"time"
"github.com/dgrijalva/jwt-go"
)
var jwtSecret []byte
type Claims struct {
Username string `json:"username"`
Password string `json:"password"`
jwt.StandardClaims
}
// GenerateToken generate tokens used for auth
func GenerateToken(username, password string) (string, error) {
nowTime := time.Now()
expireTime := nowTime.Add(7 * 24 * time.Hour)
claims := Claims{
username,
EncodeMD5(password),
jwt.StandardClaims{
ExpiresAt: expireTime.Unix(),
Issuer: "message-nest",
},
}
tokenClaims := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
token, err := tokenClaims.SignedString(jwtSecret)
return token, err
}
// ParseToken parsing token
func ParseToken(token string) (*Claims, error) {
tokenClaims, err := jwt.ParseWithClaims(token, &Claims{}, func(token *jwt.Token) (interface{}, error) {
return jwtSecret, nil
})
if tokenClaims != nil {
if claims, ok := tokenClaims.Claims.(*Claims); ok && tokenClaims.Valid {
return claims, nil
}
}
return nil, err
}
+14
View File
@@ -0,0 +1,14 @@
package util
import (
"crypto/md5"
"encoding/hex"
)
// EncodeMD5 md5 encryption
func EncodeMD5(value string) string {
m := md5.New()
m.Write([]byte(value))
return hex.EncodeToString(m.Sum(nil))
}
+29
View File
@@ -0,0 +1,29 @@
package util
import (
"github.com/gin-gonic/gin"
"github.com/unknwon/com"
"message-nest/pkg/setting"
)
// GetPage get page parameters
func GetPage(c *gin.Context) int {
result := 0
page := com.StrTo(c.Query("page")).MustInt()
if page > 0 {
result = (page - 1) * setting.AppSetting.PageSize
}
return result
}
func GetPageSize(c *gin.Context) (int, int) {
result := 0
page := com.StrTo(c.Query("page")).MustInt()
size := com.StrTo(c.Query("size")).MustInt()
if page > 0 {
result = (page - 1) * size
}
return result, size
}
+55
View File
@@ -0,0 +1,55 @@
package util
import (
"database/sql/driver"
"fmt"
"time"
)
const timeFormat = "2006-01-02 15:04:05"
const timezone = "Asia/Shanghai"
// 全局定义
type Time time.Time
func (t Time) MarshalJSON() ([]byte, error) {
b := make([]byte, 0, len(timeFormat)+2)
b = append(b, '"')
b = time.Time(t).AppendFormat(b, timeFormat)
b = append(b, '"')
return b, nil
}
func (t *Time) UnmarshalJSON(data []byte) (err error) {
now, err := time.ParseInLocation(`"`+timeFormat+`"`, string(data), time.Local)
*t = Time(now)
return
}
func (t Time) String() string {
return time.Time(t).Format(timeFormat)
}
func (t Time) local() time.Time {
loc, _ := time.LoadLocation(timezone)
return time.Time(t).In(loc)
}
func (t Time) Value() (driver.Value, error) {
var zeroTime time.Time
var ti = time.Time(t)
if ti.UnixNano() == zeroTime.UnixNano() {
return nil, nil
}
return ti, nil
}
func (t *Time) Scan(v interface{}) error {
value, ok := v.(time.Time)
if ok {
*t = Time(value)
return nil
}
return fmt.Errorf("can not convert %v to timestamp", v)
}
+49
View File
@@ -0,0 +1,49 @@
package util
import (
"github.com/go-playground/locales/en"
"github.com/go-playground/locales/zh"
"github.com/go-playground/universal-translator"
"github.com/go-playground/validator/v10"
zh_trans "github.com/go-playground/validator/v10/translations/zh"
"reflect"
"strings"
)
//var trans ut.Translator
func TransInit() (trans ut.Translator, validate *validator.Validate) {
// 创建翻译器
zhTrans := zh.New() // 中文转换器
enTrans := en.New() // 因为转换器
uni := ut.New(zhTrans, zhTrans, enTrans) // 创建一个通用转换器
curLocales := "zh" // 设置当前语言类型
trans, _ = uni.GetTranslator(curLocales) // 获取对应语言的转换器
validate = validator.New() // 创建验证器
_ = zh_trans.RegisterDefaultTranslations(validate, trans)
//switch curLocales {
//case "zh":
// // 内置tag注册 中文翻译器
// _ = zh_trans.RegisterDefaultTranslations(validate, trans)
//case "en":
// // 内置tag注册 英文翻译器
// _ = en_trans.RegisterDefaultTranslations(validate, trans)
//}
// 注册 RegisterTagNameFunc
validate.RegisterTagNameFunc(func(field reflect.StructField) string {
name := strings.SplitN(field.Tag.Get("label"), ",", 2)[0]
if name == "-" {
return ""
}
return name
})
return trans, validate
}
var Trans, CustomerValidate = TransInit()
+10
View File
@@ -0,0 +1,10 @@
package util
import (
"message-nest/pkg/setting"
)
// Setup Initialize the util
func Setup() {
jwtSecret = []byte(setting.AppSetting.JwtSecret)
}