first commit
This commit is contained in:
commit
e268852ff1
|
@ -0,0 +1,5 @@
|
|||
*.exe
|
||||
*.so
|
||||
build
|
||||
*.log
|
||||
mini_server*
|
|
@ -0,0 +1,40 @@
|
|||
# mini_server
|
||||
|
||||
#### 介绍
|
||||
微信小程序后端私有仓库
|
||||
|
||||
#### 软件架构
|
||||
软件架构说明
|
||||
|
||||
|
||||
gorm学习官网:https://gorm.io/zh_CN/docs/models.html
|
||||
|
||||
|
||||
#### 安装教程
|
||||
|
||||
1. xxxx
|
||||
2. xxxx
|
||||
3. xxxx
|
||||
|
||||
#### 使用说明
|
||||
|
||||
1. xxxx
|
||||
2. xxxx
|
||||
3. xxxx
|
||||
|
||||
#### 参与贡献
|
||||
|
||||
1. Fork 本仓库
|
||||
2. 新建 Feat_xxx 分支
|
||||
3. 提交代码
|
||||
4. 新建 Pull Request
|
||||
|
||||
|
||||
#### 特技
|
||||
|
||||
1. 使用 Readme\_XXX.md 来支持不同的语言,例如 Readme\_en.md, Readme\_zh.md
|
||||
2. Gitee 官方博客 [blog.gitee.com](https://blog.gitee.com)
|
||||
3. 你可以 [https://gitee.com/explore](https://gitee.com/explore) 这个地址来了解 Gitee 上的优秀开源项目
|
||||
4. [GVP](https://gitee.com/gvp) 全称是 Gitee 最有价值开源项目,是综合评定出的优秀开源项目
|
||||
5. Gitee 官方提供的使用手册 [https://gitee.com/help](https://gitee.com/help)
|
||||
6. Gitee 封面人物是一档用来展示 Gitee 会员风采的栏目 [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)
|
|
@ -0,0 +1,27 @@
|
|||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEogIBAAKCAQEAp5ofFuO1pBRioe3LOCJrYvyMGp3py9gEah7H0thGjClPodNj
|
||||
tdrLt3UTP2hbDuoEBiiImTDMV+WCWOB0R3xRtq+RnvtKlqXtOvxAcnPrm55jxd3O
|
||||
kSGIu/PZycY/jG4rxDxDVwKrklpISJnEjmPMwkSLE9tDKIVSp1yvnD8n2bTEo9dq
|
||||
V4s0FJMJotPOzvVYWcnrRrq2ObJvk/3AdBI/LGEwx+2JuEmf5zcmzITwgICjsZsS
|
||||
9Yfj4hnudXXbt9+c8opK/bUIuEwdqrrevAsVOTdPEfuTBDX6DYgZTAq6LTWIG+XQ
|
||||
jG/uhMaXmxBRvLRFIyuApBA6zW68CkLhz/GTqQIDAQABAoIBAAkCPRmQiSWV/Zc7
|
||||
85MY29zTkP79Q0vfA0hmTydY01yapoUe76/JYESELnyssfhN69lzjvls/g7bb0jd
|
||||
B7hanlR2K3BNjDzSE7ulQ3GOJDlBJ5Ztzbn6AMzZgU4Eh0tCa2fTisBqjFOu4U5w
|
||||
YCL8ik0G532HE50Moty2xq8HVgUFnsZqRhaAzloG+VRuNvqTx/xSOotRPS4Ayw1j
|
||||
NS/jeaKWpBHq0CAZeng1ELiWfDhjojUDeKUthOuNerCU5gp+SbnFyny9OhTP3aqx
|
||||
k2QO4UJqi3VfCgzPHDbdt3p8QHgjQvcoNBZhQoylk3/bMrp1M7tlXYyf1H25FZrq
|
||||
wlWAz4ECgYEA3PG0OZAllxXVAunHkwBVKWntsku7T77+BcBGviMM16FfDXwczylV
|
||||
2mmgd9QDuhDjog3y6Un8yb2E9OjOJCwKhddv1sRYriQKxjkhLJGbFRGtNk+bKq8Y
|
||||
lhXvH4RyhS41VcAEMvNvvtiuHc7uxLHapp+7Q53TzQ7/ba8HDHdHgAUCgYEAwjHF
|
||||
QvBeFxKCe1UVe1BEI7CF36BqVnMZsLGKP+lLQLs+HgXv+YXr1UJSZqmwV6gEfyt6
|
||||
/EaEXFeRnUBUrhg2EUmmEAsQqqk8tEc3AD4KER0vjmXBiikKIXMYzilh7JYU5pqi
|
||||
NBVqH4u5HoONsXOyaS1QlNyROpER2ZijtlIKalUCgYBoRiJ6sE8tWP5pG5A3Doci
|
||||
vn2SEi/a2Rbl+/LnNX+QHPbRVGv8UVPVethi9Uq0+9eS2eZ0t5h4Vdt0ApOXermU
|
||||
pTKBN7VqqlPzbW78q9N3RBptcXCX2n9OBhgO1eF+fWpqh+7zZPSuK3ExXEJPzmiV
|
||||
DvnAVbJqKtPeHibDeV/jSQKBgDeiurkq1EoX63oaLkVeAaeX80LWWqDZ6QpOUyVs
|
||||
WTr6ahl/6fi6/Y3jqmfvRa5XXLJyapHMQi+Shw1eWORn21WonAMMqIG8ar/bh05y
|
||||
d7/fdLh/PquuhlB/ASRPhtaZSPOoacAyQm03QpoTZozocLzhVqzPZGw7E7obmQur
|
||||
BYDhAoGAQB/JBuShnQJa0XtvSZloiNzoSEc5PjPZYKfMt80VW1NCtIk+RUGRsN6S
|
||||
V4adJlzwXnQKZSq8LokMD8sgQ227jXHdbKVLSzyCWipREM5UtNH8xg1AetJLxyH7
|
||||
ATH62gnR5qV1QcIrwGs5Dtw8JlR00gI2xvUvi7XwJHHI1c+XRoY=
|
||||
-----END RSA PRIVATE KEY-----
|
|
@ -0,0 +1,62 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIGBTCCBO2gAwIBAgIQBtj3ZRX9NfSuGIwP9+AbhDANBgkqhkiG9w0BAQsFADBu
|
||||
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
|
||||
d3cuZGlnaWNlcnQuY29tMS0wKwYDVQQDEyRFbmNyeXB0aW9uIEV2ZXJ5d2hlcmUg
|
||||
RFYgVExTIENBIC0gRzIwHhcNMjQwNTE3MDAwMDAwWhcNMjQwODE0MjM1OTU5WjAY
|
||||
MRYwFAYDVQQDEw10YWt3YXktYWkudG9wMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
|
||||
MIIBCgKCAQEAp5ofFuO1pBRioe3LOCJrYvyMGp3py9gEah7H0thGjClPodNjtdrL
|
||||
t3UTP2hbDuoEBiiImTDMV+WCWOB0R3xRtq+RnvtKlqXtOvxAcnPrm55jxd3OkSGI
|
||||
u/PZycY/jG4rxDxDVwKrklpISJnEjmPMwkSLE9tDKIVSp1yvnD8n2bTEo9dqV4s0
|
||||
FJMJotPOzvVYWcnrRrq2ObJvk/3AdBI/LGEwx+2JuEmf5zcmzITwgICjsZsS9Yfj
|
||||
4hnudXXbt9+c8opK/bUIuEwdqrrevAsVOTdPEfuTBDX6DYgZTAq6LTWIG+XQjG/u
|
||||
hMaXmxBRvLRFIyuApBA6zW68CkLhz/GTqQIDAQABo4IC8zCCAu8wHwYDVR0jBBgw
|
||||
FoAUeN+RkF/u3qz2xXXr1UxVU+8kSrYwHQYDVR0OBBYEFG7xcD2xwJgNfg4PlPL7
|
||||
eALtvIYhMCsGA1UdEQQkMCKCDXRha3dheS1haS50b3CCEXd3dy50YWt3YXktYWku
|
||||
dG9wMD4GA1UdIAQ3MDUwMwYGZ4EMAQIBMCkwJwYIKwYBBQUHAgEWG2h0dHA6Ly93
|
||||
d3cuZGlnaWNlcnQuY29tL0NQUzAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYI
|
||||
KwYBBQUHAwEGCCsGAQUFBwMCMIGABggrBgEFBQcBAQR0MHIwJAYIKwYBBQUHMAGG
|
||||
GGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBKBggrBgEFBQcwAoY+aHR0cDovL2Nh
|
||||
Y2VydHMuZGlnaWNlcnQuY29tL0VuY3J5cHRpb25FdmVyeXdoZXJlRFZUTFNDQS1H
|
||||
Mi5jcnQwDAYDVR0TAQH/BAIwADCCAX4GCisGAQQB1nkCBAIEggFuBIIBagFoAHYA
|
||||
dv+IPwq2+5VRwmHM9Ye6NLSkzbsp3GhCCp/mZ0xaOnQAAAGPhaiLngAABAMARzBF
|
||||
AiEA0uvWuS89aiRig+3xGXHNyahwV7jNx/uiCklK9klZipACIHpRZvv8iWfo1lW9
|
||||
ZhZ3UtfpXOseiIKGSbR/bAzZtr7EAHcA2ra/az+1tiKfm8K7XGvocJFxbLtRhIU0
|
||||
vaQ9MEjX+6sAAAGPhaiLegAABAMASDBGAiEAp365rPS/DmDXRVUuiQ1igB8kLkry
|
||||
MjMbZT+rvbHC9kICIQCfBvecI6ojgiGzk1U8QT7XpCOB4qAySlmF5Z0tO3v50QB1
|
||||
AD8XS0/XIkdYlB1lHIS+DRLtkDd/H4Vq68G/KIXs+GRuAAABj4Woi7UAAAQDAEYw
|
||||
RAIgR66au1GAubh/zc9Eo4i0Cu+wQlLHehJETYD8r1hP7yICIFDq5fGDS45jawLA
|
||||
qt8IF+5EEiWjLL7/DkxNHLvsnP8qMA0GCSqGSIb3DQEBCwUAA4IBAQDDE7NnYrIe
|
||||
S2FmcI1hh9encfgviEtfSBvWrUv14F3WCzQKd3HvIAzuuh2aRDpsLBr1xvcPXq8w
|
||||
2o5IwQMRpe65qFXG7H2pZEp5f0J/qVwXd2h2cZYxImkco/VTNetYvovseJ9LGNnN
|
||||
Kwrr6XgMd+/KLBzc7m19I6nq2Xvqfa1xFO4o35xyZ9GoYKnH8nn5Cwh/Ux5bRAAD
|
||||
xuK25DCiLUxXiOzHDngGh5ju4inDEePO2dzYv1TWMp9nLcWoIBp9xZ54aBQRheAm
|
||||
uSv9CD/xq4vbnRjxMcIn7Ir45HuSqcDL9ghimZ7Crx4fkJiEjaQs3HNaDbrOhKb6
|
||||
xJ7b42GBvFm+
|
||||
-----END CERTIFICATE-----
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIEqjCCA5KgAwIBAgIQDeD/te5iy2EQn2CMnO1e0zANBgkqhkiG9w0BAQsFADBh
|
||||
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
|
||||
d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBH
|
||||
MjAeFw0xNzExMjcxMjQ2NDBaFw0yNzExMjcxMjQ2NDBaMG4xCzAJBgNVBAYTAlVT
|
||||
MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j
|
||||
b20xLTArBgNVBAMTJEVuY3J5cHRpb24gRXZlcnl3aGVyZSBEViBUTFMgQ0EgLSBH
|
||||
MjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAO8Uf46i/nr7pkgTDqnE
|
||||
eSIfCFqvPnUq3aF1tMJ5hh9MnO6Lmt5UdHfBGwC9Si+XjK12cjZgxObsL6Rg1njv
|
||||
NhAMJ4JunN0JGGRJGSevbJsA3sc68nbPQzuKp5Jc8vpryp2mts38pSCXorPR+sch
|
||||
QisKA7OSQ1MjcFN0d7tbrceWFNbzgL2csJVQeogOBGSe/KZEIZw6gXLKeFe7mupn
|
||||
NYJROi2iC11+HuF79iAttMc32Cv6UOxixY/3ZV+LzpLnklFq98XORgwkIJL1HuvP
|
||||
ha8yvb+W6JislZJL+HLFtidoxmI7Qm3ZyIV66W533DsGFimFJkz3y0GeHWuSVMbI
|
||||
lfsCAwEAAaOCAU8wggFLMB0GA1UdDgQWBBR435GQX+7erPbFdevVTFVT7yRKtjAf
|
||||
BgNVHSMEGDAWgBROIlQgGJXm427mD/r6uRLtBhePOTAOBgNVHQ8BAf8EBAMCAYYw
|
||||
HQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMBIGA1UdEwEB/wQIMAYBAf8C
|
||||
AQAwNAYIKwYBBQUHAQEEKDAmMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdp
|
||||
Y2VydC5jb20wQgYDVR0fBDswOTA3oDWgM4YxaHR0cDovL2NybDMuZGlnaWNlcnQu
|
||||
Y29tL0RpZ2lDZXJ0R2xvYmFsUm9vdEcyLmNybDBMBgNVHSAERTBDMDcGCWCGSAGG
|
||||
/WwBAjAqMCgGCCsGAQUFBwIBFhxodHRwczovL3d3dy5kaWdpY2VydC5jb20vQ1BT
|
||||
MAgGBmeBDAECATANBgkqhkiG9w0BAQsFAAOCAQEAoBs1eCLKakLtVRPFRjBIJ9LJ
|
||||
L0s8ZWum8U8/1TMVkQMBn+CPb5xnCD0GSA6L/V0ZFrMNqBirrr5B241OesECvxIi
|
||||
98bZ90h9+q/X5eMyOD35f8YTaEMpdnQCnawIwiHx06/0BfiTj+b/XQih+mqt3ZXe
|
||||
xNCJqKexdiB2IWGSKcgahPacWkk/BAQFisKIFYEqHzV974S3FAz/8LIfD58xnsEN
|
||||
GfzyIDkH3JrwYZ8caPTf6ZX9M1GrISN8HnWTtdNCH2xEajRa/h9ZBXjUyFKQrGk2
|
||||
n2hcLrfZSbynEC/pSw/ET7H5nWwckjmAJ1l9fcnbqkU/pf6uMQmnfl0JQjJNSg==
|
||||
-----END CERTIFICATE-----
|
|
@ -0,0 +1,52 @@
|
|||
module mini_server
|
||||
|
||||
go 1.21.6
|
||||
|
||||
require (
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible
|
||||
github.com/gin-gonic/gin v1.9.1
|
||||
github.com/google/uuid v1.6.0
|
||||
github.com/patrickmn/go-cache v2.1.0+incompatible
|
||||
github.com/sirupsen/logrus v1.9.3
|
||||
github.com/sqids/sqids-go v0.4.1
|
||||
github.com/unrolled/secure v1.14.0
|
||||
gorm.io/datatypes v1.2.0
|
||||
gorm.io/driver/mysql v1.5.6
|
||||
gorm.io/gorm v1.25.9
|
||||
)
|
||||
|
||||
require (
|
||||
filippo.io/edwards25519 v1.1.0 // indirect
|
||||
github.com/bytedance/sonic v1.9.1 // indirect
|
||||
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect
|
||||
github.com/gabriel-vasile/mimetype v1.4.2 // indirect
|
||||
github.com/gin-contrib/sse v0.1.0 // indirect
|
||||
github.com/go-playground/locales v0.14.1 // indirect
|
||||
github.com/go-playground/universal-translator v0.18.1 // indirect
|
||||
github.com/go-playground/validator/v10 v10.14.0 // indirect
|
||||
github.com/go-sql-driver/mysql v1.8.1 // indirect
|
||||
github.com/goccy/go-json v0.10.2 // indirect
|
||||
github.com/google/go-cmp v0.5.9 // indirect
|
||||
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||
github.com/jinzhu/now v1.1.5 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.2.4 // indirect
|
||||
github.com/kr/pretty v0.3.1 // indirect
|
||||
github.com/leodido/go-urn v1.2.4 // indirect
|
||||
github.com/mattn/go-isatty v0.0.19 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.0.8 // indirect
|
||||
github.com/rogpeppe/go-internal v1.11.0 // indirect
|
||||
github.com/stretchr/testify v1.9.0 // indirect
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
||||
github.com/ugorji/go/codec v1.2.11 // indirect
|
||||
golang.org/x/arch v0.3.0 // indirect
|
||||
golang.org/x/crypto v0.22.0 // indirect
|
||||
golang.org/x/net v0.24.0 // indirect
|
||||
golang.org/x/sys v0.19.0 // indirect
|
||||
golang.org/x/text v0.14.0 // indirect
|
||||
google.golang.org/protobuf v1.30.0 // indirect
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
|
@ -0,0 +1,149 @@
|
|||
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
|
||||
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
|
||||
github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM=
|
||||
github.com/bytedance/sonic v1.9.1 h1:6iJ6NqdoxCDr6mbY8h18oSO+cShGSMRGCEo7F2h0x8s=
|
||||
github.com/bytedance/sonic v1.9.1/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U=
|
||||
github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY=
|
||||
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 h1:qSGYFH7+jGhDF8vLC+iwCD4WpbV1EBDSzWkJODFLams=
|
||||
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||
github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU=
|
||||
github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA=
|
||||
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
|
||||
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
|
||||
github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg=
|
||||
github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU=
|
||||
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
|
||||
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
||||
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
|
||||
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
|
||||
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
|
||||
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
|
||||
github.com/go-playground/validator/v10 v10.14.0 h1:vgvQWe3XCz3gIeFDm/HnTIbj6UGmg/+t63MyGU2n5js=
|
||||
github.com/go-playground/validator/v10 v10.14.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU=
|
||||
github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
|
||||
github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y=
|
||||
github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
|
||||
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
|
||||
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
||||
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 h1:au07oEsX2xN0ktxqI+Sida1w446QrXBRJ0nee3SNZlA=
|
||||
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
|
||||
github.com/golang-sql/sqlexp v0.1.0 h1:ZCD6MBpcuOVfGVqsEmY5/4FtYiKz6tSyUv9LPEDei6A=
|
||||
github.com/golang-sql/sqlexp v0.1.0/go.mod h1:J4ad9Vo8ZCWQ2GMrC4UCQy1JpCbwU9m3EOqtpKwwwHI=
|
||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
|
||||
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
|
||||
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk=
|
||||
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
|
||||
github.com/jackc/pgx/v5 v5.3.0 h1:/NQi8KHMpKWHInxXesC8yD4DhkXPrVhmnwYkjp9AmBA=
|
||||
github.com/jackc/pgx/v5 v5.3.0/go.mod h1:t3JDKnCBlYIc0ewLF0Q7B8MXmoIaBOZj/ic7iHozM/8=
|
||||
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
|
||||
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
|
||||
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
|
||||
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
||||
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||
github.com/klauspost/cpuid/v2 v2.2.4 h1:acbojRNwl3o09bUq+yDCtZFc1aiwaAAxtcn8YkZXnvk=
|
||||
github.com/klauspost/cpuid/v2 v2.2.4/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY=
|
||||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q=
|
||||
github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4=
|
||||
github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
|
||||
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/mattn/go-sqlite3 v1.14.15 h1:vfoHhTN1af61xCRSWzFIWzx2YskyMTwHLrExkBOjvxI=
|
||||
github.com/mattn/go-sqlite3 v1.14.15/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
|
||||
github.com/microsoft/go-mssqldb v0.17.0 h1:Fto83dMZPnYv1Zwx5vHHxpNraeEaUlQ/hhHLgZiaenE=
|
||||
github.com/microsoft/go-mssqldb v0.17.0/go.mod h1:OkoNGhGEs8EZqchVTtochlXruEhEOaO4S0d2sB5aeGQ=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||
github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc=
|
||||
github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
|
||||
github.com/pelletier/go-toml/v2 v2.0.8 h1:0ctb6s9mE31h0/lhu+J6OPmVeDxJn+kYnJc2jZR9tGQ=
|
||||
github.com/pelletier/go-toml/v2 v2.0.8/go.mod h1:vuYfssBdrU2XDZ9bYydBu6t+6a6PYNcZljzZR9VXg+4=
|
||||
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
|
||||
github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
|
||||
github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA=
|
||||
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
||||
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||
github.com/sqids/sqids-go v0.4.1 h1:eQKYzmAZbLlRwHeHYPF35QhgxwZHLnlmVj9AkIj/rrw=
|
||||
github.com/sqids/sqids-go v0.4.1/go.mod h1:EMwHuPQgSNFS0A49jESTfIQS+066XQTVhukrzEPScl8=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
|
||||
github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU=
|
||||
github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
|
||||
github.com/unrolled/secure v1.14.0 h1:u9vJTU/pR4Bny0ntLUMxdfLtmIRGvQf2sEFuA0TG9AE=
|
||||
github.com/unrolled/secure v1.14.0/go.mod h1:BmF5hyM6tXczk3MpQkFf1hpKSRqCyhqcbiQtiAF7+40=
|
||||
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
|
||||
golang.org/x/arch v0.3.0 h1:02VY4/ZcO/gBOH6PUaoiptASxtXU10jazRCP865E97k=
|
||||
golang.org/x/arch v0.3.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
|
||||
golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30=
|
||||
golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M=
|
||||
golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w=
|
||||
golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8=
|
||||
golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o=
|
||||
golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng=
|
||||
google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gorm.io/datatypes v1.2.0 h1:5YT+eokWdIxhJgWHdrb2zYUimyk0+TaFth+7a0ybzco=
|
||||
gorm.io/datatypes v1.2.0/go.mod h1:o1dh0ZvjIjhH/bngTpypG6lVRJ5chTBxE09FH/71k04=
|
||||
gorm.io/driver/mysql v1.5.6 h1:Ld4mkIickM+EliaQZQx3uOJDJHtrd70MxAUqWqlx3Y8=
|
||||
gorm.io/driver/mysql v1.5.6/go.mod h1:sEtPWMiqiN1N1cMXoXmBbd8C6/l+TESwriotuRRpkDM=
|
||||
gorm.io/driver/postgres v1.5.0 h1:u2FXTy14l45qc3UeCJ7QaAXZmZfDDv0YrthvmRq1l0U=
|
||||
gorm.io/driver/postgres v1.5.0/go.mod h1:FUZXzO+5Uqg5zzwzv4KK49R8lvGIyscBOqYrtI1Ce9A=
|
||||
gorm.io/driver/sqlite v1.4.3 h1:HBBcZSDnWi5BW3B3rwvVTc510KGkBkexlOg0QrmLUuU=
|
||||
gorm.io/driver/sqlite v1.4.3/go.mod h1:0Aq3iPO+v9ZKbcdiz8gLWRw5VOPcBOPUQJFLq5e2ecI=
|
||||
gorm.io/driver/sqlserver v1.4.1 h1:t4r4r6Jam5E6ejqP7N82qAJIJAht27EGT41HyPfXRw0=
|
||||
gorm.io/driver/sqlserver v1.4.1/go.mod h1:DJ4P+MeZbc5rvY58PnmN1Lnyvb5gw5NPzGshHDnJLig=
|
||||
gorm.io/gorm v1.25.7/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
|
||||
gorm.io/gorm v1.25.9 h1:wct0gxZIELDk8+ZqF/MVnHLkA1rvYlBWUMv2EdsK1g8=
|
||||
gorm.io/gorm v1.25.9/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
|
||||
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
|
|
@ -0,0 +1,63 @@
|
|||
package config
|
||||
|
||||
import (
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// 微信全局配置表
|
||||
type weixin struct {
|
||||
AppId string
|
||||
AppSecret string
|
||||
Site string
|
||||
HttpTail string
|
||||
}
|
||||
|
||||
func (wx weixin) AppUrl(code string) string {
|
||||
return wx.Site + "appid=" + wx.AppId + "&secret=" + wx.AppSecret + "&js_code=" + code + wx.HttpTail
|
||||
}
|
||||
|
||||
// 微信小程序配置表
|
||||
var WeiXin = weixin{
|
||||
AppId: "wxae661fd0f9edd7da",
|
||||
AppSecret: "f086d7be25d4cc53bc96f5411cf44548",
|
||||
Site: "https://api.weixin.qq.com/sns/jscode2session?",
|
||||
HttpTail: "&grant_type=authorization_code",
|
||||
}
|
||||
|
||||
// 数据库连接信息
|
||||
// var MysqlDSN = "root:123456@tcp(127.0.0.1:3306)/test?charset=utf8mb4&parseTime=true&loc=Local"
|
||||
|
||||
var MysqlDSN = "takway:takway123456@tcp(127.0.0.1:3306)/takway?charset=utf8mb4&parseTime=true&loc=Local"
|
||||
|
||||
// 是否使用tls
|
||||
var TlsEnable = true
|
||||
var TlsFileKey = "./cert/takway-ai.top.key"
|
||||
var TlsFilePem = "./cert/takway-ai.top.pem"
|
||||
|
||||
// 本程序的服务监听地址
|
||||
var ServerListenAddress = "0.0.0.0:8002"
|
||||
|
||||
// jwtkey
|
||||
var JwtEnable = true // 是否开启jwt
|
||||
// var JwtEnable = false // 是否开启jwt,仅测试时打开,方便使用apifox测试。
|
||||
var JwtKey = "weilaimengzhu_api_ajsdkfajsldfkjasl"
|
||||
var JwtApiAuthWhiteList = map[string]string{
|
||||
"/api/users/wx/login": "POST", // 微信快捷登录
|
||||
}
|
||||
|
||||
// 是否处理跨域请求
|
||||
var CorsEnable = false
|
||||
|
||||
// 设置logrus日志等级和日志文件
|
||||
var LogLevel = logrus.TraceLevel
|
||||
var LogFile = "./server.log"
|
||||
|
||||
// 是否使用默认用户,仅测试时打开,方便使用apifox测试。
|
||||
// var UseDefaultUserId = true
|
||||
var UseDefaultUserId = false
|
||||
var DefaultUserId = int32(7) // 7是我的用户ID
|
||||
|
||||
// 是否开启文件缓存机制。key为fileId,value为*dao.File,缓存一段时间,减少与mysql交互。
|
||||
// var FileCacheEnable = true
|
||||
var FileCacheEnable = false // 由于客户可能会手动修改mysql中的群二维码截图,所以这里关闭文件缓存服务,避免二维码更新不及时。
|
||||
// 后续可以考虑提供接口专门更新二维码图片,这样文件缓存开关就可以一直开着。
|
|
@ -0,0 +1,15 @@
|
|||
package dao
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// 参考gorm.Model实现
|
||||
type BaseModel struct {
|
||||
ID uint64 `gorm:"primarykey"`
|
||||
CreatedAt time.Time `gorm:"type:datetime(0)"` // 精度维持到秒
|
||||
UpdatedAt time.Time `gorm:"type:datetime(0)"` // 精度维持到秒
|
||||
DeletedAt gorm.DeletedAt `gorm:"index;datetime(0)"` // 精度维持到秒
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
package dao
|
||||
|
||||
import "gorm.io/gorm"
|
||||
|
||||
type Bluetooth struct {
|
||||
ID uint64 `gorm:"primaryKey"`
|
||||
DeviceId string `gorm:"unique;type varchar(64);not null;comment:'设备Id,唯一标识每个蓝牙设备'"`
|
||||
DeviceName string `gorm:"type varchar(64);comment:'蓝牙名称'"`
|
||||
DeviceType string `gorm:"type varchar(64);comment:'设备类型'"`
|
||||
UserId int32 `gorm:"index;comment:'用户ID'"`
|
||||
}
|
||||
|
||||
func AddBluetooth(data *Bluetooth) error {
|
||||
if err := s.db.Where("device_id = ? AND user_id = ?", data.DeviceId, data.UserId).FirstOrCreate(data).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func DeleteBluetooth(deviceid string, userid int32) error {
|
||||
var data *Bluetooth
|
||||
if err := s.db.Where("device_id = ? AND user_id = ?", deviceid, userid).First(&data).Error; err != nil && err != gorm.ErrRecordNotFound {
|
||||
return err
|
||||
}
|
||||
if err := s.db.Delete(&data).Error; err != nil && err != gorm.ErrRecordNotFound {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func GetAllBluetooth(userid int32) ([]*Bluetooth, error) {
|
||||
var list []*Bluetooth
|
||||
if err := s.db.Where("user_id = ?", userid).Find(&list).Error; err != nil && err != gorm.ErrRecordNotFound {
|
||||
return nil, err
|
||||
}
|
||||
return list, nil
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
package dao
|
||||
|
||||
import (
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type Character struct {
|
||||
ID int32 `gorm:"primaryKey;type:int;not null;comment:'角色ID'"`
|
||||
VoiceId int `gorm:"type:int;default null;comment:'声音ID'"`
|
||||
AvatarId string `gorm:"type:varchar(32);not null;comment:'角色头像的uuid'"`
|
||||
BackgroundIds string `gorm:"type:varchar(255);not null;comment:'聊天背景图集合,逗号分隔,元素是背景图的uuid'"`
|
||||
Name string `gorm:"type:varchar(32);not null;comment:'角色名称'"`
|
||||
WakeupWords string `gorm:"type:varchar(255);not null;"`
|
||||
WorldScenario string `gorm:"type:mediumtext;not null;"`
|
||||
Description string `gorm:"type:mediumtext;not null;"`
|
||||
Emojis string `gorm:"type:json;not null;"`
|
||||
Dialogues string `gorm:"type:mediumtext;not null;"`
|
||||
}
|
||||
|
||||
func (Character) TableName() string { return "character" }
|
||||
|
||||
func Character_Insert(data *Character) (int32, error) {
|
||||
if err := s.db.Create(data).Error; err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return data.ID, nil
|
||||
}
|
||||
|
||||
func Character_Query(characterId int32) (*Character, error) {
|
||||
var data Character
|
||||
err := s.db.Where("id = ?", characterId).First(&data).Error
|
||||
if err != nil {
|
||||
if err == gorm.ErrRecordNotFound {
|
||||
return nil, nil
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
return &data, nil
|
||||
}
|
||||
|
||||
func Character_QueryAllCharacter() ([]*Character, error) {
|
||||
var list []*Character
|
||||
err := s.db.Find(&list).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return list, nil
|
||||
}
|
||||
|
||||
// 根据角色ID列表,查询信息
|
||||
func Character_QueryList(characterIds []int32) ([]*Character, error) {
|
||||
var list []*Character
|
||||
if err := s.db.Find(&list, characterIds).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return list, nil
|
||||
}
|
||||
|
||||
func Character_Delete(characterId int32) error {
|
||||
return s.db.Delete(&Character{}, characterId).Error
|
||||
}
|
||||
|
||||
type CharacterBaseInfo struct {
|
||||
ID int32 `gorm:"id"`
|
||||
AvatarId string `gorm:"avatar_id"`
|
||||
Name string `gorm:"name"`
|
||||
}
|
||||
|
||||
// 根据头像的ID列表,查询头像和名称信息
|
||||
func Character_QueryList_BaseInfo(characterIds []int32) ([]*CharacterBaseInfo, error) {
|
||||
var list []*CharacterBaseInfo
|
||||
if err := s.db.Model(&Character{}).Where("id in (?)", characterIds).Select("id, avatar_id, name").Scan(&list).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return list, nil
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
package dao
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type ChatRecord struct {
|
||||
ID uint64 `gorm:"primaryKey;not null;comment:'聊天记录ID'"`
|
||||
CreatedAt time.Time `gorm:"index;type:datetime(0);comment:'记录时间,由数据库自动创建'"`
|
||||
UserId int32 `gorm:"index;not null;comment:'用户Id'"`
|
||||
CharacterId int32 `gorm:"index;not null;comment:'角色Id'"`
|
||||
Direction int8 `gorm:"comment:'发送方向。1:用户->角色。 2:角色->用户'"`
|
||||
Message string `gorm:"type:text;not null;comment:'消息内容'"`
|
||||
}
|
||||
|
||||
func ChatRecord_Query(user_id, character_id int32, start_time, stop_time time.Time) ([]*ChatRecord, error) {
|
||||
var list []*ChatRecord
|
||||
if err := s.db.Where("user_id = ? and character_id = ?", user_id, character_id).Where("created_at between ? and ?", start_time, stop_time).Find(&list).Error; err != nil && err != gorm.ErrRecordNotFound {
|
||||
return nil, err
|
||||
}
|
||||
return list, nil
|
||||
}
|
||||
|
||||
func ChatRecord_Insert(data *ChatRecord) error {
|
||||
return s.db.Create(data).Error
|
||||
}
|
||||
|
||||
// 查询用户和所有角色聊天记录。
|
||||
func ChatRecord_Query_ByUserId(user_id int32, start_time, stop_time time.Time) ([]*ChatRecord, error) {
|
||||
var list []*ChatRecord
|
||||
if err := s.db.Where("user_id = ?", user_id).Where("created_at between ? and ?", start_time, stop_time).Find(&list).Error; err != nil && err != gorm.ErrRecordNotFound {
|
||||
return nil, err
|
||||
}
|
||||
return list, nil
|
||||
}
|
||||
|
||||
// 查询用户和角色是否有聊天记录
|
||||
func ChatRecord_Exists(user_id, character_id int32) (bool, error) {
|
||||
id := int32(0)
|
||||
if err := s.db.Model(&ChatRecord{}).Where("user_id = ? and character_id = ?", user_id, character_id).Limit(1).Select("id").Scan(&id).Error; err != nil && err != gorm.ErrRecordNotFound {
|
||||
return false, err
|
||||
}
|
||||
return id > int32(0), nil
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
package dao
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"gorm.io/datatypes"
|
||||
"gorm.io/gorm"
|
||||
"gorm.io/gorm/clause"
|
||||
)
|
||||
|
||||
// 帖子草稿表
|
||||
type Draft struct {
|
||||
UserId int32 `gorm:"primaryKey;comment:'发帖人ID'"`
|
||||
CreatedAt time.Time `gorm:"type:datetime(0)"`
|
||||
UpdatedAt time.Time `gorm:"type:datetime(0)"`
|
||||
Title string `gorm:"index;type:varchar(255);comment:'帖子标题'"`
|
||||
Content string `gorm:"type:text;comment:'帖子内容'"`
|
||||
RoleIds datatypes.JSON `gorm:"comment:'关联角色'"`
|
||||
}
|
||||
|
||||
// 如果存在,就更新。如果不存在,就创建
|
||||
func Draft_Save(data *Draft) error {
|
||||
return s.db.Clauses(clause.OnConflict{Columns: []clause.Column{{Name: "user_id"}}, DoUpdates: clause.AssignmentColumns([]string{"title", "content", "role_ids"})}).Create(&data).Error
|
||||
}
|
||||
|
||||
func Draft_Query(userId int32) (*Draft, error) {
|
||||
var data Draft
|
||||
if err := s.db.Where("user_id = ?", userId).First(&data).Error; err != nil {
|
||||
if err == gorm.ErrRecordNotFound {
|
||||
return nil, nil
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
return &data, nil
|
||||
}
|
||||
|
||||
func Draft_Delete(userId int32) error {
|
||||
data := Draft{UserId: userId}
|
||||
return s.db.Delete(&data).Error
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
package dao
|
||||
|
||||
import (
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type File struct {
|
||||
BaseModel
|
||||
UUID string `gorm:"unique;type varchar(32);comment:'文件UUID'"`
|
||||
UserId int32 `gorm:"comment:'上传者ID'"`
|
||||
FileName string `gorm:"type:varchar(255);comment:'文件名称'"`
|
||||
FileSize uint32 `gorm:"comment:'文件大小'"`
|
||||
FileType string `gorm:"comment:'文件类型,对应html中支持的Content-Type类型'"`
|
||||
FileContent []byte `gorm:"type:mediumblob;comment:'文件内容,目前最大为16M'"`
|
||||
}
|
||||
|
||||
func File_Insert(data *File) (uint64, error) {
|
||||
if err := s.db.Create(data).Error; err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return uint64(data.ID), nil
|
||||
}
|
||||
|
||||
func File_Query(uuid string) (*File, error) {
|
||||
var data File
|
||||
if err := s.db.Where("uuid = ?", uuid).First(&data).Error; err != nil {
|
||||
if err == gorm.ErrRecordNotFound {
|
||||
return nil, nil
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
return &data, nil
|
||||
}
|
||||
|
||||
func File_Delete(uuid string) error {
|
||||
return s.db.Where("uuid = ?", uuid).Delete(&File{}).Error
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
package dao
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"gorm.io/datatypes"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// 帖子表
|
||||
type Post struct {
|
||||
BaseModel
|
||||
UserId int32 `gorm:"index;comment:'发帖人ID'"`
|
||||
Title string `gorm:"index;type:varchar(255);comment:'帖子标题'"`
|
||||
Content string `gorm:"type:text;comment:'帖子内容'"`
|
||||
RoleIds datatypes.JSON `gorm:"comment:'关联角色'"`
|
||||
}
|
||||
|
||||
func Post_Insert(data *Post) (uint64, error) {
|
||||
if err := s.db.Create(data).Error; err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return uint64(data.ID), nil
|
||||
}
|
||||
|
||||
func Post_Query(postId uint64) (*Post, error) {
|
||||
var data Post
|
||||
if err := s.db.Where("id = ?", postId).First(&data).Error; err != nil {
|
||||
if err == gorm.ErrRecordNotFound {
|
||||
return nil, nil
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
return &data, nil
|
||||
}
|
||||
|
||||
func Post_Page_Query(start_time, stop_time time.Time, role_id int32) ([]*Post, error) {
|
||||
var list []*Post
|
||||
var err error
|
||||
if role_id == int32(0) { // 不能根据role_id查询
|
||||
err = s.db.Where("created_at between ? and ?", start_time, stop_time).Find(&list).Error
|
||||
} else {
|
||||
err = s.db.Where("created_at between ? and ?", start_time, stop_time).Where(datatypes.JSONArrayQuery("role_ids").Contains(role_id)).Find(&list).Error
|
||||
}
|
||||
if err != nil && err != gorm.ErrRecordNotFound {
|
||||
return nil, err
|
||||
}
|
||||
return list, nil
|
||||
}
|
||||
|
||||
func Post_Delete(postId uint64) error {
|
||||
data := Post{}
|
||||
data.ID = postId
|
||||
return s.db.Delete(&data).Error
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
package dao
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// 帖子评论和回复表
|
||||
|
||||
type PostComment struct {
|
||||
ID uint64 `gorm:"primaryKey;not null;comment:'评论id'"`
|
||||
CreatedAt time.Time `gorm:"type:datetime(0)"`
|
||||
UserId int32 `gorm:"not null;comment:'评论者'"`
|
||||
PostId uint64 `gorm:"index;not null;comment:'帖子'"`
|
||||
Content string `gorm:"type:varchar(1024);not null;comment:'评论内容'"`
|
||||
// CommentId uint64 `gorm:"comment:'评论上级ID,作为回复某个评论时使用'"`
|
||||
}
|
||||
|
||||
func PostComment_Insert(data *PostComment) (uint64, error) {
|
||||
if err := s.db.Create(data).Error; err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return uint64(data.ID), nil
|
||||
}
|
||||
|
||||
// 根据帖子id,查询所有的评论
|
||||
func PostComment_QueryListByPostId(postId uint64) ([]*PostComment, error) {
|
||||
var list []*PostComment
|
||||
if err := s.db.Where("post_id = ?", postId).Find(&list).Error; err != nil && err != gorm.ErrRecordNotFound {
|
||||
return nil, err
|
||||
}
|
||||
return list, nil
|
||||
}
|
||||
|
||||
func PostComment_Delete(commentId uint64) error {
|
||||
data := PostComment{ID: commentId}
|
||||
return s.db.Delete(&data).Error
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
package dao
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// 贴子点赞表
|
||||
|
||||
type PostLike struct {
|
||||
PostId uint64 `gorm:"index;not null;comment:'帖子'"`
|
||||
UserId int32 `gorm:"index;not null;comment:'点赞者'"`
|
||||
CreatedAt time.Time `gorm:"type:datetime(0)"`
|
||||
}
|
||||
|
||||
// 点赞。如果已经点过赞了,则忽略。
|
||||
func PostLike_Like(data *PostLike) error {
|
||||
return s.db.Where("user_id = ? and post_id = ?", data.UserId, data.PostId).FirstOrCreate(data).Error
|
||||
}
|
||||
|
||||
// 去掉点赞
|
||||
func PostLike_UnLike(userId int32, postId uint64) error {
|
||||
return s.db.Where("user_id = ? and post_id = ?", userId, postId).Delete(&PostLike{}).Error
|
||||
}
|
||||
|
||||
// 获取点赞数
|
||||
func PostLike_Count(postId uint64) (int64, error) {
|
||||
count := int64(0)
|
||||
if err := s.db.Model(&PostLike{}).Where("post_id = ?", postId).Count(&count).Error; err != nil && err != gorm.ErrRecordNotFound {
|
||||
return 0, err
|
||||
}
|
||||
return count, nil
|
||||
}
|
||||
|
||||
// 批量获取帖子点赞数
|
||||
func PostLike_Count_Batch(postIds []uint64) (map[uint64]int64, error) {
|
||||
type search_result_item struct {
|
||||
PostId uint64
|
||||
LikeCount int64
|
||||
}
|
||||
var result []*search_result_item
|
||||
if err := s.db.Model(&PostLike{}).Where("post_id in (?)", postIds).Select("post_id,count(*) as like_count").Group("post_id").Scan(&result).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
reply := make(map[uint64]int64)
|
||||
for _, item := range result {
|
||||
reply[item.PostId] = item.LikeCount
|
||||
}
|
||||
return reply, nil
|
||||
}
|
||||
|
||||
// 当前用户有没有点赞
|
||||
func PostLike_Exists(userId int32, postId uint64) (bool, error) {
|
||||
count := int64(0)
|
||||
if err := s.db.Model(&PostLike{}).Where("user_id = ? and post_id = ?", userId, postId).Count(&count).Error; err != nil && err != gorm.ErrRecordNotFound {
|
||||
return false, err
|
||||
}
|
||||
return count != int64(0), nil
|
||||
}
|
||||
|
||||
// 批量查询用户有没有点赞
|
||||
func PostLike_Exists_Batch(userId int32, postIds []uint64) (map[uint64]bool, error) {
|
||||
var result []uint64
|
||||
if err := s.db.Model(&PostLike{}).Where("user_id = ?", userId).Where("post_id in (?)", postIds).Select("post_id").Group("post_id").Scan(&result).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
reply := make(map[uint64]bool)
|
||||
for _, post_id := range result {
|
||||
reply[post_id] = true
|
||||
}
|
||||
return reply, nil
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
package dao
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"mini_server/internal/logger"
|
||||
"time"
|
||||
|
||||
"gorm.io/driver/mysql"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type Service struct {
|
||||
dsn string
|
||||
db *gorm.DB
|
||||
}
|
||||
|
||||
var s *Service
|
||||
|
||||
// 获取当前时间,精度只精确到秒,去掉毫秒等数据。避免保存到数据库时时间进位
|
||||
func now_func() time.Time {
|
||||
tmp := time.Now().Local().Format(time.DateTime)
|
||||
now, _ := time.ParseInLocation(time.DateTime, tmp, time.Local)
|
||||
return now
|
||||
}
|
||||
|
||||
// // dsn example: "root:123@tcp(127.0.0.1:3306)/test"
|
||||
func InitDefaultService(dsn string) error {
|
||||
|
||||
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
|
||||
Logger: logger.GormLogger,
|
||||
NowFunc: now_func,
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("open mysql failed, dsn:%v, err:%v", dsn, err)
|
||||
}
|
||||
|
||||
dbs := &Service{dsn: dsn, db: db}
|
||||
|
||||
// 自动创建相关的表结构
|
||||
if err := auto_migrate_all(db); err != nil {
|
||||
return fmt.Errorf("automigrate failed, err:%v", err)
|
||||
}
|
||||
|
||||
// 数据库连接相关配置
|
||||
config_connection_info(db)
|
||||
|
||||
s = dbs
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// 自动创建对应的数据表结构
|
||||
func auto_migrate_all(db *gorm.DB) error {
|
||||
return db.AutoMigrate(
|
||||
//&Character{}, // 后续需要注释掉,避免修改客户创建的数据表
|
||||
&ChatRecord{},
|
||||
&File{},
|
||||
&Draft{},
|
||||
&PostLike{},
|
||||
&PostComment{},
|
||||
&Post{},
|
||||
&Bluetooth{},
|
||||
//&UserCharacter{}, // 需要注释掉,避免修改客户创建的数据表
|
||||
//&User{}, // 需要注释掉,避免修改客户创建的数据表
|
||||
)
|
||||
}
|
||||
|
||||
// 数据库连接相关配置
|
||||
func config_connection_info(db *gorm.DB) {
|
||||
mysqlDb, err := db.DB()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
mysqlDb.SetMaxIdleConns(10) // 设置连接池的最大限制连接数
|
||||
mysqlDb.SetMaxOpenConns(100) // 设置连接池中的最大连接数量
|
||||
}
|
|
@ -0,0 +1,97 @@
|
|||
package dao
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type User struct {
|
||||
ID int32 `gorm:"primarykey;type:int"`
|
||||
CreatedAt time.Time `gorm:"type:datetime(0)"`
|
||||
UpdatedAt time.Time `gorm:"type:datetime(0)"`
|
||||
DeletedAt gorm.DeletedAt `gorm:"index;type:datetime(0)"`
|
||||
Username string `gorm:"type:varchar(64);default null;comment:'用户名称'"`
|
||||
OpenId string `gorm:"type:varchar(255);default null;comment:'用户唯一标识'"`
|
||||
AvatarId string `gorm:"type:varchar(32);default null;comment:'头像图片uuid'"`
|
||||
Tags string `gorm:"type:json;default null;comment:'用户标签,json格式'"`
|
||||
Persona string `gorm:"type:json;default null;comment:'用户个性化数据,json格式'"`
|
||||
}
|
||||
|
||||
func (User) TableName() string { return "user" }
|
||||
|
||||
func User_WX_Insert(data *User) (int32, error) {
|
||||
if err := s.db.Create(data).Error; err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return data.ID, nil
|
||||
}
|
||||
|
||||
func User_WX_Query(openId string) (*User, error) {
|
||||
var data User
|
||||
if err := s.db.Where("open_id = ?", openId).First(&data).Error; err != nil {
|
||||
if err == gorm.ErrRecordNotFound {
|
||||
return nil, nil
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
return &data, nil
|
||||
}
|
||||
|
||||
func User_Query(userId int32) (*User, error) {
|
||||
var data User
|
||||
if err := s.db.Where("id = ?", userId).First(&data).Error; err != nil {
|
||||
if err == gorm.ErrRecordNotFound {
|
||||
return nil, nil
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
return &data, nil
|
||||
}
|
||||
|
||||
// 修改用户名称
|
||||
func User_Change_Username(userId int32, username string) error {
|
||||
user := &User{ID: userId}
|
||||
return s.db.Model(&user).Update("username", username).Error
|
||||
}
|
||||
|
||||
// 修改用户头像
|
||||
func User_Change_AvatarId(userId int32, avatarId string) error {
|
||||
user := &User{ID: userId}
|
||||
return s.db.Model(&user).Update("avatar_id", avatarId).Error
|
||||
}
|
||||
|
||||
// 查询用户信息列表,如果不存在,则设置为nil
|
||||
func User_Query_List(userIds []int32) (map[int32]*User, error) {
|
||||
var list []*User
|
||||
if err := s.db.Where("id in (?)", userIds).Find(&list).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
reply := make(map[int32]*User)
|
||||
for _, data := range list {
|
||||
reply[data.ID] = data
|
||||
}
|
||||
return reply, nil
|
||||
}
|
||||
|
||||
type UserBaseInfo struct {
|
||||
ID int32 `gorm:"column:id"`
|
||||
Username string `gorm:"column:username"`
|
||||
AvatarId string `gorm:"column:avatar_id"`
|
||||
}
|
||||
|
||||
// 批量查询用户的名称和头像信息
|
||||
func User_Query_List_BaseInfo(userIds []int32) (map[int32]*UserBaseInfo, error) {
|
||||
var list []*UserBaseInfo
|
||||
if err := s.db.Model(&User{}).Where("id in (?)", userIds).Select("id, username, avatar_id").Find(&list).Error; err != nil && err != gorm.ErrRecordNotFound {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
m := make(map[int32]*UserBaseInfo)
|
||||
for _, info := range list {
|
||||
m[info.ID] = info
|
||||
}
|
||||
|
||||
return m, nil
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
package dao
|
||||
|
||||
type UserCharacter struct {
|
||||
ID int32 `gorm:"primaryKey;type:int;not null;auto_increment;comment:'角色ID'"`
|
||||
UserId int32 `gorm:"default null;comment:'关联的用户ID'"`
|
||||
CharacterId int32 `gorm:"default null;comment:'关联的角色ID'"`
|
||||
Persona string `gorm:"type:json;default null;comment:'个性化配置'"`
|
||||
}
|
||||
|
||||
// 根据userId,查询关联的角色表
|
||||
func UserCharacter_QueryList(userId int32) ([]*UserCharacter, error) {
|
||||
var list []*UserCharacter
|
||||
if err := s.db.Where("user_id = ?", userId).Find(&list).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return list, nil
|
||||
}
|
||||
|
||||
// 根据userId,查询关联角色的role_id
|
||||
func UserCharacter_QueryList_OnlyCharacterId(userId int32) ([]int32, error) {
|
||||
var list []int32
|
||||
if err := s.db.Model(&UserCharacter{}).Where("user_id = ?", userId).Select("character_id").Scan(&list).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return list, nil
|
||||
}
|
|
@ -0,0 +1,149 @@
|
|||
package logger
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
"gorm.io/gorm/logger"
|
||||
"gorm.io/gorm/utils"
|
||||
)
|
||||
|
||||
// Colors
|
||||
const (
|
||||
Reset = "\033[0m"
|
||||
Red = "\033[31m"
|
||||
Green = "\033[32m"
|
||||
Yellow = "\033[33m"
|
||||
Blue = "\033[34m"
|
||||
Magenta = "\033[35m"
|
||||
Cyan = "\033[36m"
|
||||
White = "\033[37m"
|
||||
BlueBold = "\033[34;1m"
|
||||
MagentaBold = "\033[35;1m"
|
||||
RedBold = "\033[31;1m"
|
||||
YellowBold = "\033[33;1m"
|
||||
)
|
||||
|
||||
// New initialize logger
|
||||
func NewGormLogger(logursLogger *logrus.Logger, config logger.Config) logger.Interface {
|
||||
var (
|
||||
infoStr = "%s[info] "
|
||||
warnStr = "%s[warn] "
|
||||
errStr = "%s[error] "
|
||||
traceStr = "%s[%.3fms] [rows:%v] %s"
|
||||
traceWarnStr = "%s %s[%.3fms] [rows:%v] %s"
|
||||
traceErrStr = "%s %s[%.3fms] [rows:%v] %s"
|
||||
)
|
||||
|
||||
if config.Colorful {
|
||||
infoStr = Green + "%s" + Reset + Green + "[info] " + Reset
|
||||
warnStr = BlueBold + "%s" + Reset + Magenta + "[warn] " + Reset
|
||||
errStr = Magenta + "%s" + Reset + Red + "[error] " + Reset
|
||||
traceStr = Green + "%s" + Reset + Yellow + "[%.3fms] " + BlueBold + "[rows:%v]" + Reset + " %s"
|
||||
traceWarnStr = Green + "%s " + Yellow + "%s" + Reset + RedBold + "[%.3fms] " + Yellow + "[rows:%v]" + Magenta + " %s" + Reset
|
||||
traceErrStr = RedBold + "%s " + MagentaBold + "%s" + Reset + Yellow + "[%.3fms] " + BlueBold + "[rows:%v]" + Reset + " %s"
|
||||
}
|
||||
|
||||
switch config.LogLevel {
|
||||
case logger.Silent:
|
||||
logursLogger.SetLevel(logrus.FatalLevel)
|
||||
case logger.Error:
|
||||
logursLogger.SetLevel(logrus.ErrorLevel)
|
||||
case logger.Warn:
|
||||
logursLogger.SetLevel(logrus.WarnLevel)
|
||||
case logger.Info:
|
||||
logursLogger.SetLevel(logrus.TraceLevel)
|
||||
}
|
||||
|
||||
return &gormLogger{
|
||||
Logger: logursLogger,
|
||||
Config: config,
|
||||
infoStr: infoStr,
|
||||
warnStr: warnStr,
|
||||
errStr: errStr,
|
||||
traceStr: traceStr,
|
||||
traceWarnStr: traceWarnStr,
|
||||
traceErrStr: traceErrStr,
|
||||
}
|
||||
}
|
||||
|
||||
type gormLogger struct {
|
||||
Logger *logrus.Logger
|
||||
logger.Config
|
||||
infoStr, warnStr, errStr string
|
||||
traceStr, traceErrStr, traceWarnStr string
|
||||
}
|
||||
|
||||
// LogMode log mode
|
||||
func (l *gormLogger) LogMode(level logger.LogLevel) logger.Interface {
|
||||
newlogger := *l
|
||||
newlogger.LogLevel = level
|
||||
return &newlogger
|
||||
}
|
||||
|
||||
// Info print info
|
||||
func (l *gormLogger) Info(ctx context.Context, msg string, data ...interface{}) {
|
||||
if l.LogLevel >= logger.Info {
|
||||
l.Logger.Infof(l.infoStr+msg, append([]interface{}{utils.FileWithLineNum()}, data...)...)
|
||||
}
|
||||
}
|
||||
|
||||
// Warn print warn messages
|
||||
func (l *gormLogger) Warn(ctx context.Context, msg string, data ...interface{}) {
|
||||
if l.LogLevel >= logger.Warn {
|
||||
l.Logger.Warnf(l.warnStr+msg, append([]interface{}{utils.FileWithLineNum()}, data...)...)
|
||||
}
|
||||
}
|
||||
|
||||
// Error print error messages
|
||||
func (l *gormLogger) Error(ctx context.Context, msg string, data ...interface{}) {
|
||||
if l.LogLevel >= logger.Error {
|
||||
l.Logger.Errorf(l.errStr+msg, append([]interface{}{utils.FileWithLineNum()}, data...)...)
|
||||
}
|
||||
}
|
||||
|
||||
// Trace print sql message
|
||||
//
|
||||
//nolint:cyclop
|
||||
func (l *gormLogger) Trace(ctx context.Context, begin time.Time, fc func() (string, int64), err error) {
|
||||
if l.LogLevel <= logger.Silent {
|
||||
return
|
||||
}
|
||||
|
||||
elapsed := time.Since(begin)
|
||||
switch {
|
||||
case err != nil && l.LogLevel >= logger.Error && (!errors.Is(err, logger.ErrRecordNotFound) || !l.IgnoreRecordNotFoundError):
|
||||
sql, rows := fc()
|
||||
if rows == -1 {
|
||||
l.Logger.Errorf(l.traceErrStr, utils.FileWithLineNum(), err, float64(elapsed.Nanoseconds())/1e6, "-", sql)
|
||||
} else {
|
||||
l.Logger.Errorf(l.traceErrStr, utils.FileWithLineNum(), err, float64(elapsed.Nanoseconds())/1e6, rows, sql)
|
||||
}
|
||||
case elapsed > l.SlowThreshold && l.SlowThreshold != 0 && l.LogLevel >= logger.Warn:
|
||||
sql, rows := fc()
|
||||
slowLog := fmt.Sprintf("SLOW SQL >= %v", l.SlowThreshold)
|
||||
if rows == -1 {
|
||||
l.Logger.Warnf(l.traceWarnStr, utils.FileWithLineNum(), slowLog, float64(elapsed.Nanoseconds())/1e6, "-", sql)
|
||||
} else {
|
||||
l.Logger.Warnf(l.traceWarnStr, utils.FileWithLineNum(), slowLog, float64(elapsed.Nanoseconds())/1e6, rows, sql)
|
||||
}
|
||||
case l.LogLevel == logger.Info:
|
||||
sql, rows := fc()
|
||||
if rows == -1 {
|
||||
l.Logger.Infof(l.traceStr, utils.FileWithLineNum(), float64(elapsed.Nanoseconds())/1e6, "-", sql)
|
||||
} else {
|
||||
l.Logger.Infof(l.traceStr, utils.FileWithLineNum(), float64(elapsed.Nanoseconds())/1e6, rows, sql)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ParamsFilter filter params
|
||||
func (l *gormLogger) ParamsFilter(ctx context.Context, sql string, params ...interface{}) (string, []interface{}) {
|
||||
if l.Config.ParameterizedQueries {
|
||||
return sql, nil
|
||||
}
|
||||
return sql, params
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
package logger
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"mini_server/internal/config"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/sirupsen/logrus"
|
||||
"gorm.io/gorm/logger"
|
||||
)
|
||||
|
||||
var GinLogger io.Writer
|
||||
var GormLogger logger.Interface
|
||||
|
||||
func create_file() *os.File {
|
||||
f, err := os.OpenFile(config.LogFile, os.O_CREATE|os.O_APPEND|os.O_RDWR, 0644)
|
||||
if err != nil {
|
||||
fmt.Printf("日志文件打开失败,err:%v", err)
|
||||
os.Exit(-1)
|
||||
}
|
||||
return f
|
||||
}
|
||||
|
||||
func Init_log() {
|
||||
|
||||
f := create_file()
|
||||
// writer := io.MultiWriter(f, os.Stdout)
|
||||
writer := io.MultiWriter(f)
|
||||
|
||||
logrus.SetLevel(config.LogLevel)
|
||||
//设置日志格式,使用自定义格式
|
||||
logrus.SetFormatter(&MyFormatter{for_server: true})
|
||||
// 设置业务日志
|
||||
gin.DisableConsoleColor()
|
||||
logrus.SetOutput(writer)
|
||||
|
||||
// 设置GIN日志文件
|
||||
GinLogger = io.MultiWriter(writer)
|
||||
|
||||
gormLogrus := logrus.New()
|
||||
gormLogrus.SetFormatter(&MyFormatter{for_gorm: true})
|
||||
gormLogrus.SetOutput(writer)
|
||||
// 设置GORM日志文件
|
||||
GormLogger = NewGormLogger(
|
||||
gormLogrus,
|
||||
logger.Config{
|
||||
SlowThreshold: time.Second, // 慢SQL阈值
|
||||
LogLevel: logger.Info,
|
||||
Colorful: false, // 禁用彩色打印
|
||||
IgnoreRecordNotFoundError: true, // 不打印未查询到的日志
|
||||
},
|
||||
)
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
package logger
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
type MyFormatter struct {
|
||||
for_server bool
|
||||
for_gorm bool
|
||||
}
|
||||
|
||||
func (m *MyFormatter) Format(entry *logrus.Entry) ([]byte, error) {
|
||||
var b *bytes.Buffer
|
||||
if entry.Buffer != nil {
|
||||
b = entry.Buffer
|
||||
} else {
|
||||
b = &bytes.Buffer{}
|
||||
}
|
||||
timestamp := entry.Time.Format(time.DateTime)
|
||||
var line string
|
||||
if m.for_gorm {
|
||||
line = fmt.Sprintf("[GORM ] [%s] [%s] %s\r\n", timestamp, entry.Level, entry.Message)
|
||||
} else {
|
||||
line = fmt.Sprintf("[SERVER] [%s] [%s] %s\r\n", timestamp, entry.Level, entry.Message)
|
||||
}
|
||||
b.WriteString(line)
|
||||
return b.Bytes(), nil
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
package cors
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func CorsMiddleware() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
// 设置允许的方法
|
||||
c.Writer.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE")
|
||||
|
||||
// 设置允许的头
|
||||
c.Writer.Header().Set("Access-Control-Allow-Headers", "Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization")
|
||||
|
||||
// 设置允许的来源,* 表示允许所有来源
|
||||
c.Writer.Header().Set("Access-Control-Allow-Origin", "*")
|
||||
|
||||
// 如果是OPTIONS请求,直接返回,不继续处理
|
||||
if c.Request.Method == "OPTIONS" {
|
||||
c.AbortWithStatus(http.StatusOK)
|
||||
return
|
||||
}
|
||||
|
||||
// 继续处理请求
|
||||
c.Next()
|
||||
}
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
package jwt
|
||||
|
||||
import (
|
||||
"mini_server/internal/config"
|
||||
"mini_server/internal/dao"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/dgrijalva/jwt-go"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
var jwtKey = []byte(config.JwtKey)
|
||||
|
||||
type Claims struct {
|
||||
Username string `json:"username"`
|
||||
ID int32 `json:"id"`
|
||||
jwt.StandardClaims
|
||||
}
|
||||
|
||||
func CreateToken(user *dao.User) (string, error) {
|
||||
token := jwt.NewWithClaims(jwt.SigningMethodHS256, &Claims{
|
||||
ID: user.ID,
|
||||
Username: user.Username,
|
||||
StandardClaims: jwt.StandardClaims{
|
||||
ExpiresAt: jwt.TimeFunc().Add(time.Hour * 24).Unix(), // Token expires in 24 hours
|
||||
IssuedAt: jwt.TimeFunc().Unix(),
|
||||
},
|
||||
})
|
||||
return token.SignedString(jwtKey)
|
||||
}
|
||||
|
||||
func AuthenticateToken(tokenString string) (*Claims, error) {
|
||||
token, err := jwt.ParseWithClaims(tokenString, &Claims{}, func(token *jwt.Token) (interface{}, error) {
|
||||
return jwtKey, nil
|
||||
})
|
||||
if claims, ok := token.Claims.(*Claims); ok && token.Valid {
|
||||
return claims, nil
|
||||
} else {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
func AuthMiddleware() gin.HandlerFunc {
|
||||
return func(ctx *gin.Context) {
|
||||
if !withinWhiteList(ctx.Request.URL, ctx.Request.Method) {
|
||||
tokenString := ctx.GetHeader("Authorization")
|
||||
if tokenString == "" {
|
||||
ctx.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "Unauthorized"})
|
||||
return
|
||||
}
|
||||
|
||||
claims, err := AuthenticateToken(tokenString)
|
||||
if err != nil {
|
||||
ctx.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "Unauthorized"})
|
||||
return
|
||||
}
|
||||
ctx.Set("user", claims)
|
||||
}
|
||||
ctx.Next()
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
package jwt
|
||||
|
||||
import (
|
||||
"mini_server/internal/config"
|
||||
"net/url"
|
||||
)
|
||||
|
||||
func withinWhiteList(url *url.URL, method string) bool {
|
||||
target := config.JwtApiAuthWhiteList
|
||||
path := url.Path
|
||||
if v, ok := target[path]; ok && (method == v) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
package tls
|
||||
|
||||
import (
|
||||
"mini_server/internal/config"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/unrolled/secure"
|
||||
)
|
||||
|
||||
func TlsHandler() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
secureMiddleware := secure.New(secure.Options{
|
||||
SSLRedirect: true,
|
||||
SSLHost: config.ServerListenAddress,
|
||||
})
|
||||
err := secureMiddleware.Process(c.Writer, c.Request)
|
||||
|
||||
// If there was an error, do not continue.
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
c.Next()
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
package otherapi
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"io"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
func http_post(url string, request, reply any) error {
|
||||
jsonData, err := json.Marshal(request)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
httpRequest, err := http.NewRequest(http.MethodPost, url, bytes.NewBuffer(jsonData))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
httpRequest.Header.Set("Content-Type", "application/json")
|
||||
client := &http.Client{}
|
||||
response, err := client.Do(httpRequest)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer response.Body.Close()
|
||||
body, err := io.ReadAll(response.Body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return json.Unmarshal(body, reply)
|
||||
}
|
|
@ -0,0 +1,101 @@
|
|||
package bluetooth
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"mini_server/internal/dao"
|
||||
"mini_server/internal/server/help"
|
||||
"mini_server/internal/server/httpreply"
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
type CreateRequest struct {
|
||||
DeviceId string `gorm:"unique;type varchar(64);not null;comment:'设备Id,唯一标识每个蓝牙设备'"`
|
||||
DeviceName string `gorm:"type varchar(64);comment:'蓝牙名称'"`
|
||||
DeviceType string `gorm:"type varchar(64);comment:'设备类型'"`
|
||||
}
|
||||
|
||||
// 添加角色
|
||||
func Create(c *gin.Context) {
|
||||
reply := httpreply.NewDefaultReplyData()
|
||||
defer httpreply.Reply(c, reply)
|
||||
|
||||
var request CreateRequest
|
||||
if err := c.ShouldBindJSON(&request); err != nil {
|
||||
reply.Status = http.StatusBadRequest
|
||||
reply.Message = fmt.Sprintf("invalid json data,err:%v", err)
|
||||
return
|
||||
}
|
||||
|
||||
userid, res := help.GetUserId(c)
|
||||
if !res {
|
||||
reply.Status = http.StatusInternalServerError
|
||||
reply.Message = "登录信息已失效"
|
||||
return
|
||||
}
|
||||
|
||||
data := dao.Bluetooth{
|
||||
DeviceId: request.DeviceId,
|
||||
DeviceName: request.DeviceName,
|
||||
DeviceType: request.DeviceType,
|
||||
UserId: userid,
|
||||
}
|
||||
|
||||
err := dao.AddBluetooth(&data)
|
||||
if err != nil {
|
||||
logrus.Errorf("dao.Bluetooth_Insert failed, err:%v", err)
|
||||
reply.Status = http.StatusInternalServerError
|
||||
reply.Message = "添加蓝牙失败"
|
||||
return
|
||||
}
|
||||
reply.Data = data
|
||||
}
|
||||
|
||||
func QueryAll(c *gin.Context) {
|
||||
reply := httpreply.NewDefaultReplyData()
|
||||
defer httpreply.Reply(c, reply)
|
||||
|
||||
userid, res := help.GetUserId(c)
|
||||
if !res {
|
||||
reply.Status = http.StatusInternalServerError
|
||||
reply.Message = "登录信息已失效"
|
||||
return
|
||||
}
|
||||
data, err := dao.GetAllBluetooth(userid)
|
||||
if err != nil {
|
||||
reply.Status = http.StatusInternalServerError
|
||||
reply.Message = "蓝牙查询异常"
|
||||
return
|
||||
}
|
||||
reply.Data = data
|
||||
}
|
||||
|
||||
func Delete(c *gin.Context) {
|
||||
reply := httpreply.NewDefaultReplyData()
|
||||
defer httpreply.Reply(c, reply)
|
||||
|
||||
var request CreateRequest
|
||||
if err := c.ShouldBindJSON(&request); err != nil {
|
||||
reply.Status = http.StatusBadRequest
|
||||
reply.Message = fmt.Sprintf("invalid json data,err:%v", err)
|
||||
return
|
||||
}
|
||||
|
||||
userid, res := help.GetUserId(c)
|
||||
if !res {
|
||||
reply.Status = http.StatusInternalServerError
|
||||
reply.Message = "登录信息已失效"
|
||||
return
|
||||
}
|
||||
|
||||
err := dao.DeleteBluetooth(request.DeviceId, userid)
|
||||
if err != nil {
|
||||
logrus.Errorf("dao.Bluetooth_Delete failed, err:%v", err)
|
||||
reply.Status = http.StatusInternalServerError
|
||||
reply.Message = "删除蓝牙失败"
|
||||
return
|
||||
}
|
||||
reply.Data = err
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
package bluetooth
|
||||
|
||||
import "github.com/gin-gonic/gin"
|
||||
|
||||
// 查询用户保存的蓝牙列表
|
||||
func List(c *gin.Context) {}
|
|
@ -0,0 +1,6 @@
|
|||
package bluetooth
|
||||
|
||||
import "github.com/gin-gonic/gin"
|
||||
|
||||
// 上传蓝牙信息
|
||||
func Upload(c *gin.Context) {}
|
|
@ -0,0 +1,51 @@
|
|||
package chatrecord
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"mini_server/internal/dao"
|
||||
"mini_server/internal/server/help"
|
||||
"mini_server/internal/server/httpreply"
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
type ExistsRequest struct {
|
||||
RoleId int32 `form:"role_id" binding:"min=1"` // 角色ID
|
||||
}
|
||||
|
||||
type ExistsReply struct {
|
||||
Exists bool `json:"exists"`
|
||||
}
|
||||
|
||||
func Exists(c *gin.Context) {
|
||||
reply := httpreply.NewDefaultReplyData()
|
||||
defer httpreply.Reply(c, reply)
|
||||
|
||||
//解析请求参数
|
||||
var request ExistsRequest
|
||||
if err := c.ShouldBind(&request); err != nil {
|
||||
reply.Status = http.StatusBadRequest
|
||||
reply.Message = fmt.Sprintf("invalid json data, err:%v", err)
|
||||
return
|
||||
}
|
||||
|
||||
userId, ok := help.GetUserId(c)
|
||||
if !ok {
|
||||
reply.Status = http.StatusNotFound
|
||||
reply.Message = "无法获取用户信息"
|
||||
return
|
||||
}
|
||||
|
||||
// 在数据库中查询,是否存在角色和用户的聊天记录。
|
||||
exists, err := dao.ChatRecord_Exists(userId, request.RoleId)
|
||||
if err != nil {
|
||||
logrus.Errorf("数据库查询是否存在聊天记录时失败,userId:%d,roleId:%d,err:%v", userId, request.RoleId, err)
|
||||
reply.Status = http.StatusInternalServerError
|
||||
reply.Message = "数据库查询是否存在聊天记录时失败"
|
||||
return
|
||||
}
|
||||
|
||||
reply.Data = ExistsReply{Exists: exists}
|
||||
}
|
|
@ -0,0 +1,77 @@
|
|||
package chatrecord
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"mini_server/internal/dao"
|
||||
"mini_server/internal/server/help"
|
||||
"mini_server/internal/server/httpreply"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
type ChatRecordInfo struct {
|
||||
ChatRecordId uint64 `json:"chat_record_id"`
|
||||
UserId int32 `json:"user_id"`
|
||||
RoleId int32 `json:"role_id"`
|
||||
Direction int8 `json:"direction"`
|
||||
Message string `json:"message"`
|
||||
CreatedAt string `json:"create_at"` // 使用string保存,在设置时,不带时区
|
||||
}
|
||||
|
||||
type HistoryRequest struct {
|
||||
RoleId int32 `form:"role_id" binding:"required,gt=0"`
|
||||
StartTime time.Time `form:"start_time" binding:"required" time_format:"2006-01-02 15:04:05"`
|
||||
StopTime time.Time `form:"stop_time" binding:"required,gtfield=StartTime" time_format:"2006-01-02 15:04:05"`
|
||||
}
|
||||
|
||||
type HistoryReply struct {
|
||||
List []*ChatRecordInfo `json:"list"`
|
||||
}
|
||||
|
||||
// 聊天记录历史查询,支持分页查询
|
||||
func History(c *gin.Context) {
|
||||
reply := httpreply.NewDefaultReplyData()
|
||||
defer httpreply.Reply(c, reply)
|
||||
|
||||
userId, ok := help.GetUserId(c)
|
||||
if !ok {
|
||||
reply.Status = http.StatusNotFound
|
||||
reply.Message = "无法获取用户信息"
|
||||
return
|
||||
}
|
||||
|
||||
var request HistoryRequest
|
||||
if err := c.ShouldBind(&request); err != nil {
|
||||
reply.Status = http.StatusBadRequest
|
||||
reply.Message = fmt.Sprintf("invalid query args, err:%v", err)
|
||||
return
|
||||
}
|
||||
|
||||
list, err := dao.ChatRecord_Query(userId, request.RoleId, request.StartTime, request.StopTime)
|
||||
if err != nil {
|
||||
logrus.Errorf("聊天记录查询失败,request:%v,err:%v", request, err)
|
||||
reply.Status = http.StatusInternalServerError
|
||||
reply.Message = "聊天记录查询失败"
|
||||
return
|
||||
}
|
||||
|
||||
chatRecordList := make([]*ChatRecordInfo, len(list))
|
||||
for i, data := range list {
|
||||
var info ChatRecordInfo
|
||||
copy_from_mysql(data, &info)
|
||||
chatRecordList[i] = &info
|
||||
}
|
||||
reply.Data = &HistoryReply{List: chatRecordList}
|
||||
}
|
||||
|
||||
func copy_from_mysql(data *dao.ChatRecord, info *ChatRecordInfo) {
|
||||
info.ChatRecordId = data.ID
|
||||
info.UserId = data.UserId
|
||||
info.RoleId = data.CharacterId
|
||||
info.Direction = data.Direction
|
||||
info.Message = data.Message
|
||||
info.CreatedAt = data.CreatedAt.Format(time.DateTime)
|
||||
}
|
|
@ -0,0 +1,93 @@
|
|||
package chatrecord
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"mini_server/internal/dao"
|
||||
"mini_server/internal/server/help"
|
||||
"mini_server/internal/server/httpreply"
|
||||
"mini_server/internal/server/role"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
type HistoryAllRequest struct {
|
||||
StartTime time.Time `form:"start_time" binding:"required" time_format:"2006-01-02 15:04:05"`
|
||||
StopTime time.Time `form:"stop_time" binding:"required,gtfield=StartTime" time_format:"2006-01-02 15:04:05"`
|
||||
}
|
||||
|
||||
type HistoryAllItem struct {
|
||||
RoleInfo *role.RoleInfo `json:"role_info"`
|
||||
List []*ChatRecordInfo `json:"list"`
|
||||
}
|
||||
|
||||
type HistoryAllReply struct {
|
||||
RoleList []*HistoryAllItem `json:"role_list"`
|
||||
}
|
||||
|
||||
// 查询用户和全部角色的聊天记录。
|
||||
func HistoryAll(c *gin.Context) {
|
||||
|
||||
reply := httpreply.NewDefaultReplyData()
|
||||
defer httpreply.Reply(c, reply)
|
||||
|
||||
userId, ok := help.GetUserId(c)
|
||||
if !ok {
|
||||
reply.Status = http.StatusNotFound
|
||||
reply.Message = "无法获取用户信息"
|
||||
return
|
||||
}
|
||||
|
||||
var request HistoryAllRequest
|
||||
if err := c.ShouldBind(&request); err != nil {
|
||||
reply.Status = http.StatusBadRequest
|
||||
reply.Message = fmt.Sprintf("invalid query args, err:%v", err)
|
||||
return
|
||||
}
|
||||
|
||||
// 根据用户查询聊天记录。
|
||||
list, err := dao.ChatRecord_Query_ByUserId(userId, request.StartTime, request.StopTime)
|
||||
if err != nil {
|
||||
logrus.Errorf("聊天记录查询失败,request:%v,err:%v", request, err)
|
||||
reply.Status = http.StatusInternalServerError
|
||||
reply.Message = "聊天记录查询失败"
|
||||
return
|
||||
}
|
||||
|
||||
role_list := make([]*HistoryAllItem, 0)
|
||||
mapExistsRole := map[int32]int{} // key是role_id,value是列表中的下标。
|
||||
role_ids := make([]int32, 0)
|
||||
for _, data := range list {
|
||||
role_id := data.CharacterId
|
||||
index, ok := mapExistsRole[role_id]
|
||||
if !ok { // 不存在,则添加。
|
||||
index = len(role_list)
|
||||
mapExistsRole[role_id] = index
|
||||
role_list = append(role_list, &HistoryAllItem{RoleInfo: nil, List: make([]*ChatRecordInfo, 0)})
|
||||
role_ids = append(role_ids, role_id)
|
||||
}
|
||||
var info ChatRecordInfo
|
||||
copy_from_mysql(data, &info)
|
||||
role_list[index].List = append(role_list[index].List, &info)
|
||||
}
|
||||
if len(role_ids) > 0 {
|
||||
// 根据角色id列表,查询角色的头像和名称
|
||||
role_infos, err := dao.Character_QueryList(role_ids)
|
||||
if err != nil {
|
||||
logrus.Errorf("查询角色基础信息失败,role_ids:%v,err:%v", role_ids, err)
|
||||
reply.Status = http.StatusInternalServerError
|
||||
reply.Message = "查询角色基础信息失败"
|
||||
return
|
||||
}
|
||||
for _, role_info := range role_infos {
|
||||
role_id := role_info.ID
|
||||
var detail role.RoleInfo
|
||||
role.Copy_mysql_data(role_info, &detail)
|
||||
role_list[mapExistsRole[role_id]].RoleInfo = &detail
|
||||
}
|
||||
}
|
||||
|
||||
reply.Data = &HistoryAllReply{RoleList: role_list}
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
package chatrecord
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"mini_server/internal/dao"
|
||||
"mini_server/internal/server/help"
|
||||
"mini_server/internal/server/httpreply"
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
type UploadRequest struct {
|
||||
RoleId int32 `json:"role_id" binding:"required,gt=0"`
|
||||
Direction *int `json:"direction" binding:"required,oneof=0 1"` // 整数required时,无法接收0值,会报错。需要定义为指针类型
|
||||
Message string `json:"message" binding:"required,min=1"`
|
||||
}
|
||||
|
||||
// 上传聊天记录
|
||||
func Upload(c *gin.Context) {
|
||||
reply := httpreply.NewDefaultReplyData()
|
||||
defer httpreply.Reply(c, reply)
|
||||
|
||||
userId, ok := help.GetUserId(c)
|
||||
if !ok {
|
||||
reply.Status = http.StatusNotFound
|
||||
reply.Message = "无法获取用户信息"
|
||||
return
|
||||
}
|
||||
|
||||
var info UploadRequest
|
||||
if err := c.ShouldBindJSON(&info); err != nil {
|
||||
reply.Status = http.StatusBadRequest
|
||||
reply.Message = fmt.Sprintf("invalid json data:%v", err)
|
||||
return
|
||||
}
|
||||
|
||||
data := dao.ChatRecord{
|
||||
UserId: userId,
|
||||
CharacterId: info.RoleId,
|
||||
Direction: int8(*info.Direction),
|
||||
Message: info.Message,
|
||||
}
|
||||
if err := dao.ChatRecord_Insert(&data); err != nil {
|
||||
logrus.Errorf("保存聊天记录失败,info:%v,err:%v", info, err)
|
||||
reply.Status = http.StatusInternalServerError
|
||||
reply.Message = "聊天记录保存失败"
|
||||
return
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
package file
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"mini_server/internal/dao"
|
||||
"mini_server/internal/server/httpreply"
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
type DeleteURI struct {
|
||||
FileId string `uri:"file_id" binding:"len=32"`
|
||||
}
|
||||
|
||||
// 文件删除接口
|
||||
|
||||
func Delete(c *gin.Context) {
|
||||
reply := httpreply.NewDefaultReplyData()
|
||||
defer httpreply.Reply(c, reply)
|
||||
|
||||
var param DeleteURI
|
||||
if err := c.ShouldBindUri(¶m); err != nil {
|
||||
reply.Status = http.StatusBadRequest
|
||||
reply.Message = fmt.Sprintf("invalid uri path,err:%v", err)
|
||||
return
|
||||
}
|
||||
|
||||
if err := dao.File_Delete(param.FileId); err != nil {
|
||||
logrus.Errorf("删除文件失败,文件id:%s,err:%v", param.FileId, err)
|
||||
reply.Status = http.StatusInternalServerError
|
||||
reply.Message = "数据库删除失败"
|
||||
return
|
||||
}
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
package file
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"mini_server/internal/config"
|
||||
"mini_server/internal/dao"
|
||||
"mini_server/internal/server/help"
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
type DownloadURI struct {
|
||||
FileId string `uri:"file_id" binding:"len=32"`
|
||||
}
|
||||
|
||||
// 文件下载接口
|
||||
func Download(c *gin.Context) {
|
||||
var param DownloadURI
|
||||
if err := c.ShouldBindUri(¶m); err != nil {
|
||||
c.JSON(http.StatusBadRequest, fmt.Sprintf("invalid download uri,err:%v", err))
|
||||
return
|
||||
}
|
||||
|
||||
fileId := param.FileId
|
||||
var data *dao.File
|
||||
var err error
|
||||
var ok bool
|
||||
|
||||
if config.FileCacheEnable { // 从文件缓存中查询
|
||||
if data, ok = help.GetFileCache(fileId); ok {
|
||||
logrus.Tracef("从内存缓存中获取文件数据,file_uuid:%v", fileId)
|
||||
}
|
||||
}
|
||||
|
||||
if data == nil { // 未获取到文件缓存数据
|
||||
logrus.Tracef("从msyql中获取文件数据,file_uuid:%v", fileId)
|
||||
data, err = dao.File_Query(param.FileId)
|
||||
if err != nil {
|
||||
logrus.Errorf("文件下载失败,fileId:%s,err:%v", param.FileId, err)
|
||||
c.JSON(http.StatusInternalServerError, "文件下载失败")
|
||||
return
|
||||
}
|
||||
if data == nil { // 文件不存在
|
||||
logrus.Errorf("文件下载失败,文件file_id:%v不存在", param.FileId)
|
||||
c.JSON(http.StatusNotFound, "文件不存在")
|
||||
return
|
||||
}
|
||||
|
||||
if config.FileCacheEnable { // 更新到文件缓存中
|
||||
help.SetFileCache(fileId, data)
|
||||
}
|
||||
}
|
||||
|
||||
logrus.Tracef("文件%s下载成功,文件大小:%d,数据库中blob实际大小:%d", data.FileName, data.FileSize, len(data.FileContent))
|
||||
c.Header("Content-Disposition", "attachment;filename="+data.FileName)
|
||||
c.Header("Content-Type", data.FileType)
|
||||
c.Header("Accept-Length", fmt.Sprintf("%d", data.FileSize))
|
||||
c.Writer.WriteHeader(http.StatusOK)
|
||||
c.Writer.Write(data.FileContent)
|
||||
}
|
|
@ -0,0 +1,83 @@
|
|||
package file
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/hex"
|
||||
"io"
|
||||
"log"
|
||||
"mini_server/internal/dao"
|
||||
"mini_server/internal/server/help"
|
||||
"mini_server/internal/server/httpreply"
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/google/uuid"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
type UploadReply struct {
|
||||
FileId string `json:"file_id"` // 文件uuid,返回file_uuid
|
||||
}
|
||||
|
||||
// 文件上传接口
|
||||
|
||||
func Upload(c *gin.Context) {
|
||||
reply := httpreply.NewDefaultReplyData()
|
||||
defer httpreply.Reply(c, reply)
|
||||
|
||||
userId, ok := help.GetUserId(c)
|
||||
if !ok {
|
||||
reply.Status = http.StatusNotFound
|
||||
reply.Message = "无法获取用户信息"
|
||||
return
|
||||
}
|
||||
|
||||
file, err := c.FormFile("file")
|
||||
if err != nil {
|
||||
reply.Status = http.StatusBadRequest
|
||||
reply.Message = "无法获取文件信息"
|
||||
return
|
||||
}
|
||||
|
||||
// 读取文件中的数据,并写入到数据库中
|
||||
reader, _ := file.Open()
|
||||
defer reader.Close()
|
||||
|
||||
// 添加文件大小限制,目前使用mediumblob,有16M存储限制
|
||||
if file.Size >= int64(1024*1024*16) {
|
||||
reply.Status = http.StatusRequestEntityTooLarge
|
||||
reply.Message = "上传文件超过限制,目前最多支持16M文件上传"
|
||||
return
|
||||
}
|
||||
|
||||
// 拷贝数据
|
||||
buf := bytes.NewBuffer(nil)
|
||||
if _, err := io.Copy(buf, reader); err != nil {
|
||||
reply.Status = http.StatusInternalServerError
|
||||
reply.Message = "copy file failed"
|
||||
return
|
||||
}
|
||||
fileType := http.DetectContentType(buf.Bytes())
|
||||
log.Printf("文件上传请求,文件名:%v, 文件大小:%d, 文件类型:%v", file.Filename, file.Size, fileType)
|
||||
|
||||
// 将数据写入数据库中
|
||||
bytesUUID, _ := uuid.NewUUID()
|
||||
uuid := hex.EncodeToString(bytesUUID[:])
|
||||
data := &dao.File{
|
||||
UUID: uuid, // 作为唯一标识
|
||||
UserId: userId,
|
||||
FileType: fileType,
|
||||
FileName: file.Filename,
|
||||
FileSize: uint32(file.Size),
|
||||
FileContent: buf.Bytes(),
|
||||
}
|
||||
|
||||
if _, err = dao.File_Insert(data); err != nil {
|
||||
logrus.Errorf("dao.File_Insert failed,err:%v", err)
|
||||
reply.Status = http.StatusInternalServerError
|
||||
reply.Message = "文件上传保存失败"
|
||||
return
|
||||
}
|
||||
|
||||
reply.Data = &UploadReply{FileId: uuid}
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
package help
|
||||
|
||||
import (
|
||||
"mini_server/internal/dao"
|
||||
"time"
|
||||
|
||||
"github.com/patrickmn/go-cache"
|
||||
)
|
||||
|
||||
// 添加文件缓存功能,将文件数据保存到内存中,减少与数据库的交互,提高性能。
|
||||
var fileCache *cache.Cache
|
||||
|
||||
func init() {
|
||||
fileCache = cache.New(time.Hour, time.Minute*30) // 设置超时时间和清理时间
|
||||
}
|
||||
|
||||
func GetFileCache(file_uuid string) (*dao.File, bool) {
|
||||
if v, found := fileCache.Get(file_uuid); found {
|
||||
return v.(*dao.File), true
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
func SetFileCache(file_uuid string, data *dao.File) {
|
||||
fileCache.Set(file_uuid, data, cache.DefaultExpiration)
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
package help
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
"time"
|
||||
|
||||
"github.com/sqids/sqids-go"
|
||||
)
|
||||
|
||||
var sqlids_sqlids *sqids.Sqids
|
||||
|
||||
func init() {
|
||||
// 设置随机数种子
|
||||
rand.NewSource(time.Now().UnixNano())
|
||||
|
||||
sqlids_sqlids, _ = sqids.New()
|
||||
}
|
||||
|
||||
// 保证每秒,id唯一。同一秒内,由随机数区分,可能出现重复。
|
||||
// 注: 此微信用户名,只是展示名称,不能作为用户唯一标识使用,后期用户也可以修改。所有并没有严格唯一性要求,只要不容易重复即可。
|
||||
func GetUniqueIdEachSecond() string {
|
||||
// 生成一个0到1000之间的随机数
|
||||
randomNum := rand.Intn(1001)
|
||||
// 获取当前时间戳,精度秒即可。
|
||||
ts := time.Now().Unix()
|
||||
// 根据整数数组,生成唯一的短id
|
||||
id, _ := sqlids_sqlids.Encode([]uint64{uint64(ts), uint64(randomNum)})
|
||||
return id
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
package help
|
||||
|
||||
import (
|
||||
"mini_server/internal/config"
|
||||
"mini_server/internal/middleware/jwt"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
func GetUserId(c *gin.Context) (userId int32, ok bool) {
|
||||
defer func() {
|
||||
if !ok && config.UseDefaultUserId {
|
||||
userId = config.DefaultUserId
|
||||
ok = true
|
||||
}
|
||||
}()
|
||||
|
||||
v, ok := c.Get("user")
|
||||
logrus.Tracef("GetUserInfo, path:%v,method:%v,user v:%#v", c.Request.URL.Path, c.Request.Method, v)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
cliams, ok := v.(*jwt.Claims)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
if cliams.ID == int32(0) {
|
||||
return
|
||||
}
|
||||
userId = cliams.ID
|
||||
ok = true
|
||||
return
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
package httpreply
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
const (
|
||||
Code_OK = 200
|
||||
Code_Err = -1
|
||||
)
|
||||
|
||||
type ReplyData struct {
|
||||
Status int `json:"status"` // 状态码 200代表成功
|
||||
Message string `json:"message"` // 消息
|
||||
Data any `json:"data"` // 实体数据
|
||||
}
|
||||
|
||||
func NewDefaultReplyData() *ReplyData { return &ReplyData{Status: 200, Message: "", Data: nil} }
|
||||
func NewReplyData(status int, message string, data any) *ReplyData {
|
||||
return &ReplyData{Status: status, Message: message, Data: data}
|
||||
}
|
||||
|
||||
func Reply(c *gin.Context, data *ReplyData) {
|
||||
c.JSON(http.StatusOK, data)
|
||||
}
|
|
@ -0,0 +1,160 @@
|
|||
package post
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"mini_server/internal/dao"
|
||||
"mini_server/internal/server/help"
|
||||
"mini_server/internal/server/httpreply"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// 帖子评论处理逻辑
|
||||
|
||||
type UploadCommentRequest struct {
|
||||
Content string `json:"content" bingding:"min=1"`
|
||||
}
|
||||
|
||||
// 发布帖子
|
||||
func UploadComment(c *gin.Context) {
|
||||
reply := httpreply.NewDefaultReplyData()
|
||||
defer httpreply.Reply(c, reply)
|
||||
|
||||
userId, ok := help.GetUserId(c)
|
||||
if !ok {
|
||||
reply.Status = http.StatusNotFound
|
||||
reply.Message = "无法获取用户信息"
|
||||
return
|
||||
}
|
||||
|
||||
var param QueryURI
|
||||
if err := c.ShouldBindUri(¶m); err != nil {
|
||||
reply.Status = http.StatusBadRequest
|
||||
reply.Message = fmt.Sprintf("invalid uri path,err:%v", err)
|
||||
return
|
||||
}
|
||||
|
||||
var request UploadCommentRequest
|
||||
if err := c.ShouldBindJSON(&request); err != nil {
|
||||
reply.Status = http.StatusBadRequest
|
||||
reply.Message = fmt.Sprintf("bad request, err:%v", err)
|
||||
return
|
||||
}
|
||||
|
||||
data := dao.PostComment{
|
||||
UserId: userId,
|
||||
PostId: param.PostId,
|
||||
Content: request.Content,
|
||||
}
|
||||
if _, err := dao.PostComment_Insert(&data); err != nil {
|
||||
logrus.Errorf("评论上传失败,request:%v", request)
|
||||
reply.Status = http.StatusInternalServerError
|
||||
reply.Message = "评论上传失败"
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
type QueryCommentURI struct {
|
||||
PostId uint64 `uri:"post_id" binding:"min=1"`
|
||||
}
|
||||
|
||||
type CommentInfo struct {
|
||||
CommentId uint64 `json:"comment_id"`
|
||||
Content string `json:"content"`
|
||||
Time string `json:"time"`
|
||||
UserId int32 `json:"user_id"`
|
||||
Username string `json:"username"`
|
||||
AvatarId string `json:"avatar_id"`
|
||||
}
|
||||
type QueryCommentReply struct {
|
||||
CommentList []*CommentInfo `json:"comment_list"`
|
||||
}
|
||||
|
||||
// 查询帖子所有评论
|
||||
func QueryComment(c *gin.Context) {
|
||||
reply := httpreply.NewDefaultReplyData()
|
||||
defer httpreply.Reply(c, reply)
|
||||
|
||||
var param QueryCommentURI
|
||||
if err := c.ShouldBindUri(¶m); err != nil {
|
||||
reply.Status = http.StatusBadRequest
|
||||
reply.Message = fmt.Sprintf("invalid uri path,err:%v", err)
|
||||
return
|
||||
}
|
||||
|
||||
list, err := dao.PostComment_QueryListByPostId(param.PostId)
|
||||
if err != nil {
|
||||
logrus.Errorf("查询评论列表失败,post_id:%v", param.PostId)
|
||||
reply.Status = http.StatusInternalServerError
|
||||
reply.Message = "查询评论列表失败"
|
||||
return
|
||||
}
|
||||
mapUserIdExists := make(map[int32]bool)
|
||||
listUserId := make([]int32, 0)
|
||||
commentList := make([]*CommentInfo, len(list))
|
||||
for i, data := range list {
|
||||
user_id := data.UserId
|
||||
commentList[i] = &CommentInfo{
|
||||
CommentId: data.ID,
|
||||
Content: data.Content,
|
||||
Time: data.CreatedAt.Format(time.DateTime),
|
||||
UserId: data.UserId,
|
||||
}
|
||||
if !mapUserIdExists[user_id] {
|
||||
listUserId = append(listUserId, user_id)
|
||||
}
|
||||
}
|
||||
|
||||
if len(listUserId) > 0 {
|
||||
// 批量查询评论用户的头像和名称
|
||||
mapBaseInfo, err := dao.User_Query_List_BaseInfo(listUserId)
|
||||
if err != nil {
|
||||
logrus.Errorf("查询评论用户基本信息失败,listUserId:%v,err:%v", listUserId, err)
|
||||
reply.Status = http.StatusInternalServerError
|
||||
reply.Message = "查询评论用户基本信息失败"
|
||||
return
|
||||
}
|
||||
for i, data := range list {
|
||||
user_id := data.UserId
|
||||
commentList[i].Username = mapBaseInfo[user_id].Username
|
||||
commentList[i].AvatarId = mapBaseInfo[user_id].AvatarId
|
||||
}
|
||||
}
|
||||
|
||||
reply.Data = QueryCommentReply{CommentList: commentList}
|
||||
}
|
||||
|
||||
type DeleteCommentURI struct {
|
||||
PostId uint64 `uri:"post_id" binding:"min=1"`
|
||||
CommentId uint64 `uri:"comment_id" binding:"min=1"`
|
||||
}
|
||||
|
||||
// 删除评论
|
||||
func DeleteComment(c *gin.Context) {
|
||||
reply := httpreply.NewDefaultReplyData()
|
||||
defer httpreply.Reply(c, reply)
|
||||
|
||||
userId, ok := help.GetUserId(c)
|
||||
if !ok {
|
||||
reply.Status = http.StatusNotFound
|
||||
reply.Message = "无法获取用户信息"
|
||||
return
|
||||
}
|
||||
|
||||
var param DeleteCommentURI
|
||||
if err := c.ShouldBindUri(¶m); err != nil {
|
||||
reply.Status = http.StatusBadRequest
|
||||
reply.Message = fmt.Sprintf("invalid uri path,err:%v", err)
|
||||
return
|
||||
}
|
||||
|
||||
if err := dao.PostComment_Delete(param.CommentId); err != nil {
|
||||
logrus.Errorf("删除评论失败,userId:%d,param:%v,err:%v", userId, param, err)
|
||||
reply.Status = http.StatusInternalServerError
|
||||
reply.Message = "删除评论失败"
|
||||
return
|
||||
}
|
||||
}
|
|
@ -0,0 +1,113 @@
|
|||
package post
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"mini_server/internal/dao"
|
||||
"mini_server/internal/server/help"
|
||||
"mini_server/internal/server/httpreply"
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/sirupsen/logrus"
|
||||
"gorm.io/datatypes"
|
||||
)
|
||||
|
||||
// 草稿处理逻辑。
|
||||
|
||||
type DraftInfo struct {
|
||||
UserId int32 `json:"user_id"` // 发帖者
|
||||
Title string `json:"title"`
|
||||
Content string `json:"content"`
|
||||
RoleIds datatypes.JSON `json:"role_ids"` // 帖子关联的角色id列表
|
||||
}
|
||||
|
||||
type QueryDraftReply struct {
|
||||
DraftInfo *DraftInfo `json:"draft_info"`
|
||||
}
|
||||
|
||||
// 上传草稿
|
||||
func SaveDraft(c *gin.Context) {
|
||||
reply := httpreply.NewDefaultReplyData()
|
||||
defer httpreply.Reply(c, reply)
|
||||
|
||||
userId, ok := help.GetUserId(c)
|
||||
if !ok {
|
||||
reply.Status = http.StatusNotFound
|
||||
reply.Message = "无法获取用户信息"
|
||||
return
|
||||
}
|
||||
|
||||
var request UploadRequest
|
||||
if err := c.ShouldBindJSON(&request); err != nil {
|
||||
reply.Status = http.StatusBadRequest
|
||||
reply.Message = fmt.Sprintf("bad request, err:%v", err)
|
||||
return
|
||||
}
|
||||
|
||||
// 将数据写入数据库中
|
||||
data := dao.Draft{
|
||||
UserId: userId,
|
||||
Title: request.Title,
|
||||
Content: request.Content,
|
||||
RoleIds: request.RoleIds,
|
||||
}
|
||||
|
||||
if err := dao.Draft_Save(&data); err != nil {
|
||||
logrus.Errorf("保存草稿失败,userId:%d,err:%v", userId, err)
|
||||
reply.Status = http.StatusInternalServerError
|
||||
reply.Message = "保存草稿失败"
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// 删除草稿
|
||||
func DeleteDraft(c *gin.Context) {
|
||||
reply := httpreply.NewDefaultReplyData()
|
||||
defer httpreply.Reply(c, reply)
|
||||
|
||||
userId, ok := help.GetUserId(c)
|
||||
if !ok {
|
||||
reply.Status = http.StatusNotFound
|
||||
reply.Message = "无法获取用户信息"
|
||||
return
|
||||
}
|
||||
|
||||
if err := dao.Draft_Delete(userId); err != nil {
|
||||
logrus.Errorf("删除草稿失败,userId:%d,err:%v", userId, err)
|
||||
reply.Status = http.StatusInternalServerError
|
||||
reply.Message = "删除草稿失败"
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// 查询草稿
|
||||
func QueryDraft(c *gin.Context) {
|
||||
reply := httpreply.NewDefaultReplyData()
|
||||
defer httpreply.Reply(c, reply)
|
||||
|
||||
userId, ok := help.GetUserId(c)
|
||||
if !ok {
|
||||
reply.Status = http.StatusNotFound
|
||||
reply.Message = "无法获取用户信息"
|
||||
return
|
||||
}
|
||||
|
||||
data, err := dao.Draft_Query(userId)
|
||||
if err != nil {
|
||||
logrus.Errorf("查询草稿失败,userId:%d,err:%v", userId, err)
|
||||
reply.Status = http.StatusInternalServerError
|
||||
reply.Message = "查询草稿失败"
|
||||
return
|
||||
}
|
||||
|
||||
queryDraftReply := QueryDraftReply{DraftInfo: nil}
|
||||
if data != nil {
|
||||
queryDraftReply.DraftInfo = &DraftInfo{
|
||||
UserId: data.UserId,
|
||||
Title: data.Title,
|
||||
Content: data.Content,
|
||||
RoleIds: data.RoleIds,
|
||||
}
|
||||
}
|
||||
reply.Data = queryDraftReply
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
package post
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"mini_server/internal/dao"
|
||||
"mini_server/internal/server/help"
|
||||
"mini_server/internal/server/httpreply"
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
func Like(c *gin.Context) {
|
||||
reply := httpreply.NewDefaultReplyData()
|
||||
defer httpreply.Reply(c, reply)
|
||||
|
||||
userId, ok := help.GetUserId(c)
|
||||
if !ok {
|
||||
reply.Status = http.StatusNotFound
|
||||
reply.Message = "无法获取用户信息"
|
||||
return
|
||||
}
|
||||
|
||||
var param QueryURI
|
||||
if err := c.ShouldBindUri(¶m); err != nil {
|
||||
reply.Status = http.StatusBadRequest
|
||||
reply.Message = fmt.Sprintf("invalid uri path,err:%v", err)
|
||||
return
|
||||
}
|
||||
|
||||
data := dao.PostLike{UserId: userId, PostId: param.PostId}
|
||||
if err := dao.PostLike_Like(&data); err != nil {
|
||||
logrus.Errorf("贴子点赞插入数据库异常,userId:%d,postId:%d,err:%v", userId, param.PostId, err)
|
||||
reply.Status = http.StatusInternalServerError
|
||||
reply.Message = "贴子点赞异常"
|
||||
return
|
||||
}
|
||||
}
|
|
@ -0,0 +1,97 @@
|
|||
package post
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"mini_server/internal/dao"
|
||||
"mini_server/internal/server/help"
|
||||
"mini_server/internal/server/httpreply"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// 帖子列表查询接口。支持按照时间查询,以及角色查询。
|
||||
type ListParam struct {
|
||||
StartTime time.Time `form:"start_time" binding:"required" time_format:"2006-01-02 15:04:05"`
|
||||
StopTime time.Time `form:"stop_time" binding:"required,gtfield=StartTime" time_format:"2006-01-02 15:04:05"`
|
||||
RoleId *int32 `form:"role_id" binding:"min=0"`
|
||||
}
|
||||
|
||||
type ListReply struct {
|
||||
PostList []*PostInfo `json:"post_list"`
|
||||
}
|
||||
|
||||
func List(c *gin.Context) {
|
||||
reply := httpreply.NewDefaultReplyData()
|
||||
defer httpreply.Reply(c, reply)
|
||||
|
||||
userId, ok := help.GetUserId(c)
|
||||
if !ok {
|
||||
reply.Status = http.StatusNotFound
|
||||
reply.Message = "无法获取用户信息"
|
||||
return
|
||||
}
|
||||
|
||||
var param ListParam
|
||||
if err := c.ShouldBindQuery(¶m); err != nil {
|
||||
reply.Status = http.StatusBadRequest
|
||||
reply.Message = fmt.Sprintf("invalid query args,err:%v", err)
|
||||
return
|
||||
}
|
||||
|
||||
list, err := dao.Post_Page_Query(param.StartTime, param.StopTime, *param.RoleId)
|
||||
if err != nil {
|
||||
logrus.Errorf("帖子列表查询失败,param:%v,error:%v", param, err)
|
||||
reply.Status = http.StatusInternalServerError
|
||||
reply.Message = "帖子列表查询失败"
|
||||
return
|
||||
}
|
||||
|
||||
// 批量查询帖子点赞信息
|
||||
postIds := make([]uint64, len(list))
|
||||
for i, data := range list {
|
||||
postIds[i] = uint64(data.ID)
|
||||
}
|
||||
userIds := make([]int32, len(list))
|
||||
for i, data := range list {
|
||||
userIds[i] = data.UserId
|
||||
}
|
||||
like_count_map, err := dao.PostLike_Count_Batch(postIds)
|
||||
if err != nil {
|
||||
logrus.Errorf("帖子列表点赞数查询失败,userId:%d,postIds:%v,err:%v", userId, postIds, err)
|
||||
reply.Status = http.StatusInternalServerError
|
||||
reply.Message = "帖子列表点赞数查询失败"
|
||||
return
|
||||
}
|
||||
|
||||
// 批量查询用户是否点赞
|
||||
user_like_map, err := dao.PostLike_Exists_Batch(userId, postIds)
|
||||
if err != nil {
|
||||
logrus.Errorf("帖子列表用户点赞信息查询失败,userId:%d,postId:%v,err:%v", userId, postIds, err)
|
||||
reply.Status = http.StatusInternalServerError
|
||||
reply.Message = "帖子列表用户点赞信息查询失败"
|
||||
return
|
||||
}
|
||||
|
||||
// 批量查询用户名和用户头像
|
||||
user_info_map, err := dao.User_Query_List(userIds)
|
||||
if err != nil {
|
||||
logrus.Errorf("批量查询帖子发布者信息失败,postIds:%v,userIds:%v,err:%v", postIds, userId, err)
|
||||
reply.Status = http.StatusInternalServerError
|
||||
reply.Message = "批量查询帖子发布者信息失败"
|
||||
return
|
||||
}
|
||||
|
||||
postList := make([]*PostInfo, len(list))
|
||||
for i, data := range list {
|
||||
var info PostInfo
|
||||
current_post_id := uint64(data.ID)
|
||||
current_user_id := data.UserId
|
||||
copy_from_mysql(data, like_count_map[current_post_id], user_like_map[current_post_id], user_info_map[current_user_id], &info)
|
||||
postList[i] = &info
|
||||
}
|
||||
|
||||
reply.Data = &ListReply{PostList: postList}
|
||||
}
|
|
@ -0,0 +1,109 @@
|
|||
package post
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"mini_server/internal/dao"
|
||||
"mini_server/internal/server/help"
|
||||
"mini_server/internal/server/httpreply"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/sirupsen/logrus"
|
||||
"gorm.io/datatypes"
|
||||
)
|
||||
|
||||
type PostInfo struct {
|
||||
PostId uint64 `json:"post_id"`
|
||||
UserId int32 `json:"user_id"` // 发帖者
|
||||
UserAvatarId string `json:"user_avatar_id"` // 用户头像
|
||||
Username string `json:"username"` // 用户名称
|
||||
CreatedAt string `json:"created_at"` // 发帖时间
|
||||
Title string `json:"title"`
|
||||
Content string `json:"content"`
|
||||
LikeCount int `json:"like_count"` // 点赞数
|
||||
IsLike bool `json:"is_like"` // 当前用户是否点赞了
|
||||
RoleIds datatypes.JSON `json:"role_ids"` // 帖子关联的角色id列表
|
||||
}
|
||||
|
||||
type QueryURI struct {
|
||||
PostId uint64 `uri:"post_id" binding:"min=1"`
|
||||
}
|
||||
|
||||
type QueryReply struct {
|
||||
PostInfo *PostInfo `json:"post_info"`
|
||||
}
|
||||
|
||||
// 帖子查询接口
|
||||
|
||||
func Query(c *gin.Context) {
|
||||
reply := httpreply.NewDefaultReplyData()
|
||||
defer httpreply.Reply(c, reply)
|
||||
|
||||
userId, ok := help.GetUserId(c)
|
||||
if !ok {
|
||||
reply.Status = http.StatusNotFound
|
||||
reply.Message = "无法获取用户信息"
|
||||
return
|
||||
}
|
||||
|
||||
var param QueryURI
|
||||
if err := c.ShouldBindUri(¶m); err != nil {
|
||||
reply.Status = http.StatusBadRequest
|
||||
reply.Message = fmt.Sprintf("invalid uri path,err:%v", err)
|
||||
return
|
||||
}
|
||||
|
||||
data, err := dao.Post_Query(param.PostId)
|
||||
if err != nil {
|
||||
logrus.Errorf("帖子数据库查询失败,post_id:%d,err:%v", param.PostId, err)
|
||||
reply.Status = http.StatusInternalServerError
|
||||
reply.Message = "帖子查询异常"
|
||||
return
|
||||
}
|
||||
|
||||
// 从数据库中查询贴子的点赞情况。
|
||||
count, err := dao.PostLike_Count(param.PostId)
|
||||
if err != nil {
|
||||
logrus.Errorf("贴子点赞数查询失败,post_id:%d,err:%v", param.PostId, err)
|
||||
reply.Status = http.StatusInternalServerError
|
||||
reply.Message = "贴子点赞数查询异常"
|
||||
return
|
||||
}
|
||||
/// 查询当前用户,是否点赞了。
|
||||
is_like, err := dao.PostLike_Exists(userId, param.PostId)
|
||||
if err != nil {
|
||||
logrus.Errorf("贴子用户是否点赞查询失败,user_id:%d,post_id:%d,err:%v", userId, param.PostId, err)
|
||||
reply.Status = http.StatusInternalServerError
|
||||
reply.Message = "贴子用户是否点赞查询失败"
|
||||
return
|
||||
}
|
||||
|
||||
// 查询用户名和头像id
|
||||
user_info, err := dao.User_Query(data.UserId)
|
||||
if err != nil {
|
||||
logrus.Errorf("查询帖子发布者信息失败,user_id:%d,post_id:%d,err:%v", userId, param.PostId, err)
|
||||
reply.Status = http.StatusInternalServerError
|
||||
reply.Message = "查询帖子发布者信息失败"
|
||||
return
|
||||
}
|
||||
|
||||
var info PostInfo
|
||||
copy_from_mysql(data, count, is_like, user_info, &info)
|
||||
reply.Data = &QueryReply{PostInfo: &info}
|
||||
}
|
||||
|
||||
func copy_from_mysql(data *dao.Post, like_count int64, is_like bool, user_info *dao.User, detail *PostInfo) {
|
||||
detail.PostId = uint64(data.ID)
|
||||
detail.UserId = data.UserId
|
||||
detail.Title = data.Title
|
||||
detail.Content = data.Content
|
||||
detail.RoleIds = data.RoleIds
|
||||
detail.LikeCount = int(like_count)
|
||||
detail.IsLike = is_like
|
||||
detail.CreatedAt = data.CreatedAt.Format(time.DateTime)
|
||||
if user_info != nil {
|
||||
detail.UserAvatarId = user_info.AvatarId
|
||||
detail.Username = user_info.Username
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
package post
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"mini_server/internal/dao"
|
||||
"mini_server/internal/server/help"
|
||||
"mini_server/internal/server/httpreply"
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
func UnLike(c *gin.Context) {
|
||||
reply := httpreply.NewDefaultReplyData()
|
||||
defer httpreply.Reply(c, reply)
|
||||
|
||||
userId, ok := help.GetUserId(c)
|
||||
if !ok {
|
||||
reply.Status = http.StatusNotFound
|
||||
reply.Message = "无法获取用户信息"
|
||||
return
|
||||
}
|
||||
|
||||
var param QueryURI
|
||||
if err := c.ShouldBindUri(¶m); err != nil {
|
||||
reply.Status = http.StatusBadRequest
|
||||
reply.Message = fmt.Sprintf("invalid uri path,err:%v", err)
|
||||
return
|
||||
}
|
||||
|
||||
if err := dao.PostLike_UnLike(userId, param.PostId); err != nil {
|
||||
logrus.Errorf("贴子取消点赞删除数据库异常,userId:%d,postId:%d,err:%v", userId, param.PostId, err)
|
||||
reply.Status = http.StatusInternalServerError
|
||||
reply.Message = "贴子取消点赞异常"
|
||||
return
|
||||
}
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
package post
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"mini_server/internal/dao"
|
||||
"mini_server/internal/server/help"
|
||||
"mini_server/internal/server/httpreply"
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/sirupsen/logrus"
|
||||
"gorm.io/datatypes"
|
||||
)
|
||||
|
||||
// 发布帖子
|
||||
|
||||
type UploadRequest struct {
|
||||
Title string `json:"title" binding:"min=1"`
|
||||
Content string `json:"content" binding:"min=1"`
|
||||
RoleIds datatypes.JSON `json:"role_ids"` // 关联角色ID
|
||||
}
|
||||
|
||||
type UploadReply struct {
|
||||
PostId uint64 `json:"post_id"` // 文件ID
|
||||
}
|
||||
|
||||
// 帖子上传接口
|
||||
func Upload(c *gin.Context) {
|
||||
reply := httpreply.NewDefaultReplyData()
|
||||
defer httpreply.Reply(c, reply)
|
||||
|
||||
userId, ok := help.GetUserId(c)
|
||||
if !ok {
|
||||
reply.Status = http.StatusNotFound
|
||||
reply.Message = "无法获取用户信息"
|
||||
return
|
||||
}
|
||||
|
||||
var request UploadRequest
|
||||
if err := c.ShouldBindJSON(&request); err != nil {
|
||||
reply.Status = http.StatusBadRequest
|
||||
reply.Message = fmt.Sprintf("bad request, err:%v", err)
|
||||
return
|
||||
}
|
||||
|
||||
// 将数据写入数据库中
|
||||
data := dao.Post{
|
||||
UserId: userId,
|
||||
Title: request.Title,
|
||||
Content: request.Content,
|
||||
RoleIds: request.RoleIds,
|
||||
}
|
||||
|
||||
id, err := dao.Post_Insert(&data)
|
||||
if err != nil {
|
||||
logrus.Errorf("上传帖子到数据库中失败,err:%v", err)
|
||||
reply.Status = http.StatusInternalServerError
|
||||
reply.Message = "上传帖子数据失败"
|
||||
return
|
||||
}
|
||||
|
||||
// 帖子发布成功之后,自动删除草稿
|
||||
if err := dao.Draft_Delete(userId); err != nil {
|
||||
logrus.Errorf("删除草稿失败,userId:%d,err:%v", userId, err)
|
||||
}
|
||||
|
||||
reply.Data = &UploadReply{PostId: id}
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
package role
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"mini_server/internal/dao"
|
||||
"mini_server/internal/server/httpreply"
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// 角色添加
|
||||
|
||||
type CreateRequest struct {
|
||||
VoiceId int `json:"voice_id" bingding:"gt=0"`
|
||||
RoleName string `json:"role_name"`
|
||||
WakeupWords string `json:"wakeup_words" binding:"min=1"`
|
||||
WorldScenario string `json:"world_scenario" binding:"min=1"`
|
||||
Description string `json:"description" binding:"min=1"`
|
||||
Emojis string `json:"emojis"` // json格式
|
||||
Dialogues string `json:"dialogues" binding:"min=1"`
|
||||
AvatarId string `json:"avatar_id" binding:"min=0"` /// 头像图片路径
|
||||
BackgroundIds string `json:"background_ids" binding:"min=0"` // 背景图列表,以逗号分隔
|
||||
}
|
||||
|
||||
type CreateReply struct {
|
||||
RoleId int32 `json:"role_id"` // 角色ID
|
||||
}
|
||||
|
||||
// 添加角色
|
||||
func Create(c *gin.Context) {
|
||||
reply := httpreply.NewDefaultReplyData()
|
||||
defer httpreply.Reply(c, reply)
|
||||
|
||||
var request CreateRequest
|
||||
if err := c.ShouldBindJSON(&request); err != nil {
|
||||
reply.Status = http.StatusBadRequest
|
||||
reply.Message = fmt.Sprintf("invalid json data,err:%v", err)
|
||||
return
|
||||
}
|
||||
|
||||
// 将数据写入数据库中
|
||||
data := dao.Character{
|
||||
VoiceId: request.VoiceId,
|
||||
Name: request.RoleName,
|
||||
WakeupWords: request.WakeupWords,
|
||||
WorldScenario: request.WorldScenario,
|
||||
Description: request.Description,
|
||||
Emojis: request.Emojis,
|
||||
Dialogues: request.Dialogues,
|
||||
AvatarId: request.AvatarId,
|
||||
BackgroundIds: request.BackgroundIds,
|
||||
}
|
||||
|
||||
if data.Emojis == "" {
|
||||
data.Emojis = "{}"
|
||||
}
|
||||
roleId, err := dao.Character_Insert(&data)
|
||||
if err != nil {
|
||||
logrus.Errorf("dao.Character_Insert failed, err:%v", err)
|
||||
reply.Status = http.StatusInternalServerError
|
||||
reply.Message = "添加角色失败"
|
||||
return
|
||||
}
|
||||
reply.Data = &CreateReply{RoleId: roleId}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
package role
|
||||
|
||||
/*
|
||||
type DeleteURI struct {
|
||||
RoleId int32 `uri:"role_id" binding:"gt=0"`
|
||||
}
|
||||
|
||||
// 角色删除接口
|
||||
|
||||
func Delete(c *gin.Context) {
|
||||
reply := httpreply.NewDefaultReplyData()
|
||||
defer httpreply.Reply(c, reply)
|
||||
|
||||
var param DeleteURI
|
||||
if err := c.ShouldBindUri(¶m); err != nil {
|
||||
reply.Status = http.StatusBadRequest
|
||||
reply.Message = fmt.Sprintf("invalid uri,err:%v", err)
|
||||
return
|
||||
}
|
||||
|
||||
if err := dao.Character_Delete(param.RoleId); err != nil {
|
||||
reply.Status = http.StatusInternalServerError
|
||||
reply.Message = "角色删除失败"
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
|
@ -0,0 +1,67 @@
|
|||
package role
|
||||
|
||||
import "mini_server/internal/dao"
|
||||
|
||||
type RoleInfo struct {
|
||||
RoleId uint64 `json:"role_id"`
|
||||
VoiceId int `json:"voice_id"`
|
||||
RoleName string `json:"role_name"`
|
||||
WakeupWords string `json:"wakeup_words"`
|
||||
WorldScenario string `json:"world_scenario"`
|
||||
Description string `json:"description"`
|
||||
Emojis string `json:"emojis"`
|
||||
Dialogues string `json:"dialogues"`
|
||||
AvatarId string `json:"avatar_id"` /// 头像图片路径
|
||||
BackgroundIds string `json:"background_ids"` // 背景图列表,以逗号分隔
|
||||
}
|
||||
|
||||
/*
|
||||
type QueryURI struct {
|
||||
RoleId int32 `uri:"role_id" binding:"gt=0"`
|
||||
}
|
||||
type QueryReply struct {
|
||||
RoleInfo *RoleInfo `json:"role_info"`
|
||||
}
|
||||
|
||||
// 单个角色查询接口
|
||||
|
||||
func Query(c *gin.Context) {
|
||||
reply := httpreply.NewDefaultReplyData()
|
||||
defer httpreply.Reply(c, reply)
|
||||
|
||||
var param QueryURI
|
||||
if err := c.ShouldBindUri(¶m); err != nil {
|
||||
reply.Status = http.StatusBadRequest
|
||||
reply.Message = fmt.Sprintf("invalid uri, err:%v", err)
|
||||
return
|
||||
}
|
||||
|
||||
data, err := dao.Character_Query(param.RoleId)
|
||||
if err != nil {
|
||||
logrus.Errorf("dao.Character_Query return err:%v", err)
|
||||
reply.Status = http.StatusInternalServerError
|
||||
reply.Message = "查询角色信息失败"
|
||||
return
|
||||
}
|
||||
var queryReply QueryReply
|
||||
if data != nil {
|
||||
var detail RoleInfo
|
||||
Copy_mysql_data(data, &detail)
|
||||
queryReply.RoleInfo = &detail
|
||||
}
|
||||
reply.Data = &queryReply
|
||||
}
|
||||
*/
|
||||
|
||||
func Copy_mysql_data(data *dao.Character, detail *RoleInfo) {
|
||||
detail.BackgroundIds = data.BackgroundIds
|
||||
detail.AvatarId = data.AvatarId
|
||||
detail.RoleId = uint64(data.ID)
|
||||
detail.VoiceId = data.VoiceId
|
||||
detail.RoleName = data.Name
|
||||
detail.WakeupWords = data.WakeupWords
|
||||
detail.WorldScenario = data.WorldScenario
|
||||
detail.Description = data.Description
|
||||
detail.Emojis = data.Emojis
|
||||
detail.Dialogues = data.Dialogues
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
package role
|
||||
|
||||
import (
|
||||
"mini_server/internal/dao"
|
||||
"mini_server/internal/server/httpreply"
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// 角色列表查询接口,查询全部
|
||||
func QueryAllRole(c *gin.Context) {
|
||||
reply := httpreply.NewDefaultReplyData()
|
||||
defer httpreply.Reply(c, reply)
|
||||
|
||||
list, err := dao.Character_QueryAllCharacter()
|
||||
if err != nil {
|
||||
logrus.Errorf("角色列表查询失败,err:%v", err)
|
||||
reply.Status = http.StatusInternalServerError
|
||||
reply.Message = "角色列表查询失败"
|
||||
return
|
||||
}
|
||||
|
||||
roleList := make([]*RoleInfo, len(list))
|
||||
for i, data := range list {
|
||||
var detail RoleInfo
|
||||
Copy_mysql_data(data, &detail)
|
||||
roleList[i] = &detail
|
||||
}
|
||||
reply.Data = roleList
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
package role
|
||||
|
||||
import (
|
||||
"mini_server/internal/dao"
|
||||
"mini_server/internal/server/help"
|
||||
"mini_server/internal/server/httpreply"
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
type QueryListReply struct {
|
||||
RoleList []*RoleInfo `json:"role_list"`
|
||||
}
|
||||
|
||||
// 角色列表查询接口,根据用户ID查询
|
||||
func QueryList(c *gin.Context) {
|
||||
reply := httpreply.NewDefaultReplyData()
|
||||
defer httpreply.Reply(c, reply)
|
||||
|
||||
userId, ok := help.GetUserId(c)
|
||||
if !ok {
|
||||
reply.Status = http.StatusNotFound
|
||||
reply.Message = "无法获取用户信息"
|
||||
return
|
||||
}
|
||||
|
||||
// 1. 需要去表user_character中查询关联的角色ID
|
||||
list, err := dao.UserCharacter_QueryList(userId)
|
||||
if err != nil {
|
||||
logrus.Errorf("查询用户关联角色列表失败,err:%v", err)
|
||||
reply.Status = http.StatusInternalServerError
|
||||
reply.Message = "查询用户关联角色列表失败"
|
||||
return
|
||||
}
|
||||
|
||||
// 2. 根据角色ID列表,查询角色详情
|
||||
roleIds := make([]int32, len(list))
|
||||
for i, data := range list {
|
||||
roleIds[i] = data.CharacterId
|
||||
}
|
||||
|
||||
roleList, err := dao.Character_QueryList(roleIds)
|
||||
if err != nil {
|
||||
logrus.Errorf("查询角色列表失败,userId:%v,roleIds:%v,err:%v", userId, roleIds, err)
|
||||
reply.Status = http.StatusInternalServerError
|
||||
reply.Message = "查询角色列表失败"
|
||||
return
|
||||
}
|
||||
|
||||
replyroleList := make([]*RoleInfo, len(list))
|
||||
for i, data := range roleList {
|
||||
var detail RoleInfo
|
||||
Copy_mysql_data(data, &detail)
|
||||
replyroleList[i] = &detail
|
||||
}
|
||||
reply.Data = roleList
|
||||
}
|
|
@ -0,0 +1,129 @@
|
|||
package server
|
||||
|
||||
import (
|
||||
"mini_server/internal/config"
|
||||
"mini_server/internal/dao"
|
||||
"mini_server/internal/logger"
|
||||
"mini_server/internal/middleware/cors"
|
||||
"mini_server/internal/middleware/jwt"
|
||||
"mini_server/internal/middleware/tls"
|
||||
"mini_server/internal/server/bluetooth"
|
||||
chatrecord "mini_server/internal/server/chat_record"
|
||||
"mini_server/internal/server/file"
|
||||
"mini_server/internal/server/post"
|
||||
"mini_server/internal/server/role"
|
||||
"mini_server/internal/server/user"
|
||||
"mini_server/internal/server/wx"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
type Server struct {
|
||||
e *gin.Engine
|
||||
address string
|
||||
}
|
||||
|
||||
func NewServer(address, dsn string) (*Server, error) {
|
||||
err := dao.InitDefaultService(dsn)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
gin.DefaultWriter = logger.GinLogger
|
||||
e := gin.Default()
|
||||
srv := &Server{e: e, address: address}
|
||||
srv.init_v1_handler()
|
||||
return srv, nil
|
||||
}
|
||||
|
||||
func (s *Server) GetGinEngine() *gin.Engine { return s.e }
|
||||
|
||||
func (s *Server) Run() error {
|
||||
if config.TlsEnable { // 启用tls
|
||||
return s.e.RunTLS(s.address, config.TlsFilePem, config.TlsFileKey)
|
||||
}
|
||||
return s.e.Run(s.address)
|
||||
}
|
||||
|
||||
func (s *Server) init_v1_handler() {
|
||||
|
||||
if config.TlsEnable { // 是否开启https
|
||||
logrus.Info("use TLS")
|
||||
s.e.Use(tls.TlsHandler())
|
||||
}
|
||||
|
||||
api := s.e.Group("api")
|
||||
|
||||
if config.JwtEnable { // 是否开启jwt校验
|
||||
logrus.Info("use JWT")
|
||||
api.Use(jwt.AuthMiddleware())
|
||||
}
|
||||
|
||||
if config.CorsEnable { // 是否开启跨域处理
|
||||
logrus.Info("use CORS")
|
||||
api.Use(cors.CorsMiddleware())
|
||||
}
|
||||
|
||||
users := api.Group("users")
|
||||
{
|
||||
// users.GET("/:user_id", user.Query) // 获取用户信息。小程序未使用。
|
||||
users.PUT("/username", user.ChangeUsername) // 更新用户名称
|
||||
users.PUT("/avatar_id", user.ChangeAvatarId) // 更新用户头像
|
||||
users.POST("/wx/login", wx.WxLogin) // 微信登录
|
||||
}
|
||||
|
||||
// 聊天相关功能
|
||||
chats := api.Group("chat_records")
|
||||
{
|
||||
chats.GET("/", chatrecord.History) // 获取单个角色历史聊天记录
|
||||
chats.GET("/all", chatrecord.HistoryAll) // 获取所有角色历史聊天记录
|
||||
chats.POST("/", chatrecord.Upload) // 发送聊天消息,进行存储
|
||||
chats.GET("/exists", chatrecord.Exists) // 判断用户与角色是否有聊天记录
|
||||
}
|
||||
|
||||
// 帖子相关接口
|
||||
posts := api.Group("post")
|
||||
{
|
||||
posts.GET("/", post.List) // 获取社区帖子列表,支持按照时间查询,支持根据角色筛选
|
||||
posts.GET("/:post_id", post.Query) // 获取帖子详情
|
||||
posts.POST("/", post.Upload) // 发布帖子
|
||||
posts.POST("/:post_id/like", post.Like) // 帖子点赞
|
||||
posts.DELETE("/:post_id/like", post.UnLike) // 帖子取消点赞
|
||||
posts.GET("/:post_id/comments/", post.QueryComment) // 获取帖子的全部评论
|
||||
posts.POST("/:post_id/comments/", post.UploadComment) // 添加一条评论
|
||||
posts.DELETE("/:post_id/comments/:comment_id", post.DeleteComment) // 删除评论
|
||||
}
|
||||
// 草稿相关接口
|
||||
drafts := api.Group("drafts")
|
||||
{
|
||||
drafts.GET("/", post.QueryDraft) // 获取草稿。目前草稿的处理逻辑是,一个用户只保存一张草稿。
|
||||
drafts.POST("/", post.SaveDraft) // 保存草稿
|
||||
drafts.DELETE("/", post.DeleteDraft) // 删除草稿
|
||||
}
|
||||
|
||||
// 图片和音频等文件相关功能。
|
||||
files := api.Group("files")
|
||||
{
|
||||
files.POST("/", file.Upload) // 文件上传
|
||||
files.DELETE("/:file_id", file.Delete) // 文件删除
|
||||
}
|
||||
s.e.GET("/api/files/:file_id", file.Download) // 文件下载 /////////// 注:为了保证图片通过<image>标签下载(未设置header)。文件相关接口不受jwt限制。
|
||||
|
||||
// 蓝牙接口
|
||||
bluetooths := api.Group("bluetooths")
|
||||
{
|
||||
bluetooths.GET("/", bluetooth.QueryAll) // 查询蓝牙接口列表
|
||||
bluetooths.POST("/", bluetooth.Create) // 增加某个蓝牙的具体信息
|
||||
bluetooths.DELETE("/", bluetooth.Delete) // 删除某个蓝牙的具体信息
|
||||
}
|
||||
|
||||
// 角色接口
|
||||
roles := api.Group("roles")
|
||||
{
|
||||
roles.GET("/all", role.QueryAllRole) // 获取所有角色
|
||||
roles.POST("/", role.Create) // 添加角色
|
||||
roles.GET("/", role.QueryList) // 获取用户绑定的角色列表
|
||||
// roles.DELETE("/:role_id", role.Delete) // 删除角色。 小程序未使用此接口。
|
||||
// roles.GET("/:role_id", role.Query) // 获取角色详情。 小程序未使用此接口。
|
||||
}
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
package user
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"mini_server/internal/dao"
|
||||
"mini_server/internal/server/help"
|
||||
"mini_server/internal/server/httpreply"
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
type ChangeAvatarIdRequest struct {
|
||||
AvatarId string `json:"avatar_id" binding:"min=1"` // 修改的头像id
|
||||
}
|
||||
|
||||
func ChangeAvatarId(c *gin.Context) {
|
||||
reply := httpreply.NewDefaultReplyData()
|
||||
defer httpreply.Reply(c, reply)
|
||||
|
||||
//解析请求参数
|
||||
var request ChangeAvatarIdRequest
|
||||
if err := c.ShouldBindJSON(&request); err != nil {
|
||||
reply.Status = http.StatusBadRequest
|
||||
reply.Message = fmt.Sprintf("invalid json data, err:%v", err)
|
||||
return
|
||||
}
|
||||
|
||||
userId, ok := help.GetUserId(c)
|
||||
if !ok {
|
||||
reply.Status = http.StatusNotFound
|
||||
reply.Message = "无法获取用户信息"
|
||||
return
|
||||
}
|
||||
|
||||
logrus.Tracef("修改用户头像,userId:%d,请求参数:%v", userId, request)
|
||||
|
||||
if err := dao.User_Change_AvatarId(userId, request.AvatarId); err != nil {
|
||||
logrus.Errorf("更新用户头像失败,userId:%d,err:%v", userId, err)
|
||||
reply.Status = http.StatusInternalServerError
|
||||
reply.Message = "更新用户头像失败"
|
||||
return
|
||||
}
|
||||
|
||||
full_lastest_userinfo(reply, userId)
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
package user
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"mini_server/internal/dao"
|
||||
"mini_server/internal/server/help"
|
||||
"mini_server/internal/server/httpreply"
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
/*
|
||||
func ChangePersona(c *gin.Context) {
|
||||
reply := httpreply.NewDefaultReplyData()
|
||||
defer httpreply.Reply(c, reply)
|
||||
|
||||
var param QueryURI
|
||||
if err := c.ShouldBindUri(¶m); err != nil {
|
||||
reply.Status = http.StatusInternalServerError
|
||||
reply.Message = fmt.Sprintf("invalid uri, err:%v", err)
|
||||
return
|
||||
}
|
||||
|
||||
persona := make(map[string]interface{})
|
||||
if err := c.ShouldBindJSON(&persona); err != nil {
|
||||
reply.Status = http.StatusInternalServerError
|
||||
reply.Message = fmt.Sprintf("invalid json,err:%v", err)
|
||||
return
|
||||
}
|
||||
|
||||
if err := dao.User_Change_Persona(param.UserId, persona); err != nil {
|
||||
logrus.Errorf("dao.User_Change_Persona失败,userId:%v,persona:%v,err:%v", param.UserId, persona, err)
|
||||
reply.Status = http.StatusInternalServerError
|
||||
reply.Message = "更新个性化信息失败"
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
type ChangeUsernameRequest struct {
|
||||
Username string `json:"username" binding:"min=1"` // 修改的用户名
|
||||
}
|
||||
|
||||
func ChangeUsername(c *gin.Context) {
|
||||
reply := httpreply.NewDefaultReplyData()
|
||||
defer httpreply.Reply(c, reply)
|
||||
|
||||
//解析请求参数
|
||||
var request ChangeUsernameRequest
|
||||
if err := c.ShouldBindJSON(&request); err != nil {
|
||||
reply.Status = http.StatusBadRequest
|
||||
reply.Message = fmt.Sprintf("invalid json data, err:%v", err)
|
||||
return
|
||||
}
|
||||
|
||||
userId, ok := help.GetUserId(c)
|
||||
if !ok {
|
||||
reply.Status = http.StatusNotFound
|
||||
reply.Message = "无法获取用户信息"
|
||||
return
|
||||
}
|
||||
|
||||
logrus.Tracef("修改用户名,userId:%d,请求参数:%v", userId, request)
|
||||
|
||||
if err := dao.User_Change_Username(userId, request.Username); err != nil {
|
||||
logrus.Errorf("更新用户名称失败,userId:%d,err:%v", userId, err)
|
||||
reply.Status = http.StatusInternalServerError
|
||||
reply.Message = "更新用户名称失败"
|
||||
return
|
||||
}
|
||||
|
||||
full_lastest_userinfo(reply, userId)
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
package user
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"mini_server/internal/dao"
|
||||
"mini_server/internal/server/httpreply"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
type UserInfo struct {
|
||||
UserId uint64 `json:"user_id"`
|
||||
AvatarId string `json:"avatar_id"`
|
||||
Username string `json:"username"`
|
||||
CreatedAt string `json:"created_at"`
|
||||
Tags string `json:"tags"`
|
||||
Persona string `json:"persona"`
|
||||
}
|
||||
|
||||
type QueryURI struct {
|
||||
UserId int32 `uri:"user_id" binding:"gt=0"`
|
||||
}
|
||||
type QueryReply struct {
|
||||
UserInfo *UserInfo `json:"user_info"`
|
||||
}
|
||||
|
||||
func Query(c *gin.Context) {
|
||||
reply := httpreply.NewDefaultReplyData()
|
||||
defer httpreply.Reply(c, reply)
|
||||
|
||||
var param QueryURI
|
||||
if err := c.ShouldBindUri(¶m); err != nil {
|
||||
reply.Status = http.StatusInternalServerError
|
||||
reply.Message = fmt.Sprintf("invalid uri, err:%v", err)
|
||||
return
|
||||
}
|
||||
|
||||
full_lastest_userinfo(reply, param.UserId)
|
||||
}
|
||||
|
||||
func Copy_User_Info(data *dao.User, info *UserInfo) {
|
||||
info.UserId = uint64(data.ID)
|
||||
info.AvatarId = data.AvatarId
|
||||
info.Username = data.Username
|
||||
info.CreatedAt = data.CreatedAt.Format(time.DateTime)
|
||||
info.Tags = data.Tags
|
||||
info.Persona = data.Persona
|
||||
}
|
||||
|
||||
// 查询数据库,并填充最新的用户信息
|
||||
func full_lastest_userinfo(reply *httpreply.ReplyData, userId int32) {
|
||||
// 查询最新用户信息,并返回
|
||||
data, err := dao.User_Query(userId)
|
||||
if err != nil || data == nil {
|
||||
logrus.Errorf("查询用户最新信息失败,userId:%d,err:%v", userId, err)
|
||||
reply.Status = http.StatusInternalServerError
|
||||
reply.Message = "查询用户信息失败"
|
||||
return
|
||||
}
|
||||
var queryReply QueryReply
|
||||
var info UserInfo
|
||||
Copy_User_Info(data, &info)
|
||||
queryReply.UserInfo = &info
|
||||
reply.Data = queryReply
|
||||
}
|
|
@ -0,0 +1,147 @@
|
|||
package wx
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"mini_server/internal/config"
|
||||
"mini_server/internal/dao"
|
||||
"mini_server/internal/middleware/jwt"
|
||||
"mini_server/internal/server/help"
|
||||
"mini_server/internal/server/httpreply"
|
||||
"mini_server/internal/server/user"
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
type LoginRequest struct {
|
||||
Code string `json:"code" binding:"min=1"` // 临时会话登录code
|
||||
}
|
||||
|
||||
type LoginReply struct {
|
||||
Token string `json:"token"` // 返回登录成功的jwt token
|
||||
UserInfo *user.UserInfo `json:"user_info"`
|
||||
}
|
||||
|
||||
// 微信服务器,返回的数据结构
|
||||
type WxHttpReply struct {
|
||||
Errcode int32 `json:"errcode"` // 错误码
|
||||
Errmsg string `json:"errmsg"` // 错误信息
|
||||
OpenId string `json:"openid"` // 用户唯一标识
|
||||
// Unionid string `json:"unionid"` // 用户在开放平台的唯一标识符,在满足 UnionID 下发条件的情况下会返回,详见微信 UnionID
|
||||
SessionKey string `json:"session_key"` // 会话密钥
|
||||
}
|
||||
|
||||
func WxLogin(c *gin.Context) {
|
||||
reply := httpreply.NewDefaultReplyData()
|
||||
defer httpreply.Reply(c, reply)
|
||||
|
||||
//解析请求参数
|
||||
var request LoginRequest
|
||||
if err := c.ShouldBindJSON(&request); err != nil {
|
||||
reply.Status = http.StatusBadRequest
|
||||
reply.Message = fmt.Sprintf("invalid json data, err:%v", err)
|
||||
return
|
||||
}
|
||||
logrus.Tracef("微信登录,请求参数:%v", request)
|
||||
|
||||
// 从微信查询openId
|
||||
openId, err := get_wx_login_open_id(request.Code)
|
||||
if err != nil {
|
||||
logrus.Errorf("请求微信获取OpenId失败,err:%v", err)
|
||||
reply.Status = http.StatusServiceUnavailable
|
||||
reply.Message = "第三方服务错误"
|
||||
return
|
||||
}
|
||||
|
||||
// 首先查询,是否存在
|
||||
data, err := dao.User_WX_Query(openId)
|
||||
if err != nil {
|
||||
logrus.Errorf("微信登录,数据库查询失败,err:%v", err)
|
||||
reply.Status = http.StatusInternalServerError
|
||||
reply.Message = "用户查询失败"
|
||||
return
|
||||
}
|
||||
|
||||
if data == nil { // 用户不存在,则需要添加创建
|
||||
|
||||
default_wx_username, err := get_default_wx_username()
|
||||
if err != nil {
|
||||
logrus.Errorf("生成微信默认用户名失败,err:%v", err)
|
||||
reply.Status = http.StatusInternalServerError
|
||||
reply.Message = "生成微信默认用户名失败"
|
||||
return
|
||||
}
|
||||
|
||||
data = &dao.User{
|
||||
AvatarId: "",
|
||||
OpenId: openId,
|
||||
Username: default_wx_username, // 默认名称
|
||||
Persona: "{}",
|
||||
Tags: "{}",
|
||||
}
|
||||
|
||||
if _, err = dao.User_WX_Insert(data); err != nil {
|
||||
logrus.Errorf("微信登录,数据库用户添加失败,err:%v", err)
|
||||
reply.Status = http.StatusInternalServerError
|
||||
reply.Message = "用户添加失败"
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// 生成token
|
||||
token, err := jwt.CreateToken(data)
|
||||
if err != nil {
|
||||
logrus.Errorf("微信登录,生成token失败,err:%v", err)
|
||||
reply.Status = http.StatusInternalServerError
|
||||
reply.Message = "token生成失败"
|
||||
return
|
||||
}
|
||||
|
||||
// 返回用户信息
|
||||
var info user.UserInfo
|
||||
user.Copy_User_Info(data, &info)
|
||||
loginReply := LoginReply{
|
||||
Token: token,
|
||||
UserInfo: &info,
|
||||
}
|
||||
reply.Data = &loginReply
|
||||
logrus.Tracef("微信登录成功,应答:%v", reply)
|
||||
}
|
||||
|
||||
func get_wx_login_open_id(code string) (string, error) {
|
||||
//接口请求url拼接
|
||||
url := config.WeiXin.AppUrl(code)
|
||||
|
||||
// 转发请求到微信接口
|
||||
resp, err := http.Get(url)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("请求微信登录接口失败,err:%v", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
// 读取数据
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("读取微信登录应答数据失败,err:%v", err)
|
||||
}
|
||||
|
||||
// 解码数据并赋值给返回的respData
|
||||
respData := new(WxHttpReply)
|
||||
json.Unmarshal(body, &respData)
|
||||
|
||||
openId := respData.OpenId
|
||||
// 检测openid是否为空
|
||||
if openId == "" {
|
||||
return "", fmt.Errorf("读取微信登录应答数据openId为空")
|
||||
}
|
||||
return openId, nil
|
||||
}
|
||||
|
||||
// 注册时返回随机名称
|
||||
func get_default_wx_username() (string, error) {
|
||||
id := help.GetUniqueIdEachSecond()
|
||||
return "微信用户" + id, nil
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"mini_server/internal/config"
|
||||
"mini_server/internal/logger"
|
||||
"mini_server/internal/server"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
func init() {
|
||||
logger.Init_log()
|
||||
|
||||
}
|
||||
|
||||
func main() {
|
||||
|
||||
address := config.ServerListenAddress
|
||||
dsn := config.MysqlDSN
|
||||
if srv, err := server.NewServer(address, dsn); err != nil {
|
||||
logrus.Errorf("服务初始化失败,错误信息:%v", err)
|
||||
} else if err = srv.Run(); err != nil {
|
||||
logrus.Errorf("服务启动失败,错误信息:%v", err)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,447 @@
|
|||
[GIN-debug] [ERROR] listen tcp 0.0.0.0:8002: bind: address already in use
|
||||
[mysql] 2024/05/21 15:34:38 connection.go:49: closing bad idle connection: unexpected read from socket
|
||||
2024/05/21 16:00:38 http: TLS handshake error from 152.89.198.50:65074: tls: first record does not look like a TLS handshake
|
||||
2024/05/21 17:10:17 http: TLS handshake error from 91.240.118.187:65375: tls: first record does not look like a TLS handshake
|
||||
2024/05/21 17:28:09 文件上传请求,文件名:2Wi3IZxiuZJNa27edf8f931dc10ea680d20a3ca53006.jpg, 文件大小:87088, 文件类型:image/jpeg
|
||||
2024/05/21 17:28:28 文件上传请求,文件名:cj8XTQATw9Vka27edf8f931dc10ea680d20a3ca53006.jpg, 文件大小:87088, 文件类型:image/jpeg
|
||||
2024/05/22 04:11:22 http: TLS handshake error from 39.98.166.194:21295: EOF
|
||||
2024/05/22 04:16:39 http: TLS handshake error from 39.98.70.188:47820: tls: first record does not look like a TLS handshake
|
||||
[mysql] 2024/05/22 10:14:12 connection.go:49: closing bad idle connection: unexpected read from socket
|
||||
2024/05/22 10:55:11 文件上传请求,文件名:tmp_096f57f8db6ad391c82dc4032e2ff2e9.jpg, 文件大小:720427, 文件类型:image/jpeg
|
||||
2024/05/22 14:36:10 http: TLS handshake error from 139.162.185.210:34080: EOF
|
||||
2024/05/22 17:19:08 http: TLS handshake error from 223.104.68.207:25987: EOF
|
||||
2024/05/22 19:05:31 http: TLS handshake error from 111.7.96.150:24250: read tcp 192.168.20.202:8002->111.7.96.150:24250: read: connection reset by peer
|
||||
2024/05/22 19:06:04 http: TLS handshake error from 36.99.136.137:6598: local error: tls: unexpected message
|
||||
2024/05/22 22:59:09 http: TLS handshake error from 78.128.114.22:65525: tls: first record does not look like a TLS handshake
|
||||
2024/05/23 00:24:22 http: TLS handshake error from 170.64.155.138:58608: EOF
|
||||
2024/05/23 03:54:22 http: TLS handshake error from 185.122.204.79:64772: tls: first record does not look like a TLS handshake
|
||||
2024/05/23 05:05:51 http: TLS handshake error from 39.98.89.14:30636: EOF
|
||||
2024/05/23 05:14:59 http: TLS handshake error from 39.98.177.174:55832: tls: first record does not look like a TLS handshake
|
||||
2024/05/23 07:36:12 http: TLS handshake error from 115.231.78.7:33511: tls: first record does not look like a TLS handshake
|
||||
2024/05/23 09:55:00 http: TLS handshake error from 39.100.94.106:36678: EOF
|
||||
2024/05/23 09:55:32 http: TLS handshake error from 39.100.94.106:41686: EOF
|
||||
2024/05/23 09:55:32 http: TLS handshake error from 39.100.94.106:41576: EOF
|
||||
2024/05/23 09:55:32 http: TLS handshake error from 39.100.94.106:41688: EOF
|
||||
2024/05/23 17:22:08 http: TLS handshake error from 185.234.216.112:65102: tls: first record does not look like a TLS handshake
|
||||
2024/05/23 23:26:35 http: TLS handshake error from 39.98.82.242:13117: EOF
|
||||
2024/05/23 23:41:38 http: TLS handshake error from 47.92.228.62:49328: tls: first record does not look like a TLS handshake
|
||||
2024/05/23 23:56:19 http: TLS handshake error from 162.216.241.155:35998: unexpected EOF
|
||||
2024/05/23 23:56:20 http: TLS handshake error from 162.216.241.155:34382: tls: unsupported SSLv2 handshake received
|
||||
2024/05/23 23:58:57 http: TLS handshake error from 162.216.241.155:393: tls: unsupported SSLv2 handshake received
|
||||
2024/05/23 23:59:01 http: TLS handshake error from 162.216.241.155:46564: read tcp 192.168.20.202:8002->162.216.241.155:46564: read: connection reset by peer
|
||||
2024/05/23 23:59:01 http: TLS handshake error from 162.216.241.155:46570: read tcp 192.168.20.202:8002->162.216.241.155:46570: read: connection reset by peer
|
||||
2024/05/23 23:59:01 http: TLS handshake error from 162.216.241.155:46586: EOF
|
||||
2024/05/23 23:59:01 http: TLS handshake error from 162.216.241.155:46600: tls: client requested unsupported application protocols ([http/0.9 http/1.0 spdy/1 spdy/2 spdy/3 h2c hq])
|
||||
2024/05/23 23:59:01 http: TLS handshake error from 162.216.241.155:46612: tls: client requested unsupported application protocols ([hq h2c spdy/3 spdy/2 spdy/1 http/1.0 http/0.9])
|
||||
2024/05/23 23:59:01 http: TLS handshake error from 162.216.241.155:46626: read tcp 192.168.20.202:8002->162.216.241.155:46626: read: connection reset by peer
|
||||
2024/05/23 23:59:02 http: TLS handshake error from 162.216.241.155:46634: read tcp 192.168.20.202:8002->162.216.241.155:46634: read: connection reset by peer
|
||||
2024/05/23 23:59:02 http: TLS handshake error from 162.216.241.155:46640: read tcp 192.168.20.202:8002->162.216.241.155:46640: read: connection reset by peer
|
||||
2024/05/23 23:59:02 http: TLS handshake error from 162.216.241.155:46648: EOF
|
||||
2024/05/23 23:59:02 http: TLS handshake error from 162.216.241.155:46654: read tcp 192.168.20.202:8002->162.216.241.155:46654: read: connection reset by peer
|
||||
2024/05/23 23:59:02 http: TLS handshake error from 162.216.241.155:46666: EOF
|
||||
2024/05/24 00:00:12 http: TLS handshake error from 162.216.241.155:55340: remote error: tls: unknown certificate
|
||||
2024/05/24 03:03:07 http: TLS handshake error from 172.233.52.247:60000: read tcp 192.168.20.202:8002->172.233.52.247:60000: read: connection reset by peer
|
||||
2024/05/24 12:35:09 http: TLS handshake error from 178.159.37.98:64758: tls: first record does not look like a TLS handshake
|
||||
2024/05/24 13:26:53 http: TLS handshake error from 78.128.114.22:65268: tls: first record does not look like a TLS handshake
|
||||
2024/05/24 16:20:44 http: TLS handshake error from 78.128.114.22:64939: tls: first record does not look like a TLS handshake
|
||||
2024/05/24 20:34:47 http: TLS handshake error from 39.98.93.197:29537: EOF
|
||||
2024/05/25 10:34:03 http: TLS handshake error from 78.128.114.22:61543: tls: first record does not look like a TLS handshake
|
||||
2024/05/25 13:51:15 http: TLS handshake error from 178.159.37.98:2403: tls: first record does not look like a TLS handshake
|
||||
2024/05/26 00:05:41 http: TLS handshake error from 154.212.141.222:10190: EOF
|
||||
2024/05/26 00:05:42 http: TLS handshake error from 154.212.141.222:10664: EOF
|
||||
2024/05/26 00:05:42 http: TLS handshake error from 154.212.141.222:10888: EOF
|
||||
2024/05/26 00:05:42 http: TLS handshake error from 154.212.141.222:11082: tls: client requested unsupported application protocols ([http/0.9 http/1.0 spdy/1 spdy/2 spdy/3 h2c hq])
|
||||
2024/05/26 00:05:42 http: TLS handshake error from 154.212.141.222:11204: tls: client requested unsupported application protocols ([hq h2c spdy/3 spdy/2 spdy/1 http/1.0 http/0.9])
|
||||
2024/05/26 00:05:42 http: TLS handshake error from 154.212.141.222:11282: read tcp 192.168.20.202:8002->154.212.141.222:11282: read: connection reset by peer
|
||||
2024/05/26 00:05:42 http: TLS handshake error from 154.212.141.222:11350: EOF
|
||||
2024/05/26 00:05:42 http: TLS handshake error from 154.212.141.222:11440: EOF
|
||||
2024/05/26 00:05:42 http: TLS handshake error from 154.212.141.222:11578: read tcp 192.168.20.202:8002->154.212.141.222:11578: read: connection reset by peer
|
||||
2024/05/26 00:05:43 http: TLS handshake error from 154.212.141.222:11706: read tcp 192.168.20.202:8002->154.212.141.222:11706: read: connection reset by peer
|
||||
2024/05/26 00:05:43 http: TLS handshake error from 154.212.141.222:11806: read tcp 192.168.20.202:8002->154.212.141.222:11806: read: connection reset by peer
|
||||
2024/05/26 00:55:26 http: TLS handshake error from 121.62.21.146:49739: tls: first record does not look like a TLS handshake
|
||||
2024/05/26 12:22:21 http: TLS handshake error from 78.128.114.22:3396: tls: first record does not look like a TLS handshake
|
||||
2024/05/26 15:18:04 http: TLS handshake error from 185.234.216.112:65128: tls: first record does not look like a TLS handshake
|
||||
2024/05/26 16:28:35 http: TLS handshake error from 115.231.78.9:8477: tls: first record does not look like a TLS handshake
|
||||
2024/05/26 17:55:22 http: TLS handshake error from 39.108.88.65:51018: unexpected EOF
|
||||
2024/05/26 17:55:22 http: TLS handshake error from 39.108.88.65:55918: tls: unsupported SSLv2 handshake received
|
||||
2024/05/26 17:55:51 http: TLS handshake error from 39.108.88.65:45302: tls: unsupported SSLv2 handshake received
|
||||
2024/05/26 17:55:51 http: TLS handshake error from 39.108.88.65:45312: tls: first record does not look like a TLS handshake
|
||||
2024/05/26 17:56:03 http: TLS handshake error from 39.108.88.65:36676: tls: unsupported SSLv2 handshake received
|
||||
2024/05/26 17:56:03 http: TLS handshake error from 39.108.88.65:36666: tls: no cipher suite supported by both client and server
|
||||
2024/05/26 17:56:03 http: TLS handshake error from 39.108.88.65:36736: tls: client offered only unsupported versions: []
|
||||
2024/05/26 17:56:03 http: TLS handshake error from 39.108.88.65:36750: tls: no cipher suite supported by both client and server
|
||||
2024/05/26 17:56:03 http: TLS handshake error from 39.108.88.65:36714: tls: no cipher suite supported by both client and server
|
||||
2024/05/26 17:56:03 http: TLS handshake error from 39.108.88.65:36720: tls: no cipher suite supported by both client and server
|
||||
2024/05/26 17:56:03 http: TLS handshake error from 39.108.88.65:36704: EOF
|
||||
2024/05/26 17:56:03 http: TLS handshake error from 39.108.88.65:36694: EOF
|
||||
2024/05/26 17:56:03 http: TLS handshake error from 39.108.88.65:36752: tls: no cipher suite supported by both client and server
|
||||
2024/05/26 17:56:03 http: TLS handshake error from 39.108.88.65:36744: EOF
|
||||
2024/05/26 17:56:03 http: TLS handshake error from 39.108.88.65:36790: tls: no cipher suite supported by both client and server
|
||||
2024/05/26 17:56:03 http: TLS handshake error from 39.108.88.65:36822: tls: no cipher suite supported by both client and server
|
||||
2024/05/26 17:56:03 http: TLS handshake error from 39.108.88.65:36792: tls: no cipher suite supported by both client and server
|
||||
2024/05/26 17:56:03 http: TLS handshake error from 39.108.88.65:36776: EOF
|
||||
2024/05/26 17:56:03 http: TLS handshake error from 39.108.88.65:36806: EOF
|
||||
2024/05/26 17:56:03 http: TLS handshake error from 39.108.88.65:36842: tls: client requested unsupported application protocols ([http/0.9 http/1.0 spdy/1 spdy/2 spdy/3 stun.turn stun.nat-discovery h2c webrtc c-webrtc ftp imap pop3 managesieve coap xmpp-client xmpp-server acme-tls/1 mqtt dot ntske/1 sunrpc h3 smb irc nntp nnsp doq grpc-exp])
|
||||
2024/05/26 17:56:03 http: TLS handshake error from 39.108.88.65:36826: tls: no cipher suite supported by both client and server
|
||||
2024/05/26 17:56:03 http: TLS handshake error from 39.108.88.65:36856: EOF
|
||||
2024/05/26 17:56:03 http: TLS handshake error from 39.108.88.65:36690: EOF
|
||||
2024/05/26 17:56:03 http: TLS handshake error from 39.108.88.65:36760: EOF
|
||||
2024/05/26 17:56:03 http: TLS handshake error from 39.108.88.65:36868: EOF
|
||||
2024/05/26 17:56:03 http: TLS handshake error from 39.108.88.65:36874: EOF
|
||||
2024/05/26 17:56:03 http: TLS handshake error from 39.108.88.65:36876: EOF
|
||||
2024/05/26 17:56:03 http: TLS handshake error from 39.108.88.65:36890: EOF
|
||||
2024/05/26 17:56:03 http: TLS handshake error from 39.108.88.65:36892: tls: no cipher suite supported by both client and server
|
||||
2024/05/26 17:56:03 http: TLS handshake error from 39.108.88.65:36928: tls: no cipher suite supported by both client and server
|
||||
2024/05/26 17:56:03 http: TLS handshake error from 39.108.88.65:36906: EOF
|
||||
2024/05/26 17:56:03 http: TLS handshake error from 39.108.88.65:36922: EOF
|
||||
2024/05/26 17:56:03 http: TLS handshake error from 39.108.88.65:36936: EOF
|
||||
2024/05/26 17:56:03 http: TLS handshake error from 39.108.88.65:36938: tls: no cipher suite supported by both client and server
|
||||
2024/05/26 17:56:04 http: TLS handshake error from 39.108.88.65:36976: tls: no cipher suite supported by both client and server
|
||||
2024/05/26 17:56:04 http: TLS handshake error from 39.108.88.65:36958: tls: no cipher suite supported by both client and server
|
||||
2024/05/26 17:56:04 http: TLS handshake error from 39.108.88.65:36950: EOF
|
||||
2024/05/26 17:56:04 http: TLS handshake error from 39.108.88.65:36974: EOF
|
||||
2024/05/26 17:56:04 http: TLS handshake error from 39.108.88.65:36984: tls: no cipher suite supported by both client and server
|
||||
2024/05/26 17:56:04 http: TLS handshake error from 39.108.88.65:36988: tls: no cipher suite supported by both client and server
|
||||
2024/05/26 17:56:04 http: TLS handshake error from 39.108.88.65:36990: EOF
|
||||
2024/05/26 17:56:04 http: TLS handshake error from 39.108.88.65:37004: EOF
|
||||
2024/05/26 17:56:04 http: TLS handshake error from 39.108.88.65:37002: EOF
|
||||
2024/05/26 17:56:04 http: TLS handshake error from 39.108.88.65:37012: tls: no cipher suite supported by both client and server
|
||||
2024/05/26 17:56:04 http: TLS handshake error from 39.108.88.65:37054: tls: no cipher suite supported by both client and server
|
||||
2024/05/26 17:56:04 http: TLS handshake error from 39.108.88.65:37032: tls: no cipher suite supported by both client and server
|
||||
2024/05/26 17:56:04 http: TLS handshake error from 39.108.88.65:37020: EOF
|
||||
2024/05/26 17:56:04 http: TLS handshake error from 39.108.88.65:37042: EOF
|
||||
2024/05/26 17:56:04 http: TLS handshake error from 39.108.88.65:37062: tls: no cipher suite supported by both client and server
|
||||
2024/05/26 17:56:04 http: TLS handshake error from 39.108.88.65:37082: tls: no cipher suite supported by both client and server
|
||||
2024/05/26 17:56:04 http: TLS handshake error from 39.108.88.65:37070: tls: no cipher suite supported by both client and server
|
||||
2024/05/26 17:56:04 http: TLS handshake error from 39.108.88.65:37068: EOF
|
||||
2024/05/26 17:56:04 http: TLS handshake error from 39.108.88.65:37094: tls: client offered only unsupported versions: []
|
||||
2024/05/26 17:56:04 http: TLS handshake error from 39.108.88.65:37078: EOF
|
||||
2024/05/26 17:56:04 http: TLS handshake error from 39.108.88.65:37104: EOF
|
||||
2024/05/26 17:56:04 http: TLS handshake error from 39.108.88.65:37112: EOF
|
||||
2024/05/26 17:56:04 http: TLS handshake error from 39.108.88.65:37122: EOF
|
||||
2024/05/26 17:56:04 http: TLS handshake error from 39.108.88.65:37120: EOF
|
||||
2024/05/26 17:56:04 http: TLS handshake error from 39.108.88.65:37134: tls: no cipher suite supported by both client and server
|
||||
2024/05/26 17:56:04 http: TLS handshake error from 39.108.88.65:37138: tls: no cipher suite supported by both client and server
|
||||
2024/05/26 17:56:04 http: TLS handshake error from 39.108.88.65:37142: EOF
|
||||
2024/05/26 17:56:04 http: TLS handshake error from 39.108.88.65:37148: EOF
|
||||
2024/05/26 17:56:04 http: TLS handshake error from 39.108.88.65:37160: tls: no cipher suite supported by both client and server
|
||||
2024/05/26 17:56:04 http: TLS handshake error from 39.108.88.65:37176: tls: no cipher suite supported by both client and server
|
||||
2024/05/26 17:56:05 http: TLS handshake error from 39.108.88.65:37184: EOF
|
||||
2024/05/26 17:56:05 http: TLS handshake error from 39.108.88.65:37188: EOF
|
||||
2024/05/26 17:56:05 http: TLS handshake error from 39.108.88.65:37190: tls: no cipher suite supported by both client and server
|
||||
2024/05/26 17:56:05 http: TLS handshake error from 39.108.88.65:37206: tls: no cipher suite supported by both client and server
|
||||
2024/05/26 17:56:05 http: TLS handshake error from 39.108.88.65:37220: tls: no cipher suite supported by both client and server
|
||||
2024/05/26 17:56:05 http: TLS handshake error from 39.108.88.65:37192: EOF
|
||||
2024/05/26 17:56:05 http: TLS handshake error from 39.108.88.65:37222: tls: no cipher suite supported by both client and server
|
||||
2024/05/26 17:56:05 http: TLS handshake error from 39.108.88.65:37256: tls: no cipher suite supported by both client and server
|
||||
2024/05/26 17:56:05 http: TLS handshake error from 39.108.88.65:37242: tls: no cipher suite supported by both client and server
|
||||
2024/05/26 17:56:05 http: TLS handshake error from 39.108.88.65:37226: EOF
|
||||
2024/05/26 17:56:05 http: TLS handshake error from 39.108.88.65:37268: EOF
|
||||
2024/05/26 17:56:05 http: TLS handshake error from 39.108.88.65:37274: EOF
|
||||
2024/05/26 17:56:05 http: TLS handshake error from 39.108.88.65:37280: EOF
|
||||
2024/05/26 17:56:05 http: TLS handshake error from 39.108.88.65:37294: EOF
|
||||
2024/05/26 17:56:05 http: TLS handshake error from 39.108.88.65:37312: EOF
|
||||
2024/05/26 17:56:05 http: TLS handshake error from 39.108.88.65:37300: EOF
|
||||
2024/05/26 17:56:05 http: TLS handshake error from 39.108.88.65:37324: EOF
|
||||
2024/05/26 17:56:05 http: TLS handshake error from 39.108.88.65:37344: EOF
|
||||
2024/05/26 17:56:05 http: TLS handshake error from 39.108.88.65:37328: EOF
|
||||
2024/05/26 17:56:05 http: TLS handshake error from 39.108.88.65:37350: tls: no cipher suite supported by both client and server
|
||||
2024/05/26 17:56:05 http: TLS handshake error from 39.108.88.65:37370: EOF
|
||||
2024/05/26 17:56:05 http: TLS handshake error from 39.108.88.65:37354: EOF
|
||||
2024/05/26 17:56:05 http: TLS handshake error from 39.108.88.65:37372: tls: no cipher suite supported by both client and server
|
||||
2024/05/26 17:56:06 http: TLS handshake error from 39.108.88.65:37376: EOF
|
||||
2024/05/26 17:56:06 http: TLS handshake error from 39.108.88.65:37374: EOF
|
||||
2024/05/26 17:56:06 http: TLS handshake error from 39.108.88.65:37386: EOF
|
||||
2024/05/26 17:56:06 http: TLS handshake error from 39.108.88.65:37384: EOF
|
||||
2024/05/26 17:56:06 http: TLS handshake error from 39.108.88.65:37392: EOF
|
||||
2024/05/26 17:56:06 http: TLS handshake error from 39.108.88.65:37402: EOF
|
||||
2024/05/26 17:56:06 http: TLS handshake error from 39.108.88.65:37414: EOF
|
||||
2024/05/26 17:56:06 http: TLS handshake error from 39.108.88.65:37418: EOF
|
||||
2024/05/26 17:56:06 http: TLS handshake error from 39.108.88.65:37442: EOF
|
||||
2024/05/26 17:56:06 http: TLS handshake error from 39.108.88.65:37426: EOF
|
||||
2024/05/26 17:56:06 http: TLS handshake error from 39.108.88.65:37452: EOF
|
||||
2024/05/26 17:56:06 http: TLS handshake error from 39.108.88.65:37484: EOF
|
||||
2024/05/26 17:56:06 http: TLS handshake error from 39.108.88.65:37480: EOF
|
||||
2024/05/26 17:56:06 http: TLS handshake error from 39.108.88.65:37468: EOF
|
||||
2024/05/26 17:56:06 http: TLS handshake error from 39.108.88.65:37494: EOF
|
||||
2024/05/26 17:56:06 http: TLS handshake error from 39.108.88.65:37498: EOF
|
||||
2024/05/26 17:56:07 http: TLS handshake error from 39.108.88.65:37512: EOF
|
||||
2024/05/26 17:56:07 http: TLS handshake error from 39.108.88.65:37516: EOF
|
||||
2024/05/26 17:56:07 http: TLS handshake error from 39.108.88.65:37530: EOF
|
||||
2024/05/26 17:56:07 http: TLS handshake error from 39.108.88.65:37536: EOF
|
||||
2024/05/26 17:56:07 http: TLS handshake error from 39.108.88.65:37540: EOF
|
||||
2024/05/26 17:56:07 http: TLS handshake error from 39.108.88.65:37554: EOF
|
||||
2024/05/26 17:56:08 http: TLS handshake error from 39.108.88.65:42024: EOF
|
||||
2024/05/26 17:56:08 http: TLS handshake error from 39.108.88.65:42030: EOF
|
||||
2024/05/26 17:56:08 http: TLS handshake error from 39.108.88.65:42042: tls: client offered only unsupported versions: []
|
||||
2024/05/26 17:56:08 http: TLS handshake error from 39.108.88.65:36664: EOF
|
||||
[mysql] 2024/05/26 19:41:58 connection.go:49: closing bad idle connection: unexpected read from socket
|
||||
[mysql] 2024/05/26 19:41:58 connection.go:49: closing bad idle connection: unexpected read from socket
|
||||
2024/05/27 04:13:17 http: TLS handshake error from 85.209.133.200:57572: tls: first record does not look like a TLS handshake
|
||||
2024/05/27 04:37:07 http: TLS handshake error from 52.83.91.65:43268: tls: first record does not look like a TLS handshake
|
||||
2024/05/27 07:32:14 http: TLS handshake error from 223.113.128.194:47910: EOF
|
||||
2024/05/27 07:32:26 http: TLS handshake error from 223.113.128.194:38640: read tcp 192.168.20.202:8002->223.113.128.194:38640: read: connection reset by peer
|
||||
2024/05/27 07:32:26 http: TLS handshake error from 223.113.128.194:39086: EOF
|
||||
2024/05/27 07:32:27 http: TLS handshake error from 223.113.128.194:39292: EOF
|
||||
2024/05/27 07:32:27 http: TLS handshake error from 223.113.128.194:39660: EOF
|
||||
2024/05/27 07:32:27 http: TLS handshake error from 223.113.128.194:40228: tls: client requested unsupported application protocols ([http/0.9 http/1.0 spdy/1 spdy/2 spdy/3 h2c hq])
|
||||
2024/05/27 07:32:27 http: TLS handshake error from 223.113.128.194:40546: tls: client requested unsupported application protocols ([hq h2c spdy/3 spdy/2 spdy/1 http/1.0 http/0.9])
|
||||
2024/05/27 07:32:27 http: TLS handshake error from 223.113.128.194:40892: EOF
|
||||
2024/05/27 07:32:28 http: TLS handshake error from 223.113.128.194:41182: EOF
|
||||
2024/05/27 07:32:28 http: TLS handshake error from 223.113.128.194:41452: EOF
|
||||
2024/05/27 07:32:28 http: TLS handshake error from 223.113.128.194:41670: EOF
|
||||
2024/05/27 07:32:28 http: TLS handshake error from 223.113.128.194:41956: EOF
|
||||
2024/05/27 11:08:51 http: TLS handshake error from 87.236.176.84:60715: EOF
|
||||
2024/05/27 11:09:25 http: TLS handshake error from 87.236.176.106:56505: EOF
|
||||
2024/05/27 11:09:58 http: TLS handshake error from 87.236.176.93:35489: EOF
|
||||
2024/05/27 11:10:32 http: TLS handshake error from 87.236.176.91:39803: tls: client requested unsupported application protocols ([http/0.9 http/1.0 spdy/1 spdy/2 spdy/3 h2c hq])
|
||||
2024/05/27 11:11:49 http: TLS handshake error from 87.236.176.93:42575: tls: client requested unsupported application protocols ([hq h2c spdy/3 spdy/2 spdy/1 http/1.0 http/0.9])
|
||||
2024/05/27 11:12:22 http: TLS handshake error from 87.236.176.105:51975: EOF
|
||||
2024/05/27 11:12:56 http: TLS handshake error from 87.236.176.84:60991: EOF
|
||||
2024/05/27 11:13:30 http: TLS handshake error from 87.236.176.85:39577: EOF
|
||||
2024/05/27 11:14:03 http: TLS handshake error from 87.236.176.97:36585: EOF
|
||||
2024/05/27 11:14:37 http: TLS handshake error from 87.236.176.90:60779: EOF
|
||||
2024/05/27 11:26:34 http: TLS handshake error from 178.159.37.98:64812: tls: first record does not look like a TLS handshake
|
||||
2024/05/27 12:42:40 http: TLS handshake error from 85.209.11.113:64237: tls: first record does not look like a TLS handshake
|
||||
2024/05/27 14:33:21 http: TLS handshake error from 52.83.91.65:57994: tls: first record does not look like a TLS handshake
|
||||
2024/05/27 18:31:51 http: TLS handshake error from 78.128.114.22:65130: tls: first record does not look like a TLS handshake
|
||||
[mysql] 2024/05/27 20:26:47 connection.go:49: closing bad idle connection: unexpected read from socket
|
||||
2024/05/27 21:01:32 http: TLS handshake error from 115.231.78.7:46874: tls: first record does not look like a TLS handshake
|
||||
2024/05/27 22:08:14 http: TLS handshake error from 111.7.96.149:13476: read tcp 192.168.20.202:8002->111.7.96.149:13476: read: connection reset by peer
|
||||
2024/05/27 22:08:48 http: TLS handshake error from 36.99.136.128:48245: local error: tls: unexpected message
|
||||
2024/05/27 22:10:35 http: TLS handshake error from 36.40.78.26:57164: read tcp 192.168.20.202:8002->36.40.78.26:57164: read: connection reset by peer
|
||||
2024/05/28 00:32:50 http: TLS handshake error from 94.156.64.245:49034: tls: first record does not look like a TLS handshake
|
||||
2024/05/28 02:39:05 http: TLS handshake error from 101.251.238.169:56693: read tcp 192.168.20.202:8002->101.251.238.169:56693: read: connection reset by peer
|
||||
2024/05/28 02:47:21 http: TLS handshake error from 185.234.216.112:63390: tls: first record does not look like a TLS handshake
|
||||
2024/05/28 06:05:23 http: TLS handshake error from 31.7.62.234:64943: tls: first record does not look like a TLS handshake
|
||||
2024/05/28 14:02:32 http: TLS handshake error from 78.128.114.22:65435: tls: first record does not look like a TLS handshake
|
||||
2024/05/28 14:25:57 http: TLS handshake error from 178.159.37.98:65383: tls: first record does not look like a TLS handshake
|
||||
2024/05/28 14:30:04 http: TLS handshake error from 185.234.216.112:64609: tls: first record does not look like a TLS handshake
|
||||
[mysql] 2024/05/28 21:26:07 connection.go:49: closing bad idle connection: unexpected read from socket
|
||||
2024/05/28 21:49:41 文件上传请求,文件名:1590231450028.jpg, 文件大小:51569, 文件类型:image/jpeg
|
||||
2024/05/28 22:22:14 文件上传请求,文件名:87onykKRLtFy19a0a7202d28622c9cff3fa76820e176.png, 文件大小:379182, 文件类型:image/png
|
||||
2024/05/28 22:23:40 文件上传请求,文件名:FUBZG0VCx9Si19a0a7202d28622c9cff3fa76820e176.png, 文件大小:379182, 文件类型:image/png
|
||||
2024/05/29 10:30:46 http: TLS handshake error from 79.124.56.202:62722: tls: first record does not look like a TLS handshake
|
||||
2024/05/29 10:54:19 http: TLS handshake error from 79.124.56.202:3523: tls: first record does not look like a TLS handshake
|
||||
[mysql] 2024/05/29 11:28:35 connection.go:49: closing bad idle connection: unexpected read from socket
|
||||
2024/05/29 11:31:52 文件上传请求,文件名:1590231450028.jpg, 文件大小:51569, 文件类型:image/jpeg
|
||||
2024/05/29 12:55:39 http: TLS handshake error from 185.234.216.112:64830: tls: first record does not look like a TLS handshake
|
||||
2024/05/29 15:28:42 http: TLS handshake error from 148.153.45.234:54210: EOF
|
||||
2024/05/29 23:33:30 http: TLS handshake error from 79.124.56.202:64548: tls: first record does not look like a TLS handshake
|
||||
2024/05/30 01:03:09 http: TLS handshake error from 185.234.216.112:63180: tls: first record does not look like a TLS handshake
|
||||
2024/05/30 13:56:49 http: TLS handshake error from 185.234.216.112:63513: tls: first record does not look like a TLS handshake
|
||||
2024/05/30 14:57:27 http: TLS handshake error from 87.236.176.140:38815: read tcp 192.168.20.202:8002->87.236.176.140:38815: read: connection reset by peer
|
||||
2024/05/30 14:58:00 http: TLS handshake error from 87.236.176.143:49801: EOF
|
||||
2024/05/30 14:58:40 http: TLS handshake error from 87.236.176.135:50543: read tcp 192.168.20.202:8002->87.236.176.135:50543: read: connection reset by peer
|
||||
2024/05/30 14:59:13 http: TLS handshake error from 87.236.176.141:46163: tls: client requested unsupported application protocols ([http/0.9 http/1.0 spdy/1 spdy/2 spdy/3 h2c hq])
|
||||
2024/05/30 14:59:49 http: TLS handshake error from 87.236.176.111:42803: tls: client requested unsupported application protocols ([hq h2c spdy/3 spdy/2 spdy/1 http/1.0 http/0.9])
|
||||
2024/05/30 15:01:03 http: TLS handshake error from 87.236.176.120:45599: EOF
|
||||
2024/05/30 15:01:37 http: TLS handshake error from 87.236.176.137:38505: read tcp 192.168.20.202:8002->87.236.176.137:38505: read: connection reset by peer
|
||||
2024/05/30 15:02:11 http: TLS handshake error from 87.236.176.141:38265: EOF
|
||||
2024/05/30 15:02:46 http: TLS handshake error from 87.236.176.127:44825: EOF
|
||||
2024/05/30 15:03:21 http: TLS handshake error from 87.236.176.111:58583: EOF
|
||||
2024/05/30 15:33:13 http: TLS handshake error from 39.98.76.173:7606: EOF
|
||||
2024/05/30 20:16:28 http: TLS handshake error from 111.7.96.148:54806: read tcp 192.168.20.202:8002->111.7.96.148:54806: read: connection reset by peer
|
||||
2024/05/30 20:17:20 http: TLS handshake error from 36.99.136.128:51220: local error: tls: unexpected message
|
||||
2024/05/30 20:17:21 http: TLS handshake error from 111.7.96.164:20962: read tcp 192.168.20.202:8002->111.7.96.164:20962: read: connection reset by peer
|
||||
2024/05/30 23:53:38 http: TLS handshake error from 115.231.78.7:61077: tls: first record does not look like a TLS handshake
|
||||
2024/05/31 05:16:52 http: TLS handshake error from 52.83.92.55:52118: tls: first record does not look like a TLS handshake
|
||||
2024/05/31 05:27:50 http: TLS handshake error from 161.189.192.94:47200: tls: first record does not look like a TLS handshake
|
||||
2024/05/31 05:55:11 http: TLS handshake error from 47.92.65.140:43138: unexpected EOF
|
||||
2024/05/31 05:55:11 http: TLS handshake error from 47.92.65.140:43166: tls: unsupported SSLv2 handshake received
|
||||
2024/05/31 05:55:39 http: TLS handshake error from 47.92.65.140:59788: tls: unsupported SSLv2 handshake received
|
||||
2024/05/31 05:55:39 http: TLS handshake error from 47.92.65.140:59792: tls: first record does not look like a TLS handshake
|
||||
2024/05/31 05:55:50 http: TLS handshake error from 47.92.65.140:49446: tls: no cipher suite supported by both client and server
|
||||
2024/05/31 05:55:50 http: TLS handshake error from 47.92.65.140:49452: tls: unsupported SSLv2 handshake received
|
||||
2024/05/31 05:55:50 http: TLS handshake error from 47.92.65.140:49478: tls: client offered only unsupported versions: []
|
||||
2024/05/31 05:55:50 http: TLS handshake error from 47.92.65.140:49502: tls: no cipher suite supported by both client and server
|
||||
2024/05/31 05:55:50 http: TLS handshake error from 47.92.65.140:49464: tls: no cipher suite supported by both client and server
|
||||
2024/05/31 05:55:50 http: TLS handshake error from 47.92.65.140:49490: tls: no cipher suite supported by both client and server
|
||||
2024/05/31 05:55:50 http: TLS handshake error from 47.92.65.140:49418: EOF
|
||||
2024/05/31 05:55:50 http: TLS handshake error from 47.92.65.140:49438: EOF
|
||||
2024/05/31 05:55:50 http: TLS handshake error from 47.92.65.140:49482: EOF
|
||||
2024/05/31 05:55:50 http: TLS handshake error from 47.92.65.140:49522: tls: no cipher suite supported by both client and server
|
||||
2024/05/31 05:55:50 http: TLS handshake error from 47.92.65.140:49570: tls: no cipher suite supported by both client and server
|
||||
2024/05/31 05:55:51 http: TLS handshake error from 47.92.65.140:49520: EOF
|
||||
2024/05/31 05:55:51 http: TLS handshake error from 47.92.65.140:49582: tls: client requested unsupported application protocols ([http/0.9 http/1.0 spdy/1 spdy/2 spdy/3 stun.turn stun.nat-discovery h2c webrtc c-webrtc ftp imap pop3 managesieve coap xmpp-client xmpp-server acme-tls/1 mqtt dot ntske/1 sunrpc h3 smb irc nntp nnsp doq grpc-exp])
|
||||
2024/05/31 05:55:51 http: TLS handshake error from 47.92.65.140:49596: EOF
|
||||
2024/05/31 05:55:51 http: TLS handshake error from 47.92.65.140:49514: EOF
|
||||
2024/05/31 05:55:51 http: TLS handshake error from 47.92.65.140:49416: EOF
|
||||
2024/05/31 05:55:51 http: TLS handshake error from 47.92.65.140:49608: EOF
|
||||
2024/05/31 05:55:51 http: TLS handshake error from 47.92.65.140:49610: EOF
|
||||
2024/05/31 05:55:51 http: TLS handshake error from 47.92.65.140:49614: tls: no cipher suite supported by both client and server
|
||||
2024/05/31 05:55:51 http: TLS handshake error from 47.92.65.140:49622: tls: no cipher suite supported by both client and server
|
||||
2024/05/31 05:55:51 http: TLS handshake error from 47.92.65.140:49632: tls: no cipher suite supported by both client and server
|
||||
2024/05/31 05:55:51 http: TLS handshake error from 47.92.65.140:49644: EOF
|
||||
2024/05/31 05:55:51 http: TLS handshake error from 47.92.65.140:49654: tls: client offered only unsupported versions: []
|
||||
2024/05/31 05:55:51 http: TLS handshake error from 47.92.65.140:49658: tls: no cipher suite supported by both client and server
|
||||
2024/05/31 05:55:51 http: TLS handshake error from 47.92.65.140:49670: tls: no cipher suite supported by both client and server
|
||||
2024/05/31 05:55:51 http: TLS handshake error from 47.92.65.140:49680: tls: no cipher suite supported by both client and server
|
||||
2024/05/31 05:55:51 http: TLS handshake error from 47.92.65.140:49532: tls: no cipher suite supported by both client and server
|
||||
2024/05/31 05:55:51 http: TLS handshake error from 47.92.65.140:49686: tls: no cipher suite supported by both client and server
|
||||
2024/05/31 05:55:51 http: TLS handshake error from 47.92.65.140:49554: tls: no cipher suite supported by both client and server
|
||||
2024/05/31 05:55:52 http: TLS handshake error from 47.92.65.140:49538: read tcp 192.168.20.202:8002->47.92.65.140:49538: read: connection reset by peer
|
||||
2024/05/31 05:55:52 http: TLS handshake error from 47.92.65.140:49698: EOF
|
||||
2024/05/31 05:55:52 http: TLS handshake error from 47.92.65.140:49704: tls: no cipher suite supported by both client and server
|
||||
2024/05/31 05:55:52 http: TLS handshake error from 47.92.65.140:49700: EOF
|
||||
2024/05/31 05:55:52 http: TLS handshake error from 47.92.65.140:49720: EOF
|
||||
2024/05/31 05:55:52 http: TLS handshake error from 47.92.65.140:49734: EOF
|
||||
2024/05/31 05:55:52 http: TLS handshake error from 47.92.65.140:49774: tls: no cipher suite supported by both client and server
|
||||
2024/05/31 05:55:52 http: TLS handshake error from 47.92.65.140:49744: EOF
|
||||
2024/05/31 05:55:52 http: TLS handshake error from 47.92.65.140:49780: tls: no cipher suite supported by both client and server
|
||||
2024/05/31 05:55:52 http: TLS handshake error from 47.92.65.140:49758: EOF
|
||||
2024/05/31 05:55:52 http: TLS handshake error from 47.92.65.140:49790: EOF
|
||||
2024/05/31 05:55:52 http: TLS handshake error from 47.92.65.140:49798: EOF
|
||||
2024/05/31 05:55:52 http: TLS handshake error from 47.92.65.140:49804: tls: no cipher suite supported by both client and server
|
||||
2024/05/31 05:55:52 http: TLS handshake error from 47.92.65.140:49800: tls: no cipher suite supported by both client and server
|
||||
2024/05/31 05:55:52 http: TLS handshake error from 47.92.65.140:49834: tls: no cipher suite supported by both client and server
|
||||
2024/05/31 05:55:52 http: TLS handshake error from 47.92.65.140:49824: EOF
|
||||
2024/05/31 05:55:52 http: TLS handshake error from 47.92.65.140:49816: EOF
|
||||
2024/05/31 05:55:52 http: TLS handshake error from 47.92.65.140:49864: tls: no cipher suite supported by both client and server
|
||||
2024/05/31 05:55:52 http: TLS handshake error from 47.92.65.140:49874: tls: no cipher suite supported by both client and server
|
||||
2024/05/31 05:55:52 http: TLS handshake error from 47.92.65.140:49880: tls: no cipher suite supported by both client and server
|
||||
2024/05/31 05:55:52 http: TLS handshake error from 47.92.65.140:49850: EOF
|
||||
2024/05/31 05:55:52 http: TLS handshake error from 47.92.65.140:49870: EOF
|
||||
2024/05/31 05:55:52 http: TLS handshake error from 47.92.65.140:49882: tls: no cipher suite supported by both client and server
|
||||
2024/05/31 05:55:52 http: TLS handshake error from 47.92.65.140:49898: tls: no cipher suite supported by both client and server
|
||||
2024/05/31 05:55:52 http: TLS handshake error from 47.92.65.140:49900: EOF
|
||||
2024/05/31 05:55:52 http: TLS handshake error from 47.92.65.140:49922: EOF
|
||||
2024/05/31 05:55:52 http: TLS handshake error from 47.92.65.140:49912: EOF
|
||||
2024/05/31 05:55:52 http: TLS handshake error from 47.92.65.140:49932: tls: no cipher suite supported by both client and server
|
||||
2024/05/31 05:55:52 http: TLS handshake error from 47.92.65.140:49948: tls: no cipher suite supported by both client and server
|
||||
2024/05/31 05:55:52 http: TLS handshake error from 47.92.65.140:49954: EOF
|
||||
2024/05/31 05:55:52 http: TLS handshake error from 47.92.65.140:49952: EOF
|
||||
2024/05/31 05:55:52 http: TLS handshake error from 47.92.65.140:49960: EOF
|
||||
2024/05/31 05:55:53 http: TLS handshake error from 47.92.65.140:49968: EOF
|
||||
2024/05/31 05:55:53 http: TLS handshake error from 47.92.65.140:49982: EOF
|
||||
2024/05/31 05:55:53 http: TLS handshake error from 47.92.65.140:49996: EOF
|
||||
2024/05/31 05:55:53 http: TLS handshake error from 47.92.65.140:49998: EOF
|
||||
2024/05/31 05:55:53 http: TLS handshake error from 47.92.65.140:50020: tls: no cipher suite supported by both client and server
|
||||
2024/05/31 05:55:53 http: TLS handshake error from 47.92.65.140:50006: EOF
|
||||
2024/05/31 05:55:53 http: TLS handshake error from 47.92.65.140:50026: EOF
|
||||
2024/05/31 05:55:53 http: TLS handshake error from 47.92.65.140:50048: tls: no cipher suite supported by both client and server
|
||||
2024/05/31 05:55:53 http: TLS handshake error from 47.92.65.140:50034: EOF
|
||||
2024/05/31 05:55:53 http: TLS handshake error from 47.92.65.140:50058: tls: no cipher suite supported by both client and server
|
||||
2024/05/31 05:55:53 http: TLS handshake error from 47.92.65.140:50056: EOF
|
||||
2024/05/31 05:55:53 http: TLS handshake error from 47.92.65.140:50074: EOF
|
||||
2024/05/31 05:55:53 http: TLS handshake error from 47.92.65.140:50102: tls: no cipher suite supported by both client and server
|
||||
2024/05/31 05:55:53 http: TLS handshake error from 47.92.65.140:50090: EOF
|
||||
2024/05/31 05:55:53 http: TLS handshake error from 47.92.65.140:50110: EOF
|
||||
2024/05/31 05:55:53 http: TLS handshake error from 47.92.65.140:50124: EOF
|
||||
2024/05/31 05:55:53 http: TLS handshake error from 47.92.65.140:50126: EOF
|
||||
2024/05/31 05:55:53 http: TLS handshake error from 47.92.65.140:50138: EOF
|
||||
2024/05/31 05:55:53 http: TLS handshake error from 47.92.65.140:50140: EOF
|
||||
2024/05/31 05:55:53 http: TLS handshake error from 47.92.65.140:50144: EOF
|
||||
2024/05/31 05:55:54 http: TLS handshake error from 47.92.65.140:50156: EOF
|
||||
2024/05/31 05:55:54 http: TLS handshake error from 47.92.65.140:50166: EOF
|
||||
2024/05/31 05:55:54 http: TLS handshake error from 47.92.65.140:50178: EOF
|
||||
2024/05/31 05:55:54 http: TLS handshake error from 47.92.65.140:50180: EOF
|
||||
2024/05/31 05:55:54 http: TLS handshake error from 47.92.65.140:50206: tls: no cipher suite supported by both client and server
|
||||
2024/05/31 05:55:54 http: TLS handshake error from 47.92.65.140:50194: EOF
|
||||
2024/05/31 05:55:54 http: TLS handshake error from 47.92.65.140:50232: tls: no cipher suite supported by both client and server
|
||||
2024/05/31 05:55:54 http: TLS handshake error from 47.92.65.140:50222: EOF
|
||||
2024/05/31 05:55:54 http: TLS handshake error from 47.92.65.140:50242: EOF
|
||||
2024/05/31 05:55:54 http: TLS handshake error from 47.92.65.140:50258: EOF
|
||||
2024/05/31 05:55:54 http: TLS handshake error from 47.92.65.140:50264: EOF
|
||||
2024/05/31 05:55:54 http: TLS handshake error from 47.92.65.140:50266: EOF
|
||||
2024/05/31 05:55:54 http: TLS handshake error from 47.92.65.140:50270: EOF
|
||||
2024/05/31 05:55:54 http: TLS handshake error from 47.92.65.140:50280: EOF
|
||||
2024/05/31 05:55:55 http: TLS handshake error from 47.92.65.140:50296: EOF
|
||||
2024/05/31 05:55:55 http: TLS handshake error from 47.92.65.140:50300: EOF
|
||||
2024/05/31 05:55:55 http: TLS handshake error from 47.92.65.140:50316: EOF
|
||||
2024/05/31 05:55:55 http: TLS handshake error from 47.92.65.140:50326: EOF
|
||||
2024/05/31 05:55:55 http: TLS handshake error from 47.92.65.140:50334: EOF
|
||||
2024/05/31 05:55:55 http: TLS handshake error from 47.92.65.140:49378: EOF
|
||||
2024/05/31 05:55:55 http: TLS handshake error from 47.92.65.140:49386: EOF
|
||||
2024/05/31 05:55:55 http: TLS handshake error from 47.92.65.140:49390: EOF
|
||||
2024/05/31 05:55:56 http: TLS handshake error from 47.92.65.140:49400: EOF
|
||||
2024/05/31 05:55:56 http: TLS handshake error from 47.92.65.140:49416: EOF
|
||||
2024/05/31 05:55:56 http: TLS handshake error from 47.92.65.140:49426: EOF
|
||||
2024/05/31 05:55:56 http: TLS handshake error from 47.92.65.140:49428: EOF
|
||||
2024/05/31 05:55:56 http: TLS handshake error from 47.92.65.140:49438: tls: client offered only unsupported versions: []
|
||||
2024/05/31 05:55:56 http: TLS handshake error from 47.92.65.140:49414: EOF
|
||||
2024/05/31 12:39:35 http: TLS handshake error from 85.209.11.113:63985: tls: first record does not look like a TLS handshake
|
||||
2024/05/31 13:29:55 http: TLS handshake error from 79.124.56.202:64545: tls: first record does not look like a TLS handshake
|
||||
2024/05/31 16:23:30 http: TLS handshake error from 185.234.216.112:64460: tls: first record does not look like a TLS handshake
|
||||
2024/06/01 02:43:30 http: TLS handshake error from 213.226.123.98:64873: tls: first record does not look like a TLS handshake
|
||||
2024/06/01 11:24:57 http: TLS handshake error from 79.124.56.202:64076: tls: first record does not look like a TLS handshake
|
||||
2024/06/01 14:28:13 http: TLS handshake error from 79.124.56.202:65124: tls: first record does not look like a TLS handshake
|
||||
2024/06/01 18:16:43 http: TLS handshake error from 213.226.123.98:64798: tls: first record does not look like a TLS handshake
|
||||
2024/06/01 22:25:07 http: TLS handshake error from 206.81.24.227:44996: read tcp 192.168.20.202:8002->206.81.24.227:44996: read: connection reset by peer
|
||||
2024/06/01 22:25:08 http: TLS handshake error from 206.81.24.227:45012: read tcp 192.168.20.202:8002->206.81.24.227:45012: read: connection reset by peer
|
||||
2024/06/01 22:25:08 http: TLS handshake error from 206.81.24.227:45016: read tcp 192.168.20.202:8002->206.81.24.227:45016: read: connection reset by peer
|
||||
2024/06/01 22:25:09 http: TLS handshake error from 206.81.24.227:45018: tls: client requested unsupported application protocols ([http/0.9 http/1.0 spdy/1 spdy/2 spdy/3 h2c hq])
|
||||
2024/06/01 22:25:09 http: TLS handshake error from 206.81.24.227:45028: tls: client requested unsupported application protocols ([hq h2c spdy/3 spdy/2 spdy/1 http/1.0 http/0.9])
|
||||
2024/06/01 22:25:10 http: TLS handshake error from 206.81.24.227:45038: read tcp 192.168.20.202:8002->206.81.24.227:45038: read: connection reset by peer
|
||||
2024/06/01 22:25:11 http: TLS handshake error from 206.81.24.227:45046: read tcp 192.168.20.202:8002->206.81.24.227:45046: read: connection reset by peer
|
||||
2024/06/01 22:25:12 http: TLS handshake error from 206.81.24.227:45058: read tcp 192.168.20.202:8002->206.81.24.227:45058: read: connection reset by peer
|
||||
2024/06/01 22:25:12 http: TLS handshake error from 206.81.24.227:45070: read tcp 192.168.20.202:8002->206.81.24.227:45070: read: connection reset by peer
|
||||
2024/06/01 22:25:13 http: TLS handshake error from 206.81.24.227:45078: read tcp 192.168.20.202:8002->206.81.24.227:45078: read: connection reset by peer
|
||||
2024/06/02 00:48:59 http: TLS handshake error from 172.235.174.210:60000: read tcp 192.168.20.202:8002->172.235.174.210:60000: read: connection reset by peer
|
||||
2024/06/02 02:20:17 http: TLS handshake error from 118.193.56.149:54516: EOF
|
||||
2024/06/02 02:20:37 http: TLS handshake error from 118.193.56.149:47666: read tcp 192.168.20.202:8002->118.193.56.149:47666: read: connection reset by peer
|
||||
2024/06/02 02:20:37 http: TLS handshake error from 118.193.56.149:47676: read tcp 192.168.20.202:8002->118.193.56.149:47676: read: connection reset by peer
|
||||
2024/06/02 02:20:37 http: TLS handshake error from 118.193.56.149:47684: read tcp 192.168.20.202:8002->118.193.56.149:47684: read: connection reset by peer
|
||||
2024/06/02 02:20:37 http: TLS handshake error from 118.193.56.149:47698: tls: client requested unsupported application protocols ([http/0.9 http/1.0 spdy/1 spdy/2 spdy/3 h2c hq])
|
||||
2024/06/02 02:20:37 http: TLS handshake error from 118.193.56.149:47710: tls: client requested unsupported application protocols ([hq h2c spdy/3 spdy/2 spdy/1 http/1.0 http/0.9])
|
||||
2024/06/02 02:20:38 http: TLS handshake error from 118.193.56.149:47724: read tcp 192.168.20.202:8002->118.193.56.149:47724: read: connection reset by peer
|
||||
2024/06/02 02:20:38 http: TLS handshake error from 118.193.56.149:47728: read tcp 192.168.20.202:8002->118.193.56.149:47728: read: connection reset by peer
|
||||
2024/06/02 02:20:38 http: TLS handshake error from 118.193.56.149:47738: read tcp 192.168.20.202:8002->118.193.56.149:47738: read: connection reset by peer
|
||||
2024/06/02 02:20:38 http: TLS handshake error from 118.193.56.149:47752: read tcp 192.168.20.202:8002->118.193.56.149:47752: read: connection reset by peer
|
||||
2024/06/02 02:20:39 http: TLS handshake error from 118.193.56.149:47758: read tcp 192.168.20.202:8002->118.193.56.149:47758: read: connection reset by peer
|
||||
2024/06/02 10:00:17 http: TLS handshake error from 213.226.123.98:63162: tls: first record does not look like a TLS handshake
|
||||
2024/06/02 11:07:39 http: TLS handshake error from 115.231.78.9:11949: tls: first record does not look like a TLS handshake
|
||||
2024/06/02 12:05:00 http: TLS handshake error from 152.89.198.254:63533: tls: first record does not look like a TLS handshake
|
||||
2024/06/02 13:26:15 http: TLS handshake error from 79.124.56.202:64139: tls: first record does not look like a TLS handshake
|
||||
2024/06/02 14:42:51 http: TLS handshake error from 178.159.37.98:2669: tls: first record does not look like a TLS handshake
|
||||
[mysql] 2024/06/02 18:05:24 connection.go:49: closing bad idle connection: unexpected read from socket
|
||||
[mysql] 2024/06/02 18:05:24 connection.go:49: closing bad idle connection: unexpected read from socket
|
||||
2024/06/02 19:02:42 http: TLS handshake error from 87.236.176.208:60789: EOF
|
||||
2024/06/02 19:03:55 http: TLS handshake error from 87.236.176.213:52835: read tcp 192.168.20.202:8002->87.236.176.213:52835: read: connection reset by peer
|
||||
2024/06/02 19:04:29 http: TLS handshake error from 87.236.176.217:58165: EOF
|
||||
2024/06/02 19:04:52 http: TLS handshake error from 79.124.56.202:65005: tls: first record does not look like a TLS handshake
|
||||
2024/06/02 19:06:23 http: TLS handshake error from 87.236.176.213:35043: tls: client requested unsupported application protocols ([http/0.9 http/1.0 spdy/1 spdy/2 spdy/3 h2c hq])
|
||||
2024/06/02 19:06:56 http: TLS handshake error from 87.236.176.195:41495: tls: client requested unsupported application protocols ([hq h2c spdy/3 spdy/2 spdy/1 http/1.0 http/0.9])
|
||||
2024/06/02 19:07:30 http: TLS handshake error from 87.236.176.210:48675: read tcp 192.168.20.202:8002->87.236.176.210:48675: read: connection reset by peer
|
||||
2024/06/02 19:08:44 http: TLS handshake error from 87.236.176.203:40213: read tcp 192.168.20.202:8002->87.236.176.203:40213: read: connection reset by peer
|
||||
2024/06/02 19:09:57 http: TLS handshake error from 87.236.176.206:51169: EOF
|
||||
2024/06/02 19:10:31 http: TLS handshake error from 87.236.176.189:42549: EOF
|
||||
2024/06/02 19:11:04 http: TLS handshake error from 87.236.176.183:45873: EOF
|
||||
2024/06/03 01:58:40 http: TLS handshake error from 213.226.123.98:65404: tls: first record does not look like a TLS handshake
|
||||
2024/06/03 02:02:28 http: TLS handshake error from 111.162.158.53:57399: EOF
|
||||
2024/06/03 02:02:38 http: TLS handshake error from 180.212.93.10:52777: EOF
|
||||
2024/06/03 02:02:44 http: TLS handshake error from 118.81.86.60:53559: EOF
|
||||
2024/06/03 02:02:48 http: TLS handshake error from 171.120.158.108:32526: read tcp 192.168.20.202:8002->171.120.158.108:32526: read: connection reset by peer
|
||||
2024/06/03 02:02:49 http: TLS handshake error from 27.98.228.73:42586: tls: client requested unsupported application protocols ([http/0.9 http/1.0 spdy/1 spdy/2 spdy/3 h2c hq])
|
||||
2024/06/03 02:02:49 http: TLS handshake error from 110.177.176.191:58517: tls: client requested unsupported application protocols ([hq h2c spdy/3 spdy/2 spdy/1 http/1.0 http/0.9])
|
||||
2024/06/03 02:02:49 http: TLS handshake error from 221.213.12.184:64390: read tcp 192.168.20.202:8002->221.213.12.184:64390: read: connection reset by peer
|
||||
2024/06/03 02:02:51 http: TLS handshake error from 221.213.12.230:43586: EOF
|
||||
2024/06/03 02:02:51 http: TLS handshake error from 60.16.204.89:37869: read tcp 192.168.20.202:8002->60.16.204.89:37869: read: connection reset by peer
|
||||
2024/06/03 02:02:54 http: TLS handshake error from 124.90.51.219:54040: EOF
|
||||
2024/06/03 02:02:55 http: TLS handshake error from 171.8.138.202:21988: read tcp 192.168.20.202:8002->171.8.138.202:21988: read: connection reset by peer
|
||||
2024/06/03 02:02:57 http: TLS handshake error from 111.224.6.7:28407: read tcp 192.168.20.202:8002->111.224.6.7:28407: read: connection reset by peer
|
||||
2024/06/03 02:03:03 http: TLS handshake error from 124.90.48.175:40575: EOF
|
||||
2024/06/03 02:05:52 http: TLS handshake error from 175.30.48.170:65225: read tcp 192.168.20.202:8002->175.30.48.170:65225: read: connection timed out
|
||||
2024/06/03 10:07:12 http: TLS handshake error from 154.212.141.203:58604: EOF
|
||||
2024/06/03 10:07:12 http: TLS handshake error from 154.212.141.203:58624: read tcp 192.168.20.202:8002->154.212.141.203:58624: read: connection reset by peer
|
||||
2024/06/03 10:07:12 http: TLS handshake error from 154.212.141.203:58658: EOF
|
||||
2024/06/03 10:07:12 http: TLS handshake error from 154.212.141.203:58752: tls: client requested unsupported application protocols ([http/0.9 http/1.0 spdy/1 spdy/2 spdy/3 h2c hq])
|
||||
2024/06/03 10:07:12 http: TLS handshake error from 154.212.141.203:58776: tls: client requested unsupported application protocols ([hq h2c spdy/3 spdy/2 spdy/1 http/1.0 http/0.9])
|
||||
2024/06/03 10:07:12 http: TLS handshake error from 154.212.141.203:58806: read tcp 192.168.20.202:8002->154.212.141.203:58806: read: connection reset by peer
|
||||
2024/06/03 10:07:12 http: TLS handshake error from 154.212.141.203:58822: EOF
|
||||
2024/06/03 10:07:12 http: TLS handshake error from 154.212.141.203:58868: read tcp 192.168.20.202:8002->154.212.141.203:58868: read: connection reset by peer
|
||||
2024/06/03 10:07:12 http: TLS handshake error from 154.212.141.203:58886: EOF
|
||||
2024/06/03 10:07:13 http: TLS handshake error from 154.212.141.203:58910: read tcp 192.168.20.202:8002->154.212.141.203:58910: read: connection reset by peer
|
||||
2024/06/03 10:07:13 http: TLS handshake error from 154.212.141.203:58924: EOF
|
||||
2024/06/03 10:28:09 http: TLS handshake error from 178.159.37.98:2201: tls: first record does not look like a TLS handshake
|
||||
2024/06/03 14:37:43 http: TLS handshake error from 79.124.56.202:61708: tls: first record does not look like a TLS handshake
|
||||
2024/06/03 15:22:07 http: TLS handshake error from 79.124.56.202:62208: tls: first record does not look like a TLS handshake
|
||||
2024/06/03 19:30:22 http: TLS handshake error from 39.100.34.21:9929: EOF
|
||||
2024/06/04 02:03:45 http: TLS handshake error from 79.124.56.202:65187: tls: first record does not look like a TLS handshake
|
||||
2024/06/04 02:52:56 http: TLS handshake error from 170.64.234.117:53702: EOF
|
||||
2024/06/04 05:30:07 http: TLS handshake error from 161.189.192.94:38938: tls: first record does not look like a TLS handshake
|
||||
2024/06/04 05:36:52 http: TLS handshake error from 161.189.134.11:53366: tls: first record does not look like a TLS handshake
|
||||
2024/06/04 07:02:52 http: TLS handshake error from 31.7.62.234:59603: tls: first record does not look like a TLS handshake
|
||||
2024/06/04 09:40:20 http: TLS handshake error from 39.100.20.124:11732: EOF
|
||||
2024/06/04 12:05:20 http: TLS handshake error from 39.98.186.243:27542: EOF
|
||||
2024/06/04 14:13:20 http: TLS handshake error from 79.124.56.202:60759: tls: first record does not look like a TLS handshake
|
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue