Compare commits

...

12 Commits

Author SHA1 Message Date
truthhun 1220eb55f2 文档转换
6 months ago
truthhun 04eafd7f16 inkscape required
6 months ago
truthhun 3a1bec6f42 svg处理
6 months ago
truthhun 785b5ac5a9 文档转换处理
6 months ago
truthhun 1dc153e5df reconvert
6 months ago
truthhun dd8dd11043 支持webp
6 months ago
truthhun db0215899a hash问题检测
6 months ago
truthhun b942f939fb update .gitignore
6 months ago
truthhun 87267ef477 无值不替换为*
6 months ago
truthhun d2e68ba422 私密信息用星号替代
6 months ago
truthhun f1a82f3c87 控制是否验证注册邮箱
6 months ago
truthhun 243536f03a imagemagick版本检测
6 months ago

3
.gitignore vendored

@ -17,4 +17,5 @@ license.cert
*.cert
/logs
/util/cloudstore
*.crt
*.crt
/tmp

@ -649,6 +649,7 @@ type ConfigSecurity struct {
MaxDocumentSize int32 `protobuf:"varint,9,opt,name=max_document_size,json=maxDocumentSize,proto3" json:"max_document_size,omitempty"`
DocumentAllowedExt []string `protobuf:"bytes,10,rep,name=document_allowed_ext,json=documentAllowedExt,proto3" json:"document_allowed_ext,omitempty"`
LoginRequired bool `protobuf:"varint,11,opt,name=login_required,json=loginRequired,proto3" json:"login_required,omitempty"`
EnableVerifyRegisterEmail bool `protobuf:"varint,12,opt,name=enable_verify_register_email,json=enableVerifyRegisterEmail,proto3" json:"enable_verify_register_email,omitempty"`
}
func (m *ConfigSecurity) Reset() { *m = ConfigSecurity{} }
@ -761,6 +762,13 @@ func (m *ConfigSecurity) GetLoginRequired() bool {
return false
}
func (m *ConfigSecurity) GetEnableVerifyRegisterEmail() bool {
if m != nil {
return m.EnableVerifyRegisterEmail
}
return false
}
// 系统配置
type Settings struct {
System *ConfigSystem `protobuf:"bytes,1,opt,name=system,proto3" json:"system,omitempty"`
@ -1411,125 +1419,126 @@ func init() {
func init() { proto.RegisterFile("api/v1/config.proto", fileDescriptor_321614cd6c9c1b8a) }
var fileDescriptor_321614cd6c9c1b8a = []byte{
// 1876 bytes of a gzipped FileDescriptorProto
// 1901 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x58, 0xdd, 0x6f, 0x1b, 0xb9,
0x11, 0x8f, 0xbe, 0x2c, 0x69, 0x24, 0x4b, 0x0e, 0xfd, 0x11, 0x45, 0x49, 0x1d, 0x67, 0x7b, 0xd7,
0x11, 0x8f, 0xbe, 0x2c, 0x89, 0x92, 0x25, 0x87, 0x76, 0x12, 0x45, 0x49, 0x1d, 0x67, 0x7b, 0xd7,
0xf3, 0x05, 0x85, 0x75, 0x71, 0xbf, 0x80, 0xb6, 0xc0, 0xc1, 0xb1, 0x7d, 0xa9, 0x81, 0xeb, 0xc1,
0xa5, 0xcf, 0xe8, 0xc7, 0xcb, 0x82, 0xde, 0xa5, 0x25, 0xd6, 0xab, 0xe5, 0x1e, 0x49, 0x29, 0x56,
0x5e, 0x8a, 0xde, 0x53, 0x81, 0xbe, 0x5c, 0x51, 0xa0, 0xfd, 0x97, 0x5a, 0xf4, 0xe5, 0x80, 0xbe,
0xf4, 0xad, 0x45, 0xd2, 0xfe, 0x1d, 0x2d, 0x38, 0xe4, 0xae, 0x24, 0x1b, 0x06, 0x02, 0xf4, 0x8d,
0x33, 0xf3, 0xe3, 0x70, 0x38, 0xf3, 0xe3, 0x90, 0xbb, 0xb0, 0xce, 0x32, 0x31, 0x98, 0x3e, 0x1f,
0x44, 0x32, 0xbd, 0x14, 0xc3, 0xbd, 0x4c, 0x49, 0x23, 0xc9, 0x0a, 0xcb, 0xc4, 0xde, 0xf4, 0x79,
0xff, 0xc9, 0x50, 0xca, 0x61, 0xc2, 0x07, 0xa8, 0xbd, 0x98, 0x5c, 0x0e, 0x8c, 0x18, 0x73, 0x6d,
0xd8, 0x38, 0x73, 0xc0, 0xfe, 0xc6, 0x50, 0x0e, 0x25, 0x0e, 0x07, 0x76, 0xe4, 0xb5, 0x8f, 0xfd,
0x34, 0xeb, 0x9a, 0xa5, 0xa9, 0x34, 0xcc, 0x08, 0x99, 0x6a, 0x6f, 0x7d, 0x74, 0xd3, 0x29, 0x1f,
0x67, 0x66, 0xe6, 0x8c, 0xc1, 0x7f, 0xca, 0xb0, 0x72, 0x88, 0xa1, 0x90, 0x0e, 0x94, 0x45, 0xdc,
0x2b, 0xed, 0x94, 0x76, 0x2b, 0xb4, 0x2c, 0x62, 0xb2, 0x01, 0xb5, 0x84, 0x5d, 0xf0, 0xa4, 0x57,
0xde, 0x29, 0xed, 0x36, 0xa9, 0x13, 0x08, 0x81, 0x6a, 0xca, 0xc6, 0xbc, 0x57, 0x41, 0x25, 0x8e,
0x2d, 0x72, 0xca, 0x92, 0x09, 0xef, 0x55, 0x1d, 0x12, 0x05, 0xb2, 0x03, 0xad, 0x2c, 0x61, 0x11,
0x1f, 0xc9, 0x24, 0xe6, 0xaa, 0x57, 0x43, 0xdb, 0xa2, 0x8a, 0x7c, 0x03, 0x40, 0xa4, 0xd9, 0xc4,
0x84, 0x66, 0x96, 0xf1, 0xde, 0x0a, 0x02, 0x9a, 0xa8, 0xf9, 0x7c, 0x96, 0x71, 0xd2, 0x87, 0x46,
0xc4, 0x0c, 0x1f, 0x4a, 0x35, 0xeb, 0xd5, 0xd1, 0x58, 0xc8, 0x36, 0x0c, 0x2d, 0x95, 0xe9, 0x35,
0x76, 0x4a, 0xbb, 0x35, 0x8a, 0x63, 0xd2, 0x83, 0xba, 0xcc, 0x70, 0xe7, 0xbd, 0x26, 0xc2, 0x73,
0x91, 0x7c, 0x0c, 0x10, 0x29, 0xce, 0x0c, 0x8f, 0x43, 0x66, 0x7a, 0xb0, 0x53, 0xda, 0x6d, 0xed,
0xf7, 0xf7, 0x5c, 0x5e, 0xf6, 0xf2, 0xbc, 0xec, 0x7d, 0x9e, 0x27, 0xfb, 0x45, 0xf5, 0xab, 0x7f,
0x3e, 0x29, 0xd1, 0xa6, 0x9f, 0x73, 0x60, 0xac, 0x83, 0x49, 0x16, 0xe7, 0x0e, 0x5a, 0xef, 0xea,
0xc0, 0xcf, 0x39, 0x30, 0xc1, 0x00, 0xee, 0x7f, 0x2a, 0xb4, 0x71, 0xa9, 0xa6, 0xfc, 0x8b, 0x09,
0xd7, 0x66, 0x69, 0x83, 0xa5, 0x9d, 0xca, 0xe2, 0x06, 0x83, 0xe7, 0x50, 0x77, 0x60, 0x4d, 0xbe,
0x05, 0x2b, 0x8e, 0x2d, 0x08, 0x6a, 0xed, 0x77, 0xf6, 0x1c, 0x5d, 0xf6, 0xbc, 0x37, 0x6f, 0x0d,
0x04, 0xac, 0x3a, 0xcd, 0x21, 0xcb, 0x4c, 0x34, 0x62, 0x64, 0x0b, 0x56, 0x12, 0x9e, 0x0e, 0xcd,
0x08, 0xab, 0x5a, 0xa3, 0x5e, 0xb2, 0xf5, 0x7a, 0x25, 0x62, 0x33, 0xc2, 0xca, 0xd6, 0xa8, 0x13,
0x2c, 0x7a, 0xc4, 0xc5, 0x70, 0x64, 0xb0, 0xb6, 0x35, 0xea, 0x25, 0x9b, 0x6a, 0xac, 0x8f, 0x2b,
0x2e, 0x8e, 0x83, 0xff, 0x56, 0xa0, 0xed, 0xd6, 0x3a, 0x9b, 0x69, 0xc3, 0xc7, 0x76, 0x72, 0x2c,
0xc7, 0x4c, 0xa4, 0xb8, 0x54, 0x93, 0x7a, 0xc9, 0x2e, 0x65, 0x84, 0x49, 0x78, 0x4e, 0x22, 0x14,
0xec, 0xc6, 0xaf, 0xf8, 0xec, 0x95, 0x54, 0xb1, 0xf6, 0x44, 0x2a, 0x64, 0x4b, 0x9b, 0x98, 0xeb,
0x48, 0x09, 0xac, 0x9d, 0x5f, 0x75, 0x51, 0x65, 0x03, 0x4a, 0xe4, 0x50, 0x7a, 0x46, 0xe1, 0xd8,
0xd6, 0xfe, 0x92, 0x4d, 0x45, 0x24, 0x53, 0xcf, 0xa3, 0x5c, 0x24, 0x6b, 0x50, 0x11, 0x51, 0xe6,
0x09, 0x64, 0x87, 0xe4, 0x31, 0x34, 0x59, 0xca, 0x92, 0x99, 0x11, 0x91, 0x46, 0x02, 0x35, 0xe9,
0x5c, 0x61, 0x63, 0xd3, 0xc2, 0x70, 0x24, 0xb9, 0xa3, 0x51, 0x21, 0x93, 0x8f, 0x60, 0x23, 0x92,
0xd9, 0x4c, 0xd9, 0xbc, 0x84, 0xda, 0x30, 0x65, 0xc2, 0x19, 0x67, 0x0a, 0x19, 0xd5, 0xa4, 0xa4,
0xb0, 0x9d, 0x59, 0xd3, 0x2f, 0x39, 0x53, 0x64, 0x00, 0xeb, 0x8a, 0x0f, 0x85, 0x36, 0x5c, 0x85,
0x17, 0x2c, 0xba, 0x1a, 0x2a, 0x39, 0x49, 0x63, 0x64, 0x50, 0x93, 0x92, 0xdc, 0xf4, 0xa2, 0xb0,
0x90, 0x0f, 0x61, 0x2d, 0x91, 0x43, 0x91, 0x2e, 0xa2, 0xdb, 0x88, 0xee, 0xa2, 0x7e, 0x01, 0xfa,
0x01, 0x74, 0x15, 0x8f, 0xe4, 0x78, 0xcc, 0xd3, 0x38, 0x74, 0xc9, 0x5c, 0x45, 0x16, 0x75, 0x0a,
0xf5, 0xcf, 0x31, 0xa5, 0x3d, 0xa8, 0x4f, 0xb9, 0xd2, 0x36, 0x9d, 0x1d, 0x97, 0x1c, 0x2f, 0x92,
0x27, 0xd0, 0x8a, 0x14, 0x8f, 0x85, 0x09, 0x71, 0xbf, 0x5d, 0xb4, 0x82, 0x53, 0x7d, 0x66, 0x77,
0xfc, 0x00, 0xea, 0x9a, 0x47, 0xa1, 0xcd, 0xe0, 0x9a, 0x2b, 0xac, 0xe6, 0xd1, 0x49, 0x94, 0x05,
0x7f, 0x2a, 0xe5, 0x0c, 0xf8, 0x44, 0x4a, 0xc3, 0x95, 0xad, 0x34, 0xbb, 0x90, 0x13, 0xe3, 0x09,
0xe0, 0x04, 0xbb, 0x74, 0x24, 0x53, 0xc3, 0x22, 0xe3, 0x19, 0x90, 0x8b, 0x58, 0x85, 0xa1, 0xe2,
0x7c, 0xcc, 0x53, 0xe3, 0x49, 0x30, 0x57, 0x58, 0x6b, 0x91, 0x4d, 0xcf, 0x81, 0xb9, 0xc2, 0xd6,
0xe8, 0x92, 0xf3, 0xd8, 0xa6, 0xc8, 0xb3, 0xa0, 0x90, 0x83, 0x3f, 0x94, 0xf3, 0x63, 0x70, 0x24,
0x74, 0x96, 0xb0, 0x19, 0xf9, 0x01, 0xf4, 0xf4, 0x48, 0xbe, 0x0a, 0x8b, 0x42, 0x4c, 0x34, 0x57,
0x61, 0x24, 0x27, 0xa9, 0x0b, 0xb6, 0x41, 0x37, 0xad, 0x9d, 0x7a, 0xf3, 0xb9, 0xe6, 0xea, 0xd0,
0x1a, 0xc9, 0x3e, 0xa0, 0x21, 0x14, 0x69, 0xcc, 0xaf, 0x43, 0x7f, 0x34, 0x05, 0xd7, 0xb8, 0x95,
0x06, 0x5d, 0xb7, 0xc6, 0x13, 0x6b, 0x3b, 0x2c, 0x4c, 0xe4, 0x3d, 0xe8, 0x64, 0x6c, 0xc8, 0x75,
0x98, 0x71, 0x15, 0x2a, 0xce, 0x62, 0x7f, 0x9a, 0xda, 0xa8, 0x3d, 0xe5, 0x8a, 0x72, 0x16, 0x5b,
0x5a, 0x2c, 0x11, 0xc9, 0xb8, 0x34, 0x54, 0x6f, 0xf3, 0xc8, 0x59, 0xc8, 0x8f, 0xa1, 0x8f, 0xa1,
0xc4, 0x32, 0x9a, 0x58, 0x45, 0xb8, 0x70, 0x20, 0x34, 0xe6, 0xa0, 0x41, 0x71, 0x97, 0x47, 0x1e,
0x70, 0xb4, 0x60, 0x0f, 0xfe, 0x5c, 0x85, 0x8e, 0x3f, 0xae, 0x3c, 0x9a, 0x28, 0x61, 0x66, 0xe4,
0x21, 0x34, 0x84, 0x0e, 0xa3, 0x44, 0x6a, 0xee, 0x93, 0x50, 0x17, 0xfa, 0xd0, 0x8a, 0x96, 0x57,
0xa8, 0x5f, 0x08, 0xcc, 0xd5, 0xae, 0x83, 0xea, 0x79, 0x50, 0x1f, 0x40, 0x97, 0xa7, 0xec, 0x22,
0xe1, 0x45, 0x6a, 0x71, 0xb3, 0x0d, 0xda, 0x71, 0xea, 0x3c, 0xa3, 0xf6, 0xdc, 0x78, 0x60, 0xe4,
0x5a, 0x53, 0x88, 0x5c, 0xc6, 0xfd, 0x36, 0x28, 0x71, 0x36, 0xdf, 0xb5, 0x3e, 0xb5, 0x16, 0xf2,
0x7d, 0x78, 0x70, 0x63, 0x46, 0xb1, 0x84, 0xdb, 0xec, 0xe6, 0xd2, 0xa4, 0x62, 0xa5, 0xef, 0xc2,
0xd6, 0x8d, 0x79, 0xee, 0x24, 0x18, 0x6c, 0x0b, 0x0d, 0xba, 0xb1, 0x34, 0xed, 0xd0, 0xd9, 0xc8,
0xc7, 0xf0, 0xf8, 0xc6, 0xac, 0x4b, 0x91, 0xc6, 0x61, 0xc6, 0xb4, 0xb6, 0xe7, 0x0a, 0x9b, 0x47,
0x83, 0x3e, 0x5c, 0x9a, 0xfb, 0x89, 0x48, 0xe3, 0x53, 0x0f, 0xb0, 0x4c, 0xb9, 0xe1, 0x60, 0x92,
0x25, 0x92, 0xc5, 0xd8, 0x5e, 0x1a, 0x74, 0x7d, 0x69, 0xe6, 0x39, 0x9a, 0xc8, 0x33, 0xb8, 0x3f,
0x66, 0xd7, 0xf3, 0x8a, 0x6a, 0xf1, 0xda, 0x75, 0x9c, 0x1a, 0xed, 0x8e, 0xd9, 0x75, 0x5e, 0xc8,
0x33, 0xf1, 0x1a, 0x1b, 0x4f, 0x81, 0x63, 0x49, 0x22, 0x5f, 0xf1, 0x38, 0xe4, 0xd7, 0xf6, 0x2a,
0xb3, 0xe7, 0x9d, 0xe4, 0xb6, 0x03, 0x67, 0x3a, 0xbe, 0x36, 0xe4, 0x7d, 0xe8, 0xb8, 0x3e, 0xa2,
0xf8, 0x17, 0x13, 0xa1, 0xb8, 0xeb, 0x39, 0x0d, 0xba, 0x8a, 0x5a, 0xea, 0x95, 0xc1, 0xdf, 0x4a,
0xd0, 0x38, 0xe3, 0xc6, 0x88, 0x74, 0xa8, 0xc9, 0xb7, 0x61, 0x45, 0x63, 0x3b, 0x47, 0x46, 0xb4,
0xf6, 0x37, 0x96, 0x2f, 0x1a, 0xd7, 0xea, 0xa9, 0xc7, 0x58, 0xf4, 0x25, 0x1e, 0x7d, 0x64, 0xc7,
0x2d, 0xb4, 0x6b, 0x0b, 0xd4, 0x63, 0xc8, 0x3e, 0x34, 0xb4, 0xe7, 0x1e, 0x92, 0xa4, 0xb5, 0xbf,
0x75, 0xc3, 0xbb, 0xb7, 0xd2, 0x02, 0x47, 0x06, 0x50, 0x8f, 0xdd, 0x19, 0x46, 0xa6, 0xb4, 0xf6,
0x37, 0x97, 0xa7, 0xf8, 0x03, 0x4e, 0x73, 0x54, 0xf0, 0xfb, 0x32, 0xb4, 0x8f, 0xd3, 0xe9, 0x11,
0xcf, 0x78, 0x1a, 0xdb, 0xc2, 0xe6, 0xaf, 0x95, 0xd2, 0xc2, 0x6b, 0xe5, 0xc6, 0x05, 0x53, 0xbe,
0x7d, 0xc1, 0x3c, 0x85, 0xb6, 0xd0, 0xa1, 0x48, 0xb5, 0x61, 0x49, 0xc2, 0x63, 0x4f, 0xea, 0x96,
0xd0, 0x27, 0xb9, 0xca, 0x76, 0x3b, 0xae, 0x94, 0x54, 0xf9, 0x93, 0x07, 0x05, 0x7c, 0x67, 0x8c,
0x78, 0x74, 0xe5, 0x9e, 0x09, 0xb5, 0x77, 0x7e, 0x67, 0xb8, 0x39, 0x07, 0xc6, 0x5e, 0x56, 0xd1,
0x38, 0xf6, 0x57, 0x98, 0x1d, 0xda, 0x0e, 0x2d, 0xf4, 0xbc, 0x88, 0x8e, 0x89, 0x20, 0x74, 0x5e,
0xc1, 0xc5, 0xe6, 0xde, 0x58, 0x6a, 0xee, 0xc1, 0x47, 0x50, 0x3d, 0x4e, 0xa7, 0x9a, 0xec, 0x42,
0x95, 0xa7, 0x53, 0xed, 0x5f, 0x0f, 0x45, 0x99, 0x16, 0x13, 0x45, 0x11, 0x11, 0xfc, 0xae, 0x02,
0x35, 0x7b, 0xbc, 0xb5, 0x7d, 0x9a, 0xdd, 0xe8, 0x92, 0x15, 0xda, 0x9c, 0x14, 0x9d, 0xf1, 0x7d,
0xe8, 0x14, 0x7c, 0x74, 0x90, 0x32, 0x42, 0x56, 0x73, 0x6d, 0x01, 0xcb, 0x1f, 0x34, 0x1e, 0x56,
0x71, 0xb0, 0x5c, 0xeb, 0x60, 0xdf, 0x84, 0x55, 0xa6, 0x8c, 0x88, 0xec, 0xf1, 0x41, 0x54, 0x15,
0x51, 0x6d, 0xaf, 0x2c, 0x40, 0xfe, 0x28, 0x7b, 0x50, 0xcd, 0x81, 0xbc, 0xd2, 0x81, 0x9e, 0x42,
0xfb, 0x82, 0xa5, 0x69, 0x11, 0xf8, 0x0a, 0x62, 0x5a, 0x4e, 0xe7, 0x20, 0x1f, 0xc2, 0xda, 0xa5,
0x12, 0x3c, 0x8d, 0x13, 0x91, 0x5e, 0x79, 0x58, 0x1d, 0x61, 0xdd, 0xb9, 0xde, 0x41, 0x3b, 0x50,
0x96, 0xf9, 0x0b, 0xa1, 0x2c, 0x97, 0xee, 0xd1, 0xe6, 0xf2, 0x3d, 0x4a, 0xa0, 0x3a, 0x62, 0x7a,
0xe4, 0x1f, 0x02, 0x38, 0xb6, 0x1d, 0xf6, 0x62, 0x22, 0x92, 0xe2, 0xc5, 0xd8, 0xa4, 0x75, 0x94,
0x0f, 0x30, 0x4c, 0xc5, 0x33, 0xa9, 0xf2, 0xad, 0xb4, 0x5d, 0x98, 0x4e, 0x87, 0x6b, 0x07, 0xbf,
0x86, 0xfa, 0xe1, 0xe9, 0xf9, 0x49, 0x7a, 0x29, 0x2d, 0xd7, 0x22, 0xa9, 0xb8, 0xf6, 0xaf, 0x38,
0x27, 0xd8, 0x0a, 0x8d, 0x65, 0xcc, 0x13, 0x77, 0x73, 0x3b, 0x16, 0x37, 0x51, 0x83, 0x17, 0xf7,
0x1a, 0x54, 0xc6, 0xa3, 0xd7, 0x98, 0xef, 0x32, 0xb5, 0x43, 0x1b, 0x7d, 0xc6, 0x55, 0x94, 0xdf,
0x33, 0x65, 0x9a, 0x8b, 0xc1, 0x97, 0x25, 0x80, 0x9f, 0xf2, 0xb1, 0x54, 0xb3, 0x7c, 0x3d, 0x23,
0x0d, 0x4b, 0x7c, 0xd9, 0x9d, 0x80, 0xf7, 0xf5, 0x94, 0x89, 0xc4, 0x36, 0x32, 0x5f, 0xed, 0xb9,
0xc2, 0x26, 0x60, 0xa2, 0xfd, 0x51, 0xa9, 0x50, 0x1c, 0x5b, 0xdd, 0xa5, 0xe2, 0xdc, 0x57, 0x13,
0xc7, 0x8b, 0x41, 0xd4, 0x96, 0x83, 0xf8, 0x0d, 0x34, 0x8e, 0x84, 0xbe, 0xc2, 0x08, 0x1e, 0x41,
0x33, 0x16, 0xfa, 0x2a, 0x5c, 0x38, 0xbb, 0x0d, 0xab, 0xf8, 0xcc, 0x7f, 0x6d, 0xb8, 0xf0, 0xca,
0x8b, 0xe1, 0xfd, 0xff, 0x01, 0xfc, 0xb6, 0x04, 0x70, 0xc4, 0xa7, 0x22, 0xe2, 0x18, 0xc3, 0x53,
0xa8, 0x44, 0xd9, 0xc4, 0x77, 0xc2, 0x6e, 0xd1, 0x78, 0x5c, 0x4d, 0xa8, 0xb5, 0x91, 0x67, 0xb0,
0x32, 0xc6, 0xb4, 0xf9, 0x0e, 0x48, 0x72, 0xd4, 0x3c, 0x99, 0xd4, 0x23, 0xc8, 0x7b, 0x50, 0xb5,
0x3b, 0xe8, 0x55, 0xf0, 0x10, 0xae, 0xe5, 0xc8, 0x7c, 0xcb, 0x14, 0xad, 0xfb, 0x7f, 0xad, 0x42,
0xd3, 0xf5, 0xb6, 0x83, 0xd3, 0x13, 0xf2, 0x33, 0x68, 0xbd, 0xe4, 0xa6, 0x68, 0xcf, 0x5b, 0xb7,
0x3a, 0xc9, 0xb1, 0xfd, 0x92, 0xeb, 0x17, 0xce, 0x72, 0x64, 0xd0, 0xfb, 0xf2, 0xef, 0xff, 0xfe,
0x63, 0x99, 0x90, 0xb5, 0x81, 0xff, 0xda, 0xd4, 0xb9, 0x0f, 0x0a, 0xed, 0x73, 0xfc, 0x28, 0xf1,
0x1f, 0x7d, 0xdd, 0xe5, 0x8e, 0xaa, 0xfb, 0x77, 0x2c, 0x12, 0x3c, 0x44, 0x97, 0xeb, 0xfd, 0xce,
0x60, 0xe9, 0x03, 0xf6, 0x87, 0xa5, 0x67, 0xe4, 0x1c, 0x60, 0xfe, 0x6d, 0x43, 0x1e, 0xe6, 0x1e,
0x6f, 0x7d, 0xef, 0xf4, 0x6f, 0x2e, 0x16, 0x3c, 0x42, 0xa7, 0x9b, 0x64, 0x7d, 0xd9, 0xe9, 0x20,
0x11, 0xda, 0x90, 0x9f, 0x40, 0xc3, 0xee, 0x1e, 0xdb, 0xd1, 0x5d, 0x5b, 0x5f, 0x2d, 0xb6, 0x6e,
0x61, 0xc1, 0x26, 0xfa, 0xeb, 0x92, 0xd5, 0x62, 0xdf, 0x38, 0xfb, 0x18, 0xea, 0x2f, 0xb9, 0xc1,
0x5e, 0x78, 0x97, 0xa3, 0xf6, 0x42, 0x57, 0xd4, 0xc1, 0x06, 0xfa, 0xe9, 0x90, 0x76, 0xee, 0xc7,
0x76, 0x47, 0xf2, 0x0b, 0x58, 0x75, 0xb9, 0x3b, 0x13, 0x86, 0x8f, 0x59, 0x76, 0xa7, 0xb3, 0xbb,
0x72, 0xf8, 0x00, 0xdd, 0xde, 0xef, 0x77, 0x8b, 0xf0, 0xbc, 0xa3, 0x33, 0x58, 0x7d, 0xc9, 0xcd,
0x02, 0xf9, 0xee, 0xf2, 0x5c, 0x30, 0x6c, 0x8e, 0x0d, 0xb6, 0xd0, 0xeb, 0x1a, 0x29, 0x2a, 0x13,
0xa3, 0xed, 0xc5, 0xf7, 0xfe, 0xf2, 0x66, 0xbb, 0xf4, 0xf5, 0x9b, 0xed, 0xd2, 0xbf, 0xde, 0x6c,
0x97, 0xbe, 0x7a, 0xbb, 0x7d, 0xef, 0xeb, 0xb7, 0xdb, 0xf7, 0xfe, 0xf1, 0x76, 0xfb, 0x1e, 0xf8,
0xdf, 0x0d, 0xa7, 0xa5, 0x5f, 0xdd, 0x1f, 0x4b, 0xc5, 0x63, 0x19, 0xf9, 0xa9, 0x3f, 0x9a, 0x3e,
0xbf, 0x58, 0xc1, 0x25, 0xbf, 0xf3, 0xbf, 0x00, 0x00, 0x00, 0xff, 0xff, 0xee, 0x28, 0x27, 0x2b,
0xa9, 0x10, 0x00, 0x00,
0xa5, 0xcf, 0xfd, 0x7a, 0x59, 0xd0, 0xbb, 0x23, 0x89, 0xf5, 0x6a, 0xb9, 0x47, 0x52, 0x8a, 0x95,
0x97, 0xa2, 0xf7, 0x54, 0xa0, 0x2f, 0x57, 0x14, 0xe8, 0xdf, 0xd4, 0xa2, 0x2f, 0x07, 0xf4, 0xe5,
0xde, 0x5a, 0x24, 0xed, 0xdf, 0xd1, 0x82, 0x43, 0xee, 0x4a, 0xb2, 0x61, 0xe0, 0x80, 0x7b, 0xe3,
0xcc, 0xfc, 0x38, 0xe4, 0xcc, 0xfc, 0x38, 0xe4, 0x2e, 0xd9, 0xe4, 0x99, 0x18, 0xcc, 0x9e, 0x0f,
0x22, 0x99, 0x0e, 0xc5, 0x68, 0x2f, 0x53, 0xd2, 0x48, 0xba, 0xc6, 0x33, 0xb1, 0x37, 0x7b, 0xde,
0x7f, 0x32, 0x92, 0x72, 0x94, 0xc0, 0x00, 0xb5, 0x17, 0xd3, 0xe1, 0xc0, 0x88, 0x09, 0x68, 0xc3,
0x27, 0x99, 0x03, 0xf6, 0xb7, 0x46, 0x72, 0x24, 0x71, 0x38, 0xb0, 0x23, 0xaf, 0x7d, 0xec, 0xa7,
0x59, 0xd7, 0x3c, 0x4d, 0xa5, 0xe1, 0x46, 0xc8, 0x54, 0x7b, 0xeb, 0xa3, 0xeb, 0x4e, 0x61, 0x92,
0x99, 0xb9, 0x33, 0x06, 0xff, 0x2d, 0x93, 0xb5, 0x43, 0xdc, 0x0a, 0xed, 0x90, 0xb2, 0x88, 0x7b,
0xa5, 0x9d, 0xd2, 0x6e, 0x85, 0x95, 0x45, 0x4c, 0xb7, 0x48, 0x2d, 0xe1, 0x17, 0x90, 0xf4, 0xca,
0x3b, 0xa5, 0xdd, 0x26, 0x73, 0x02, 0xa5, 0xa4, 0x9a, 0xf2, 0x09, 0xf4, 0x2a, 0xa8, 0xc4, 0xb1,
0x45, 0xce, 0x78, 0x32, 0x85, 0x5e, 0xd5, 0x21, 0x51, 0xa0, 0x3b, 0xa4, 0x95, 0x25, 0x3c, 0x82,
0xb1, 0x4c, 0x62, 0x50, 0xbd, 0x1a, 0xda, 0x96, 0x55, 0xf4, 0x5b, 0x84, 0x88, 0x34, 0x9b, 0x9a,
0xd0, 0xcc, 0x33, 0xe8, 0xad, 0x21, 0xa0, 0x89, 0x9a, 0x4f, 0xe7, 0x19, 0xd0, 0x3e, 0x69, 0x44,
0xdc, 0xc0, 0x48, 0xaa, 0x79, 0xaf, 0x8e, 0xc6, 0x42, 0xb6, 0xdb, 0xd0, 0x52, 0x99, 0x5e, 0x63,
0xa7, 0xb4, 0x5b, 0x63, 0x38, 0xa6, 0x3d, 0x52, 0x97, 0x19, 0x46, 0xde, 0x6b, 0x22, 0x3c, 0x17,
0xe9, 0x87, 0x84, 0x44, 0x0a, 0xb8, 0x81, 0x38, 0xe4, 0xa6, 0x47, 0x76, 0x4a, 0xbb, 0xad, 0xfd,
0xfe, 0x9e, 0xcb, 0xcb, 0x5e, 0x9e, 0x97, 0xbd, 0x4f, 0xf3, 0x64, 0xbf, 0xa8, 0x7e, 0xf1, 0xaf,
0x27, 0x25, 0xd6, 0xf4, 0x73, 0x0e, 0x8c, 0x75, 0x30, 0xcd, 0xe2, 0xdc, 0x41, 0xeb, 0xeb, 0x3a,
0xf0, 0x73, 0x0e, 0x4c, 0x30, 0x20, 0x77, 0x3f, 0x16, 0xda, 0xb8, 0x54, 0x33, 0xf8, 0x6c, 0x0a,
0xda, 0xac, 0x04, 0x58, 0xda, 0xa9, 0x2c, 0x07, 0x18, 0x3c, 0x27, 0x75, 0x07, 0xd6, 0xf4, 0x3b,
0x64, 0xcd, 0xb1, 0x05, 0x41, 0xad, 0xfd, 0xce, 0x9e, 0xa3, 0xcb, 0x9e, 0xf7, 0xe6, 0xad, 0x81,
0x20, 0xeb, 0x4e, 0x73, 0xc8, 0x33, 0x13, 0x8d, 0x39, 0xbd, 0x4f, 0xd6, 0x12, 0x48, 0x47, 0x66,
0x8c, 0x55, 0xad, 0x31, 0x2f, 0xd9, 0x7a, 0xbd, 0x12, 0xb1, 0x19, 0x63, 0x65, 0x6b, 0xcc, 0x09,
0x16, 0x3d, 0x06, 0x31, 0x1a, 0x1b, 0xac, 0x6d, 0x8d, 0x79, 0xc9, 0xa6, 0x1a, 0xeb, 0xe3, 0x8a,
0x8b, 0xe3, 0xe0, 0x7f, 0x15, 0xd2, 0x76, 0x6b, 0x9d, 0xcd, 0xb5, 0x81, 0x89, 0x9d, 0x1c, 0xcb,
0x09, 0x17, 0x29, 0x2e, 0xd5, 0x64, 0x5e, 0xb2, 0x4b, 0x19, 0x61, 0x12, 0xc8, 0x49, 0x84, 0x82,
0x0d, 0xfc, 0x12, 0xe6, 0xaf, 0xa4, 0x8a, 0xb5, 0x27, 0x52, 0x21, 0x5b, 0xda, 0xc4, 0xa0, 0x23,
0x25, 0xb0, 0x76, 0x7e, 0xd5, 0x65, 0x95, 0xdd, 0x50, 0x22, 0x47, 0xd2, 0x33, 0x0a, 0xc7, 0xb6,
0xf6, 0x43, 0x3e, 0x13, 0x91, 0x4c, 0x3d, 0x8f, 0x72, 0x91, 0x6e, 0x90, 0x8a, 0x88, 0x32, 0x4f,
0x20, 0x3b, 0xa4, 0x8f, 0x49, 0x93, 0xa7, 0x3c, 0x99, 0x1b, 0x11, 0x69, 0x24, 0x50, 0x93, 0x2d,
0x14, 0x76, 0x6f, 0x5a, 0x18, 0x40, 0x92, 0x3b, 0x1a, 0x15, 0x32, 0xfd, 0x80, 0x6c, 0x45, 0x32,
0x9b, 0x2b, 0x9b, 0x97, 0x50, 0x1b, 0xae, 0x4c, 0x38, 0x07, 0xae, 0x90, 0x51, 0x4d, 0x46, 0x0b,
0xdb, 0x99, 0x35, 0xfd, 0x06, 0xb8, 0xa2, 0x03, 0xb2, 0xa9, 0x60, 0x24, 0xb4, 0x01, 0x15, 0x5e,
0xf0, 0xe8, 0x72, 0xa4, 0xe4, 0x34, 0x8d, 0x91, 0x41, 0x4d, 0x46, 0x73, 0xd3, 0x8b, 0xc2, 0x42,
0xdf, 0x27, 0x1b, 0x89, 0x1c, 0x89, 0x74, 0x19, 0xdd, 0x46, 0x74, 0x17, 0xf5, 0x4b, 0xd0, 0xf7,
0x48, 0x57, 0x41, 0x24, 0x27, 0x13, 0x48, 0xe3, 0xd0, 0x25, 0x73, 0x1d, 0x59, 0xd4, 0x29, 0xd4,
0xbf, 0xc2, 0x94, 0xf6, 0x48, 0x7d, 0x06, 0x4a, 0xdb, 0x74, 0x76, 0x5c, 0x72, 0xbc, 0x48, 0x9f,
0x90, 0x56, 0xa4, 0x20, 0x16, 0x26, 0xc4, 0x78, 0xbb, 0x68, 0x25, 0x4e, 0xf5, 0x89, 0x8d, 0xf8,
0x01, 0xa9, 0x6b, 0x88, 0x42, 0x9b, 0xc1, 0x0d, 0x57, 0x58, 0x0d, 0xd1, 0x49, 0x94, 0x05, 0x7f,
0x2d, 0xe5, 0x0c, 0xf8, 0x48, 0x4a, 0x03, 0xca, 0x56, 0x9a, 0x5f, 0xc8, 0xa9, 0xf1, 0x04, 0x70,
0x82, 0x5d, 0x3a, 0x92, 0xa9, 0xe1, 0x91, 0xf1, 0x0c, 0xc8, 0x45, 0xac, 0xc2, 0x48, 0x01, 0x4c,
0x20, 0x35, 0x9e, 0x04, 0x0b, 0x85, 0xb5, 0x16, 0xd9, 0xf4, 0x1c, 0x58, 0x28, 0x6c, 0x8d, 0x86,
0x00, 0xb1, 0x4d, 0x91, 0x67, 0x41, 0x21, 0x07, 0x7f, 0x2e, 0xe7, 0xc7, 0xe0, 0x48, 0xe8, 0x2c,
0xe1, 0x73, 0xfa, 0x23, 0xd2, 0xd3, 0x63, 0xf9, 0x2a, 0x2c, 0x0a, 0x31, 0xd5, 0xa0, 0xc2, 0x48,
0x4e, 0x53, 0xb7, 0xd9, 0x06, 0xbb, 0x67, 0xed, 0xcc, 0x9b, 0xcf, 0x35, 0xa8, 0x43, 0x6b, 0xa4,
0xfb, 0x04, 0x0d, 0xa1, 0x48, 0x63, 0xb8, 0x0a, 0xfd, 0xd1, 0x14, 0xa0, 0x31, 0x94, 0x06, 0xdb,
0xb4, 0xc6, 0x13, 0x6b, 0x3b, 0x2c, 0x4c, 0xf4, 0x1d, 0xd2, 0xc9, 0xf8, 0x08, 0x74, 0x98, 0x81,
0x0a, 0x15, 0xf0, 0xd8, 0x9f, 0xa6, 0x36, 0x6a, 0x4f, 0x41, 0x31, 0xe0, 0xb1, 0xa5, 0xc5, 0x0a,
0x91, 0x8c, 0x4b, 0x43, 0xf5, 0x26, 0x8f, 0x9c, 0x85, 0xfe, 0x94, 0xf4, 0x71, 0x2b, 0xb1, 0x8c,
0xa6, 0x56, 0x11, 0x2e, 0x1d, 0x08, 0x8d, 0x39, 0x68, 0x30, 0x8c, 0xf2, 0xc8, 0x03, 0x8e, 0x96,
0xec, 0xc1, 0x57, 0x55, 0xd2, 0xf1, 0xc7, 0x15, 0xa2, 0xa9, 0x12, 0x66, 0x4e, 0x1f, 0x92, 0x86,
0xd0, 0x61, 0x94, 0x48, 0x0d, 0x3e, 0x09, 0x75, 0xa1, 0x0f, 0xad, 0x68, 0x79, 0x85, 0xfa, 0xa5,
0x8d, 0xb9, 0xda, 0x75, 0x50, 0xbd, 0xd8, 0xd4, 0x7b, 0xa4, 0x0b, 0x29, 0xbf, 0x48, 0xa0, 0x48,
0x2d, 0x06, 0xdb, 0x60, 0x1d, 0xa7, 0xce, 0x33, 0x6a, 0xcf, 0x8d, 0x07, 0x46, 0xae, 0x35, 0x85,
0xc8, 0x65, 0x8c, 0xb7, 0xc1, 0xa8, 0xb3, 0xf9, 0xae, 0xf5, 0xb1, 0xb5, 0xd0, 0x1f, 0x92, 0x07,
0xd7, 0x66, 0x14, 0x4b, 0xb8, 0x60, 0xef, 0xad, 0x4c, 0x2a, 0x56, 0xfa, 0x3e, 0xb9, 0x7f, 0x6d,
0x9e, 0x3b, 0x09, 0x06, 0xdb, 0x42, 0x83, 0x6d, 0xad, 0x4c, 0x3b, 0x74, 0x36, 0xfa, 0x21, 0x79,
0x7c, 0x6d, 0xd6, 0x50, 0xa4, 0x71, 0x98, 0x71, 0xad, 0xed, 0xb9, 0xc2, 0xe6, 0xd1, 0x60, 0x0f,
0x57, 0xe6, 0x7e, 0x24, 0xd2, 0xf8, 0xd4, 0x03, 0x2c, 0x53, 0xae, 0x39, 0x98, 0x66, 0x89, 0xe4,
0x31, 0xb6, 0x97, 0x06, 0xdb, 0x5c, 0x99, 0x79, 0x8e, 0x26, 0xfa, 0x8c, 0xdc, 0x9d, 0xf0, 0xab,
0x45, 0x45, 0xb5, 0x78, 0xed, 0x3a, 0x4e, 0x8d, 0x75, 0x27, 0xfc, 0x2a, 0x2f, 0xe4, 0x99, 0x78,
0x8d, 0x8d, 0xa7, 0xc0, 0xf1, 0x24, 0x91, 0xaf, 0x20, 0x0e, 0xe1, 0xca, 0x5e, 0x65, 0xf6, 0xbc,
0xd3, 0xdc, 0x76, 0xe0, 0x4c, 0xc7, 0x57, 0x86, 0xbe, 0x4b, 0x3a, 0xae, 0x8f, 0x28, 0xf8, 0x6c,
0x2a, 0x14, 0xb8, 0x9e, 0xd3, 0x60, 0xeb, 0xa8, 0x65, 0x5e, 0xb9, 0x14, 0xf9, 0x0c, 0x94, 0x18,
0xce, 0x17, 0x87, 0x04, 0x26, 0x5c, 0x24, 0xd8, 0x7a, 0x8a, 0xc8, 0x7f, 0x89, 0x90, 0x3c, 0xd7,
0xc7, 0x16, 0x10, 0xfc, 0xa3, 0x44, 0x1a, 0x67, 0x60, 0x8c, 0x48, 0x47, 0x9a, 0x7e, 0x97, 0xac,
0x69, 0xbc, 0x0f, 0x90, 0x52, 0xad, 0xfd, 0xad, 0xd5, 0x9b, 0xca, 0xdd, 0x15, 0xcc, 0x63, 0x2c,
0x7a, 0x88, 0xbd, 0x03, 0xe9, 0x75, 0x03, 0xed, 0xfa, 0x0a, 0xf3, 0x18, 0xba, 0x4f, 0x1a, 0xda,
0x93, 0x17, 0x59, 0xd6, 0xda, 0xbf, 0x7f, 0xcd, 0xbb, 0xb7, 0xb2, 0x02, 0x47, 0x07, 0xa4, 0x1e,
0xbb, 0x26, 0x80, 0x54, 0x6b, 0xed, 0xdf, 0x5b, 0x9d, 0xe2, 0x3b, 0x04, 0xcb, 0x51, 0xc1, 0x9f,
0xca, 0xa4, 0x7d, 0x9c, 0xce, 0x8e, 0x20, 0x83, 0x34, 0xb6, 0xcc, 0xc8, 0x9f, 0x3b, 0xa5, 0xa5,
0xe7, 0xce, 0xb5, 0x1b, 0xaa, 0x7c, 0xf3, 0x86, 0x7a, 0x4a, 0xda, 0x42, 0x87, 0x22, 0xd5, 0x86,
0x27, 0x09, 0xc4, 0xfe, 0x54, 0xb4, 0x84, 0x3e, 0xc9, 0x55, 0xb6, 0x5d, 0x82, 0x52, 0x52, 0xe5,
0x6f, 0x26, 0x14, 0xf0, 0xa1, 0x32, 0x86, 0xe8, 0xd2, 0xbd, 0x33, 0x6a, 0x5f, 0xfb, 0xa1, 0xe2,
0xe6, 0x1c, 0x18, 0x7b, 0xdb, 0x45, 0x93, 0xd8, 0xdf, 0x81, 0x76, 0x68, 0x5b, 0xbc, 0xd0, 0x0b,
0x16, 0x38, 0x2a, 0x13, 0xa1, 0x0b, 0x0a, 0x2c, 0xdd, 0x0e, 0x8d, 0x95, 0xdb, 0x21, 0xf8, 0x80,
0x54, 0x8f, 0xd3, 0x99, 0xa6, 0xbb, 0xa4, 0x0a, 0xe9, 0x4c, 0xfb, 0xe7, 0x47, 0x51, 0xa6, 0xe5,
0x44, 0x31, 0x44, 0x04, 0x7f, 0xac, 0x90, 0x9a, 0xed, 0x0f, 0xda, 0xbe, 0xed, 0xae, 0xb5, 0xd9,
0x0a, 0x6b, 0x4e, 0x8b, 0xd6, 0xfa, 0x2e, 0xe9, 0x14, 0x84, 0x76, 0x90, 0x32, 0x42, 0xd6, 0x73,
0x6d, 0x01, 0xcb, 0x5f, 0x44, 0x1e, 0x56, 0x71, 0xb0, 0x5c, 0xeb, 0x60, 0xdf, 0x26, 0xeb, 0x5c,
0x19, 0x11, 0xd9, 0xf3, 0x87, 0xa8, 0x2a, 0xa2, 0xda, 0x5e, 0x59, 0x80, 0x7c, 0x2f, 0xf0, 0xa0,
0x9a, 0x03, 0x79, 0xa5, 0x03, 0x3d, 0x25, 0xed, 0x0b, 0x9e, 0xa6, 0xc5, 0xc6, 0xd7, 0x10, 0xd3,
0x72, 0x3a, 0x07, 0x79, 0x9f, 0x6c, 0x0c, 0x95, 0x80, 0x34, 0x4e, 0x44, 0x7a, 0xe9, 0x61, 0x75,
0x84, 0x75, 0x17, 0x7a, 0x07, 0xed, 0x90, 0xb2, 0xcc, 0x9f, 0x18, 0x65, 0xb9, 0x72, 0x11, 0x37,
0x57, 0x2f, 0x62, 0x4a, 0xaa, 0x63, 0xae, 0xc7, 0xfe, 0x25, 0x81, 0x63, 0xdb, 0xa2, 0x2f, 0xa6,
0x22, 0x29, 0x9e, 0x9c, 0x4d, 0x56, 0x47, 0xf9, 0x00, 0xb7, 0xa9, 0x20, 0x93, 0x2a, 0x0f, 0xa5,
0xed, 0xb6, 0xe9, 0x74, 0xb8, 0x76, 0xf0, 0x3b, 0x52, 0x3f, 0x3c, 0x3d, 0x3f, 0x49, 0x87, 0xd2,
0x72, 0x2d, 0x92, 0x0a, 0xb4, 0x7f, 0x06, 0x3a, 0xc1, 0x56, 0x68, 0x22, 0x63, 0x48, 0xdc, 0xd5,
0xef, 0x58, 0xdc, 0x44, 0x0d, 0xde, 0xfc, 0x1b, 0xa4, 0x32, 0x19, 0xbf, 0xc6, 0x7c, 0x97, 0x99,
0x1d, 0xda, 0xdd, 0x67, 0xa0, 0xa2, 0xfc, 0xa2, 0x2a, 0xb3, 0x5c, 0x0c, 0x3e, 0x2f, 0x11, 0xf2,
0x73, 0x98, 0x48, 0x35, 0xcf, 0xd7, 0x33, 0xd2, 0xf0, 0xc4, 0x97, 0xdd, 0x09, 0x78, 0xe1, 0xcf,
0xb8, 0x48, 0x6c, 0x27, 0xf1, 0xd5, 0x5e, 0x28, 0x6c, 0x02, 0xa6, 0xda, 0x1f, 0x95, 0x0a, 0xc3,
0xb1, 0xd5, 0x0d, 0x15, 0x80, 0xaf, 0x26, 0x8e, 0x97, 0x37, 0x51, 0x5b, 0xdd, 0xc4, 0xef, 0x49,
0xe3, 0x48, 0xe8, 0x4b, 0xdc, 0xc1, 0x23, 0xd2, 0x8c, 0x85, 0xbe, 0x0c, 0x97, 0xce, 0x6e, 0xc3,
0x2a, 0x3e, 0xf1, 0x9f, 0x2b, 0x6e, 0x7b, 0xe5, 0xe5, 0xed, 0x7d, 0xf3, 0x0d, 0xfc, 0xa1, 0x44,
0xc8, 0x11, 0xcc, 0x44, 0x04, 0xb8, 0x87, 0xa7, 0xa4, 0x12, 0x65, 0x53, 0xdf, 0x09, 0xbb, 0x45,
0xe3, 0x71, 0x35, 0x61, 0xd6, 0x46, 0x9f, 0x91, 0xb5, 0x09, 0xa6, 0xcd, 0x77, 0x40, 0x9a, 0xa3,
0x16, 0xc9, 0x64, 0x1e, 0x41, 0xdf, 0x21, 0x55, 0x1b, 0x41, 0xaf, 0x82, 0x87, 0x70, 0x23, 0x47,
0xe6, 0x21, 0x33, 0xb4, 0xee, 0xff, 0xbd, 0x4a, 0x9a, 0xae, 0xb7, 0x1d, 0x9c, 0x9e, 0xd0, 0x5f,
0x90, 0xd6, 0x4b, 0x30, 0x45, 0x7b, 0xbe, 0x7f, 0xa3, 0x93, 0x1c, 0xdb, 0x4f, 0xc1, 0x7e, 0xe1,
0x2c, 0x47, 0x06, 0xbd, 0xcf, 0xff, 0xf9, 0x9f, 0xbf, 0x94, 0x29, 0xdd, 0x18, 0xf8, 0xcf, 0x55,
0x9d, 0xfb, 0x60, 0xa4, 0x7d, 0x8e, 0x5f, 0x35, 0xfe, 0xab, 0xb1, 0xbb, 0xda, 0x51, 0x75, 0xff,
0x96, 0x45, 0x82, 0x87, 0xe8, 0x72, 0xb3, 0xdf, 0x19, 0xac, 0x7c, 0x01, 0xff, 0xb8, 0xf4, 0x8c,
0x9e, 0x13, 0xb2, 0xf8, 0x38, 0xa2, 0x0f, 0x73, 0x8f, 0x37, 0x3e, 0x98, 0xfa, 0xd7, 0x17, 0x0b,
0x1e, 0xa1, 0xd3, 0x7b, 0x74, 0x73, 0xd5, 0xe9, 0x20, 0x11, 0xda, 0xd0, 0x9f, 0x91, 0x86, 0x8d,
0x1e, 0xdb, 0xd1, 0x6d, 0xa1, 0xaf, 0x17, 0xa1, 0x5b, 0x58, 0x70, 0x0f, 0xfd, 0x75, 0xe9, 0x7a,
0x11, 0x37, 0xce, 0x3e, 0x26, 0xf5, 0x97, 0x60, 0xb0, 0x17, 0xde, 0xe6, 0xa8, 0xbd, 0xd4, 0x15,
0x75, 0xb0, 0x85, 0x7e, 0x3a, 0xb4, 0x9d, 0xfb, 0xb1, 0xdd, 0x91, 0xfe, 0x9a, 0xac, 0xbb, 0xdc,
0x9d, 0x09, 0x03, 0x13, 0x9e, 0xdd, 0xea, 0xec, 0xb6, 0x1c, 0x3e, 0x40, 0xb7, 0x77, 0xfb, 0xdd,
0x62, 0x7b, 0xde, 0xd1, 0x19, 0x59, 0x7f, 0x09, 0x66, 0x89, 0x7c, 0xb7, 0x79, 0x2e, 0x18, 0xb6,
0xc0, 0x06, 0xf7, 0xd1, 0xeb, 0x06, 0x2d, 0x2a, 0x13, 0xa3, 0xed, 0xc5, 0x0f, 0xfe, 0xf6, 0x66,
0xbb, 0xf4, 0xe5, 0x9b, 0xed, 0xd2, 0xbf, 0xdf, 0x6c, 0x97, 0xbe, 0x78, 0xbb, 0x7d, 0xe7, 0xcb,
0xb7, 0xdb, 0x77, 0xbe, 0x7a, 0xbb, 0x7d, 0x87, 0xf8, 0xff, 0x15, 0xa7, 0xa5, 0xdf, 0xde, 0x9d,
0x48, 0x05, 0xb1, 0x8c, 0xfc, 0xd4, 0x9f, 0xcc, 0x9e, 0x5f, 0xac, 0xe1, 0x92, 0xdf, 0xfb, 0x7f,
0x00, 0x00, 0x00, 0xff, 0xff, 0x24, 0x4d, 0x78, 0x92, 0xea, 0x10, 0x00, 0x00,
}
// Reference imports to suppress errors if they are not otherwise used.
@ -2340,6 +2349,16 @@ func (m *ConfigSecurity) MarshalToSizedBuffer(dAtA []byte) (int, error) {
_ = i
var l int
_ = l
if m.EnableVerifyRegisterEmail {
i--
if m.EnableVerifyRegisterEmail {
dAtA[i] = 1
} else {
dAtA[i] = 0
}
i--
dAtA[i] = 0x60
}
if m.LoginRequired {
i--
if m.LoginRequired {
@ -3225,6 +3244,9 @@ func (m *ConfigSecurity) Size() (n int) {
if m.LoginRequired {
n += 2
}
if m.EnableVerifyRegisterEmail {
n += 2
}
return n
}
@ -5350,6 +5372,26 @@ func (m *ConfigSecurity) Unmarshal(dAtA []byte) error {
}
}
m.LoginRequired = bool(v != 0)
case 12:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field EnableVerifyRegisterEmail", wireType)
}
var v int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowConfig
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
v |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
m.EnableVerifyRegisterEmail = bool(v != 0)
default:
iNdEx = preIndex
skippy, err := skipConfig(dAtA[iNdEx:])

@ -96,6 +96,7 @@ message ConfigSecurity {
int32 max_document_size = 9; //
repeated string document_allowed_ext = 10; //
bool login_required = 11; // 访
bool enable_verify_register_email = 12; //
}
//

@ -33,6 +33,31 @@ var _ = time.Kitchen
// proto package needs to be updated.
const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
type EmailCodeType int32
const (
EmailCodeType_EmailCodeTypeRegister EmailCodeType = 0
EmailCodeType_EmailCodeTypeLogin EmailCodeType = 1
)
var EmailCodeType_name = map[int32]string{
0: "EmailCodeTypeRegister",
1: "EmailCodeTypeLogin",
}
var EmailCodeType_value = map[string]int32{
"EmailCodeTypeRegister": 0,
"EmailCodeTypeLogin": 1,
}
func (x EmailCodeType) String() string {
return proto.EnumName(EmailCodeType_name, int32(x))
}
func (EmailCodeType) EnumDescriptor() ([]byte, []int) {
return fileDescriptor_b74e2e33d57193df, []int{0}
}
// 用户信息
type User struct {
LoginAt *time.Time `protobuf:"bytes,19,opt,name=login_at,json=loginAt,proto3,stdtime" json:"login_at,omitempty"`
@ -253,6 +278,7 @@ type RegisterAndLoginRequest struct {
Captcha string `protobuf:"bytes,3,opt,name=captcha,proto3" json:"captcha,omitempty"`
CaptchaId string `protobuf:"bytes,4,opt,name=captcha_id,json=captchaId,proto3" json:"captcha_id,omitempty"`
Email string `protobuf:"bytes,5,opt,name=email,proto3" json:"email,omitempty"`
Code string `protobuf:"bytes,6,opt,name=code,proto3" json:"code,omitempty"`
}
func (m *RegisterAndLoginRequest) Reset() { *m = RegisterAndLoginRequest{} }
@ -323,6 +349,81 @@ func (m *RegisterAndLoginRequest) GetEmail() string {
return ""
}
func (m *RegisterAndLoginRequest) GetCode() string {
if m != nil {
return m.Code
}
return ""
}
type SendEmailCodeRequest struct {
Email string `protobuf:"bytes,1,opt,name=email,proto3" json:"email,omitempty"`
Captcha string `protobuf:"bytes,2,opt,name=captcha,proto3" json:"captcha,omitempty"`
CaptchaId string `protobuf:"bytes,3,opt,name=captcha_id,json=captchaId,proto3" json:"captcha_id,omitempty"`
Type EmailCodeType `protobuf:"varint,4,opt,name=type,proto3,enum=api.v1.EmailCodeType" json:"type,omitempty"`
}
func (m *SendEmailCodeRequest) Reset() { *m = SendEmailCodeRequest{} }
func (m *SendEmailCodeRequest) String() string { return proto.CompactTextString(m) }
func (*SendEmailCodeRequest) ProtoMessage() {}
func (*SendEmailCodeRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_b74e2e33d57193df, []int{2}
}
func (m *SendEmailCodeRequest) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
}
func (m *SendEmailCodeRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
if deterministic {
return xxx_messageInfo_SendEmailCodeRequest.Marshal(b, m, deterministic)
} else {
b = b[:cap(b)]
n, err := m.MarshalToSizedBuffer(b)
if err != nil {
return nil, err
}
return b[:n], nil
}
}
func (m *SendEmailCodeRequest) XXX_Merge(src proto.Message) {
xxx_messageInfo_SendEmailCodeRequest.Merge(m, src)
}
func (m *SendEmailCodeRequest) XXX_Size() int {
return m.Size()
}
func (m *SendEmailCodeRequest) XXX_DiscardUnknown() {
xxx_messageInfo_SendEmailCodeRequest.DiscardUnknown(m)
}
var xxx_messageInfo_SendEmailCodeRequest proto.InternalMessageInfo
func (m *SendEmailCodeRequest) GetEmail() string {
if m != nil {
return m.Email
}
return ""
}
func (m *SendEmailCodeRequest) GetCaptcha() string {
if m != nil {
return m.Captcha
}
return ""
}
func (m *SendEmailCodeRequest) GetCaptchaId() string {
if m != nil {
return m.CaptchaId
}
return ""
}
func (m *SendEmailCodeRequest) GetType() EmailCodeType {
if m != nil {
return m.Type
}
return EmailCodeType_EmailCodeTypeRegister
}
// 查询验证码请求
type GetUserCaptchaRequest struct {
Type string `protobuf:"bytes,1,opt,name=type,proto3" json:"type,omitempty"`
@ -332,7 +433,7 @@ func (m *GetUserCaptchaRequest) Reset() { *m = GetUserCaptchaRequest{} }
func (m *GetUserCaptchaRequest) String() string { return proto.CompactTextString(m) }
func (*GetUserCaptchaRequest) ProtoMessage() {}
func (*GetUserCaptchaRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_b74e2e33d57193df, []int{2}
return fileDescriptor_b74e2e33d57193df, []int{3}
}
func (m *GetUserCaptchaRequest) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@ -378,7 +479,7 @@ func (m *LoginReply) Reset() { *m = LoginReply{} }
func (m *LoginReply) String() string { return proto.CompactTextString(m) }
func (*LoginReply) ProtoMessage() {}
func (*LoginReply) Descriptor() ([]byte, []int) {
return fileDescriptor_b74e2e33d57193df, []int{3}
return fileDescriptor_b74e2e33d57193df, []int{4}
}
func (m *LoginReply) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@ -430,7 +531,7 @@ func (m *DeleteUserRequest) Reset() { *m = DeleteUserRequest{} }
func (m *DeleteUserRequest) String() string { return proto.CompactTextString(m) }
func (*DeleteUserRequest) ProtoMessage() {}
func (*DeleteUserRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_b74e2e33d57193df, []int{4}
return fileDescriptor_b74e2e33d57193df, []int{5}
}
func (m *DeleteUserRequest) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@ -475,7 +576,7 @@ func (m *GetUserRequest) Reset() { *m = GetUserRequest{} }
func (m *GetUserRequest) String() string { return proto.CompactTextString(m) }
func (*GetUserRequest) ProtoMessage() {}
func (*GetUserRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_b74e2e33d57193df, []int{5}
return fileDescriptor_b74e2e33d57193df, []int{6}
}
func (m *GetUserRequest) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@ -524,7 +625,7 @@ func (m *FindPasswordRequest) Reset() { *m = FindPasswordRequest{} }
func (m *FindPasswordRequest) String() string { return proto.CompactTextString(m) }
func (*FindPasswordRequest) ProtoMessage() {}
func (*FindPasswordRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_b74e2e33d57193df, []int{6}
return fileDescriptor_b74e2e33d57193df, []int{7}
}
func (m *FindPasswordRequest) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@ -605,7 +706,7 @@ func (m *ListUserRequest) Reset() { *m = ListUserRequest{} }
func (m *ListUserRequest) String() string { return proto.CompactTextString(m) }
func (*ListUserRequest) ProtoMessage() {}
func (*ListUserRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_b74e2e33d57193df, []int{7}
return fileDescriptor_b74e2e33d57193df, []int{8}
}
func (m *ListUserRequest) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@ -707,7 +808,7 @@ func (m *ListUserReply) Reset() { *m = ListUserReply{} }
func (m *ListUserReply) String() string { return proto.CompactTextString(m) }
func (*ListUserReply) ProtoMessage() {}
func (*ListUserReply) Descriptor() ([]byte, []int) {
return fileDescriptor_b74e2e33d57193df, []int{8}
return fileDescriptor_b74e2e33d57193df, []int{9}
}
func (m *ListUserReply) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@ -762,7 +863,7 @@ func (m *GetUserCaptchaReply) Reset() { *m = GetUserCaptchaReply{} }
func (m *GetUserCaptchaReply) String() string { return proto.CompactTextString(m) }
func (*GetUserCaptchaReply) ProtoMessage() {}
func (*GetUserCaptchaReply) Descriptor() ([]byte, []int) {
return fileDescriptor_b74e2e33d57193df, []int{9}
return fileDescriptor_b74e2e33d57193df, []int{10}
}
func (m *GetUserCaptchaReply) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@ -830,7 +931,7 @@ func (m *UpdateUserPasswordRequest) Reset() { *m = UpdateUserPasswordReq
func (m *UpdateUserPasswordRequest) String() string { return proto.CompactTextString(m) }
func (*UpdateUserPasswordRequest) ProtoMessage() {}
func (*UpdateUserPasswordRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_b74e2e33d57193df, []int{10}
return fileDescriptor_b74e2e33d57193df, []int{11}
}
func (m *UpdateUserPasswordRequest) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@ -889,7 +990,7 @@ func (m *GetUserPermissionsReply) Reset() { *m = GetUserPermissionsReply
func (m *GetUserPermissionsReply) String() string { return proto.CompactTextString(m) }
func (*GetUserPermissionsReply) ProtoMessage() {}
func (*GetUserPermissionsReply) Descriptor() ([]byte, []int) {
return fileDescriptor_b74e2e33d57193df, []int{11}
return fileDescriptor_b74e2e33d57193df, []int{12}
}
func (m *GetUserPermissionsReply) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@ -938,7 +1039,7 @@ func (m *SetUserRequest) Reset() { *m = SetUserRequest{} }
func (m *SetUserRequest) String() string { return proto.CompactTextString(m) }
func (*SetUserRequest) ProtoMessage() {}
func (*SetUserRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_b74e2e33d57193df, []int{12}
return fileDescriptor_b74e2e33d57193df, []int{13}
}
func (m *SetUserRequest) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@ -1017,7 +1118,7 @@ func (m *Dynamic) Reset() { *m = Dynamic{} }
func (m *Dynamic) String() string { return proto.CompactTextString(m) }
func (*Dynamic) ProtoMessage() {}
func (*Dynamic) Descriptor() ([]byte, []int) {
return fileDescriptor_b74e2e33d57193df, []int{13}
return fileDescriptor_b74e2e33d57193df, []int{14}
}
func (m *Dynamic) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@ -1105,7 +1206,7 @@ func (m *ListUserDynamicRequest) Reset() { *m = ListUserDynamicRequest{}
func (m *ListUserDynamicRequest) String() string { return proto.CompactTextString(m) }
func (*ListUserDynamicRequest) ProtoMessage() {}
func (*ListUserDynamicRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_b74e2e33d57193df, []int{14}
return fileDescriptor_b74e2e33d57193df, []int{15}
}
func (m *ListUserDynamicRequest) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@ -1158,7 +1259,7 @@ func (m *ListUserDynamicReply) Reset() { *m = ListUserDynamicReply{} }
func (m *ListUserDynamicReply) String() string { return proto.CompactTextString(m) }
func (*ListUserDynamicReply) ProtoMessage() {}
func (*ListUserDynamicReply) Descriptor() ([]byte, []int) {
return fileDescriptor_b74e2e33d57193df, []int{15}
return fileDescriptor_b74e2e33d57193df, []int{16}
}
func (m *ListUserDynamicReply) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@ -1215,7 +1316,7 @@ func (m *Sign) Reset() { *m = Sign{} }
func (m *Sign) String() string { return proto.CompactTextString(m) }
func (*Sign) ProtoMessage() {}
func (*Sign) Descriptor() ([]byte, []int) {
return fileDescriptor_b74e2e33d57193df, []int{16}
return fileDescriptor_b74e2e33d57193df, []int{17}
}
func (m *Sign) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@ -1295,7 +1396,7 @@ func (m *ListUserDownloadRequest) Reset() { *m = ListUserDownloadRequest
func (m *ListUserDownloadRequest) String() string { return proto.CompactTextString(m) }
func (*ListUserDownloadRequest) ProtoMessage() {}
func (*ListUserDownloadRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_b74e2e33d57193df, []int{17}
return fileDescriptor_b74e2e33d57193df, []int{18}
}
func (m *ListUserDownloadRequest) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@ -1347,7 +1448,7 @@ func (m *ListUserDownloadReply) Reset() { *m = ListUserDownloadReply{} }
func (m *ListUserDownloadReply) String() string { return proto.CompactTextString(m) }
func (*ListUserDownloadReply) ProtoMessage() {}
func (*ListUserDownloadReply) Descriptor() ([]byte, []int) {
return fileDescriptor_b74e2e33d57193df, []int{18}
return fileDescriptor_b74e2e33d57193df, []int{19}
}
func (m *ListUserDownloadReply) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@ -1391,8 +1492,10 @@ func (m *ListUserDownloadReply) GetDownload() []*Download {
}
func init() {
proto.RegisterEnum("api.v1.EmailCodeType", EmailCodeType_name, EmailCodeType_value)
proto.RegisterType((*User)(nil), "api.v1.User")
proto.RegisterType((*RegisterAndLoginRequest)(nil), "api.v1.RegisterAndLoginRequest")
proto.RegisterType((*SendEmailCodeRequest)(nil), "api.v1.SendEmailCodeRequest")
proto.RegisterType((*GetUserCaptchaRequest)(nil), "api.v1.GetUserCaptchaRequest")
proto.RegisterType((*LoginReply)(nil), "api.v1.LoginReply")
proto.RegisterType((*DeleteUserRequest)(nil), "api.v1.DeleteUserRequest")
@ -1415,113 +1518,119 @@ func init() {
func init() { proto.RegisterFile("api/v1/user.proto", fileDescriptor_b74e2e33d57193df) }
var fileDescriptor_b74e2e33d57193df = []byte{
// 1687 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x58, 0x4f, 0x6f, 0x23, 0x49,
0x15, 0x9f, 0xf6, 0x7f, 0x3f, 0x27, 0x99, 0xa4, 0xe2, 0xd8, 0x4e, 0x67, 0x26, 0x76, 0x7a, 0x05,
0x84, 0x61, 0x14, 0x33, 0x19, 0xc1, 0x4a, 0xb3, 0x5a, 0xa1, 0xcc, 0x64, 0x77, 0x15, 0x14, 0x44,
0xe8, 0x4c, 0x84, 0xb4, 0x7b, 0x88, 0x2a, 0xee, 0x8a, 0x29, 0xb6, 0xbb, 0xab, 0xa7, 0xbb, 0x1c,
0x6f, 0x38, 0x72, 0xe1, 0xba, 0x12, 0x5f, 0x03, 0x89, 0x2f, 0xc0, 0x07, 0xe0, 0x80, 0xd0, 0x4a,
0x7b, 0xe1, 0xb4, 0xa0, 0x19, 0xae, 0x5c, 0xf6, 0x03, 0x20, 0x54, 0xff, 0xda, 0xee, 0x76, 0x7a,
0x49, 0x66, 0x6e, 0xfd, 0x5e, 0xbd, 0xfa, 0x55, 0xd5, 0x7b, 0xbf, 0xf7, 0xc7, 0x86, 0x35, 0x1c,
0xd1, 0xe1, 0xd5, 0x93, 0xe1, 0x24, 0x21, 0xf1, 0x5e, 0x14, 0x33, 0xce, 0x50, 0x0d, 0x47, 0x74,
0xef, 0xea, 0x89, 0xdd, 0x1f, 0x33, 0x36, 0xf6, 0xc9, 0x50, 0x6a, 0x2f, 0x26, 0x97, 0x43, 0x4e,
0x03, 0x92, 0x70, 0x1c, 0x44, 0xca, 0xd0, 0x6e, 0x8f, 0xd9, 0x98, 0xc9, 0xcf, 0xa1, 0xf8, 0xd2,
0xda, 0x07, 0x7a, 0x9b, 0x00, 0xc6, 0x61, 0xc8, 0x38, 0xe6, 0x94, 0x85, 0x89, 0x5e, 0xdd, 0xca,
0x83, 0x92, 0x20, 0xe2, 0xd7, 0x7a, 0xb1, 0xab, 0x2f, 0x13, 0x91, 0x38, 0xa0, 0x49, 0x42, 0x59,
0xa8, 0x17, 0x36, 0xf4, 0x82, 0xc7, 0xa6, 0xa1, 0xcf, 0xb0, 0xa7, 0xd4, 0xce, 0x7f, 0xaa, 0x50,
0x39, 0x4b, 0x48, 0x8c, 0x3e, 0x80, 0x86, 0xcf, 0xc6, 0x34, 0x3c, 0xc7, 0xbc, 0xb7, 0x3e, 0xb0,
0x76, 0x5b, 0xfb, 0xf6, 0x9e, 0x3a, 0x68, 0xcf, 0x1c, 0xb4, 0xf7, 0xd2, 0xdc, 0xfe, 0x79, 0xe5,
0xcb, 0x7f, 0xf6, 0x2d, 0xb7, 0x2e, 0x77, 0x1c, 0x70, 0xf4, 0x33, 0x80, 0x51, 0x4c, 0x30, 0x27,
0x9e, 0xd8, 0xde, 0xbe, 0xe5, 0xf6, 0xa6, 0xde, 0xa3, 0x00, 0x26, 0x91, 0x67, 0x00, 0x36, 0x6e,
0x0b, 0xa0, 0xf7, 0x1c, 0x70, 0xb4, 0x02, 0x25, 0xea, 0xf5, 0xac, 0x81, 0xb5, 0x5b, 0x76, 0x4b,
0xd4, 0x43, 0x36, 0x34, 0x44, 0x3c, 0x42, 0x1c, 0x90, 0x5e, 0x69, 0x60, 0xed, 0x36, 0xdd, 0x54,
0x46, 0x1d, 0xa8, 0x05, 0xec, 0x82, 0xfa, 0xa4, 0x57, 0x96, 0x2b, 0x5a, 0x42, 0x6d, 0xa8, 0x92,
0x00, 0x53, 0xbf, 0x57, 0x91, 0x6a, 0x25, 0xa0, 0x1e, 0xd4, 0xb1, 0xe7, 0xc5, 0x24, 0x49, 0x7a,
0x55, 0xa9, 0x37, 0x22, 0x7a, 0x00, 0xcd, 0x84, 0x8e, 0x43, 0xcc, 0x27, 0x31, 0xe9, 0xd5, 0xe4,
0xda, 0x4c, 0x81, 0x1c, 0x58, 0xf6, 0x71, 0xc2, 0xcf, 0x95, 0x57, 0x69, 0xd4, 0xab, 0x4b, 0x8b,
0x96, 0x50, 0x1e, 0x0b, 0xdd, 0x51, 0x84, 0xfa, 0xd0, 0x8a, 0xc9, 0x98, 0x26, 0x9c, 0xc4, 0xc2,
0xa2, 0x21, 0x2d, 0xc0, 0xa8, 0x8e, 0x22, 0xb4, 0x05, 0x4d, 0x8f, 0x8d, 0xce, 0x47, 0x6c, 0x12,
0xf2, 0x5e, 0x73, 0x60, 0xed, 0x56, 0xdd, 0x86, 0xc7, 0x46, 0x2f, 0x84, 0x8c, 0x76, 0x60, 0xe9,
0x92, 0xf9, 0x3e, 0x9b, 0xea, 0x75, 0x90, 0xeb, 0x2d, 0xa5, 0x53, 0x26, 0x0f, 0x01, 0x2e, 0x71,
0x98, 0x68, 0x83, 0x96, 0x34, 0x68, 0x0a, 0x8d, 0x5a, 0xfe, 0x1e, 0xac, 0x5c, 0xe2, 0x2b, 0x16,
0x53, 0x4e, 0xb4, 0xc9, 0x92, 0x34, 0x59, 0x36, 0x5a, 0x65, 0xf6, 0x1e, 0x2c, 0x8f, 0x58, 0x10,
0x90, 0x90, 0x6b, 0xab, 0x65, 0x69, 0xb5, 0xa4, 0x95, 0xca, 0xa8, 0x03, 0xb5, 0x84, 0x63, 0x3e,
0x49, 0x7a, 0x2b, 0x72, 0x55, 0x4b, 0x42, 0x8f, 0xaf, 0x30, 0xc7, 0x71, 0xef, 0xbe, 0xf2, 0xb6,
0x92, 0x44, 0x84, 0xa8, 0x47, 0x42, 0x4e, 0xf9, 0x75, 0x6f, 0x55, 0x45, 0xc8, 0xc8, 0x62, 0x2d,
0x26, 0xd8, 0x97, 0xd1, 0x5b, 0x53, 0x6b, 0x46, 0x46, 0x9b, 0xd0, 0x18, 0xc7, 0x6c, 0x12, 0x9d,
0x53, 0xaf, 0x87, 0x06, 0xe5, 0xdd, 0xb2, 0x5b, 0x97, 0xf2, 0x91, 0x27, 0x1c, 0x32, 0x8a, 0x89,
0x47, 0xcd, 0x35, 0x3b, 0xca, 0x21, 0x4a, 0x27, 0x6f, 0xe9, 0x7c, 0x6d, 0x41, 0xd7, 0xd5, 0xfe,
0x3d, 0x08, 0x3d, 0x19, 0x08, 0x97, 0xbc, 0x9a, 0x90, 0x84, 0xa3, 0xf7, 0xe7, 0x38, 0x23, 0x98,
0xd4, 0x7c, 0xbe, 0xf5, 0xed, 0x37, 0xfd, 0xee, 0x15, 0xf6, 0xa9, 0xa0, 0xd9, 0x33, 0x27, 0xa0,
0xe1, 0x87, 0x4f, 0x1f, 0x07, 0xf8, 0x8b, 0x0f, 0x9f, 0xee, 0x3b, 0x73, 0x84, 0xfa, 0x31, 0x34,
0x22, 0x9c, 0x24, 0x53, 0x16, 0x7b, 0x8a, 0x6c, 0xcf, 0xdb, 0xdf, 0x7e, 0xd3, 0x5f, 0xcd, 0x6e,
0xfc, 0xa9, 0xe3, 0xa6, 0x56, 0x82, 0x54, 0x23, 0x1c, 0xf1, 0xd1, 0x6f, 0xb0, 0xe6, 0xa0, 0x11,
0x45, 0xc4, 0xf4, 0xa7, 0x78, 0xa0, 0x62, 0x62, 0x53, 0x6b, 0x8e, 0xbc, 0x19, 0x47, 0xab, 0x73,
0x1c, 0x75, 0x7e, 0x04, 0x1b, 0x9f, 0x10, 0x2e, 0xf2, 0xf8, 0x85, 0xb2, 0x34, 0x4f, 0x42, 0x50,
0xe1, 0xd7, 0x91, 0x7e, 0x8e, 0x2b, 0xbf, 0x9d, 0x43, 0x00, 0xfd, 0xec, 0xc8, 0xbf, 0x16, 0x80,
0x9c, 0x7d, 0x4e, 0x42, 0x6d, 0xa2, 0x04, 0x34, 0x80, 0x8a, 0x78, 0x9d, 0x7c, 0x4d, 0x6b, 0x7f,
0x69, 0x4f, 0xd5, 0xb3, 0x3d, 0x71, 0x82, 0x2b, 0x57, 0x9c, 0xf7, 0x60, 0xed, 0x90, 0xf8, 0x84,
0x13, 0xa9, 0xd3, 0xc7, 0x99, 0x2c, 0x2c, 0xab, 0x2c, 0x74, 0x06, 0xb0, 0xa2, 0xef, 0x95, 0xb7,
0xd0, 0x79, 0xea, 0xfc, 0xc9, 0x82, 0xf5, 0x8f, 0x69, 0xe8, 0x9d, 0x68, 0xcf, 0x18, 0xbb, 0xf4,
0x9d, 0xd6, 0x7c, 0x2e, 0xa6, 0x97, 0x2d, 0xcd, 0x5f, 0x76, 0xde, 0xfd, 0xe5, 0xbb, 0xba, 0xbf,
0xf2, 0x5d, 0xee, 0xaf, 0xe6, 0xdc, 0xef, 0xfc, 0xcd, 0x82, 0xfb, 0xc7, 0x34, 0xc9, 0x3c, 0x09,
0x41, 0x25, 0xc2, 0x63, 0xa2, 0x1f, 0x25, 0xbf, 0x85, 0x2e, 0xa1, 0xbf, 0x53, 0xa5, 0xa7, 0xec,
0xca, 0x6f, 0xf1, 0xf4, 0xa9, 0xbe, 0xa0, 0x5b, 0x9a, 0x7a, 0xd2, 0x86, 0xc5, 0x5c, 0xdf, 0x40,
0x7e, 0x6b, 0xf7, 0x54, 0x8d, 0x03, 0x33, 0x64, 0xaf, 0x65, 0xc9, 0x3e, 0xcb, 0xb7, 0xfa, 0xa0,
0x3c, 0x97, 0x6f, 0x6d, 0xa8, 0xfa, 0x34, 0xa0, 0x5c, 0x56, 0x93, 0xb2, 0xab, 0x04, 0xa1, 0xbd,
0xa4, 0xc4, 0xf7, 0x7a, 0xcd, 0x41, 0x59, 0x78, 0x4e, 0x0a, 0xce, 0x27, 0xb0, 0x3c, 0x7b, 0x4d,
0xca, 0x06, 0x8e, 0x7d, 0xfd, 0x18, 0x25, 0xcc, 0xb1, 0xa1, 0x5c, 0xc0, 0x86, 0xcf, 0x61, 0x3d,
0x4f, 0x40, 0x01, 0xd7, 0x81, 0x1a, 0x09, 0xf1, 0x85, 0xaf, 0x9c, 0xd3, 0x70, 0xb5, 0xa4, 0x9f,
0xa9, 0x82, 0x28, 0x9e, 0x59, 0x9c, 0x0e, 0x86, 0xc0, 0x95, 0x39, 0x02, 0xff, 0xc1, 0x82, 0xcd,
0x33, 0x59, 0xf9, 0xc5, 0x81, 0x79, 0xe6, 0xe4, 0x3b, 0xc1, 0x0e, 0x2c, 0x31, 0xdf, 0x3b, 0xcf,
0x26, 0xa8, 0xdb, 0x62, 0x7e, 0xca, 0x39, 0xf4, 0x3e, 0x2c, 0x85, 0x64, 0x7a, 0x7e, 0x2b, 0x12,
0xb5, 0x42, 0x32, 0x35, 0x1b, 0x9d, 0x5f, 0x40, 0x57, 0x3f, 0xfb, 0x24, 0xed, 0xb7, 0x89, 0x7a,
0xfa, 0x3e, 0xc0, 0xac, 0x07, 0xcb, 0x94, 0x68, 0xed, 0x23, 0xe3, 0xb9, 0x99, 0xb5, 0x3b, 0x67,
0xe5, 0xfc, 0xc5, 0x82, 0x95, 0xd3, 0xef, 0xcc, 0x97, 0x4c, 0x8d, 0x2a, 0xbd, 0x6d, 0x8d, 0xba,
0x5d, 0x92, 0xcc, 0x73, 0xaf, 0x92, 0xe5, 0xde, 0xcd, 0x55, 0xe8, 0xbf, 0x16, 0xd4, 0x0f, 0xaf,
0x43, 0x1c, 0xd0, 0xd1, 0xc2, 0xbd, 0xbb, 0x50, 0x17, 0x57, 0x39, 0xd7, 0x61, 0x2f, 0xbb, 0x35,
0x21, 0x1e, 0xa9, 0xd0, 0xb3, 0x90, 0x93, 0x90, 0xa7, 0xa1, 0x57, 0x62, 0x26, 0xf4, 0x55, 0x15,
0xfa, 0x4c, 0x5b, 0xaf, 0xe7, 0xda, 0x7a, 0x76, 0x08, 0xa9, 0xbe, 0xeb, 0x10, 0x52, 0xbb, 0xf3,
0x10, 0xe2, 0x7c, 0x0c, 0x1d, 0x93, 0x4e, 0xda, 0x0f, 0x77, 0xac, 0x11, 0x3f, 0xaf, 0x34, 0xca,
0xab, 0x15, 0xe7, 0xd7, 0xd0, 0x5e, 0xc0, 0x29, 0xce, 0xce, 0x1f, 0x42, 0xdd, 0x53, 0x56, 0x3a,
0x41, 0xef, 0x1b, 0x9a, 0x99, 0xcd, 0x66, 0xdd, 0xf9, 0xb3, 0x05, 0x95, 0x53, 0x3a, 0x0e, 0x6f,
0x1f, 0x9e, 0x2e, 0xd4, 0xc5, 0x48, 0x23, 0x1c, 0x52, 0xd6, 0x6d, 0x9d, 0x8e, 0x43, 0x3d, 0x70,
0x45, 0x3a, 0x2d, 0x4b, 0x34, 0x7a, 0x77, 0xef, 0xb7, 0xa1, 0x8a, 0xa7, 0x38, 0xf6, 0xa4, 0xe3,
0xab, 0xae, 0x12, 0x9c, 0x03, 0xe8, 0xa6, 0xae, 0xd0, 0x93, 0xeb, 0x1d, 0x7d, 0xea, 0x7c, 0x06,
0x1b, 0x8b, 0x10, 0xc5, 0xee, 0x7c, 0x0c, 0x0d, 0x33, 0x23, 0x6b, 0x7f, 0xae, 0xa6, 0xfe, 0x34,
0xdb, 0x53, 0x8b, 0xfd, 0xbf, 0xaf, 0x40, 0x5d, 0x20, 0x1f, 0x9c, 0x1c, 0x21, 0x0c, 0x0d, 0x33,
0x5a, 0xa0, 0xbe, 0xd9, 0x53, 0x30, 0x6c, 0xd8, 0x69, 0x2d, 0x98, 0xf5, 0x62, 0x67, 0xf0, 0xfb,
0xaf, 0xff, 0xfd, 0xc7, 0x92, 0xed, 0x6c, 0x0c, 0xe7, 0x7e, 0x52, 0x0c, 0xcd, 0x38, 0xf8, 0xcc,
0x7a, 0x84, 0x3e, 0x83, 0xaa, 0xb4, 0x7f, 0x3b, 0xfc, 0x87, 0x12, 0xbf, 0xeb, 0xa0, 0x0c, 0xbe,
0x1c, 0x50, 0x05, 0xf8, 0x19, 0xd4, 0x8e, 0xd9, 0x98, 0x4d, 0x38, 0xea, 0x2c, 0x04, 0xee, 0x23,
0xf1, 0x1b, 0xc3, 0x2e, 0xd0, 0x3b, 0x5b, 0x12, 0x78, 0xe3, 0xd1, 0x7a, 0x1e, 0x58, 0x80, 0x7d,
0x04, 0x75, 0x5d, 0x24, 0x51, 0xc7, 0x5c, 0x2a, 0x3b, 0x15, 0xd8, 0x99, 0x96, 0xe2, 0xb4, 0x25,
0xda, 0x0a, 0x5a, 0x9a, 0x47, 0x43, 0xaf, 0x00, 0x2d, 0x16, 0x7d, 0xb4, 0x93, 0xee, 0x2c, 0x6a,
0x08, 0x85, 0x97, 0xd6, 0xde, 0xb6, 0xb3, 0xde, 0x36, 0xe5, 0x4f, 0x38, 0xe4, 0x53, 0x58, 0x9b,
0x83, 0x8d, 0xd9, 0xa5, 0xf8, 0x95, 0x90, 0xb9, 0x6b, 0x21, 0x78, 0x5f, 0x82, 0x6f, 0xda, 0xed,
0x2c, 0xb8, 0xc2, 0x50, 0xce, 0x86, 0xd9, 0xfc, 0x84, 0x36, 0x53, 0x8a, 0xe5, 0x67, 0xaa, 0xc2,
0x13, 0xb4, 0x97, 0x1e, 0x65, 0xbd, 0xe4, 0x42, 0xfd, 0xc0, 0xf3, 0xb2, 0xce, 0xce, 0xb6, 0x94,
0x42, 0xc0, 0xae, 0x04, 0x5c, 0x73, 0x32, 0x80, 0xe2, 0xaa, 0x2e, 0xd4, 0x4f, 0xf3, 0x01, 0xbc,
0x1b, 0xa6, 0xbd, 0x80, 0x79, 0x06, 0x0d, 0x93, 0x94, 0xa8, 0x9b, 0x52, 0x35, 0x3b, 0x59, 0xd9,
0x1b, 0x8b, 0x0b, 0x82, 0xc6, 0x9b, 0x12, 0x74, 0x1d, 0xad, 0x65, 0xd9, 0x46, 0x13, 0x8e, 0x7e,
0x9b, 0x0e, 0x9c, 0x2f, 0xcc, 0x40, 0x97, 0xa3, 0x5c, 0x76, 0x40, 0xb6, 0xb7, 0x8a, 0x96, 0xc5,
0x41, 0x0f, 0xe4, 0x41, 0x1d, 0x94, 0x0d, 0xa2, 0x19, 0x4d, 0x42, 0x40, 0x8b, 0xcd, 0xbf, 0x30,
0x75, 0xfa, 0xb9, 0x83, 0xf2, 0x03, 0x83, 0x61, 0x0c, 0xea, 0x66, 0x19, 0x93, 0x9a, 0xa1, 0x00,
0xd0, 0x0b, 0x1c, 0x1e, 0x9d, 0x45, 0xa2, 0xf0, 0x1c, 0xb2, 0xd1, 0x44, 0xfc, 0xf6, 0xba, 0x73,
0xaa, 0xfe, 0x40, 0x1e, 0xb3, 0x83, 0xfa, 0xb9, 0x37, 0x85, 0x74, 0x22, 0x81, 0x3d, 0x03, 0x1c,
0xcc, 0x26, 0x5d, 0xd3, 0xd4, 0xb7, 0xf3, 0xf1, 0xc8, 0x76, 0x39, 0xfb, 0x41, 0xe1, 0x7a, 0xb1,
0x37, 0x75, 0x6b, 0x42, 0xc7, 0xd0, 0x14, 0x9d, 0xe9, 0x25, 0xf3, 0xf0, 0x75, 0xe1, 0xa3, 0xd2,
0xdc, 0x13, 0xa6, 0x86, 0x07, 0x76, 0x96, 0x07, 0xa2, 0x3f, 0xa1, 0x5f, 0x49, 0x1e, 0x08, 0x2b,
0xe2, 0xbd, 0x05, 0x24, 0xba, 0x01, 0xf2, 0x15, 0xac, 0xe6, 0xdb, 0xc8, 0xac, 0x0a, 0x17, 0xf4,
0x28, 0xfb, 0x61, 0xb1, 0xc1, 0x5c, 0x41, 0x46, 0xd9, 0x12, 0x64, 0x9a, 0x0b, 0xfa, 0x22, 0xfb,
0xdb, 0xe8, 0x94, 0x93, 0xe8, 0x97, 0x21, 0x41, 0x29, 0x67, 0x6f, 0xf8, 0xe1, 0x54, 0x18, 0xf7,
0xc7, 0xf2, 0xa8, 0xef, 0x3b, 0x3b, 0x99, 0xa3, 0x2e, 0x69, 0xe8, 0x99, 0x8a, 0x37, 0x4c, 0x38,
0x89, 0x58, 0x28, 0xab, 0xd3, 0x0d, 0x27, 0xbf, 0x9c, 0xb2, 0x77, 0x3a, 0xd9, 0xfe, 0x3f, 0x27,
0xf3, 0x29, 0x7b, 0x66, 0x3d, 0x7a, 0xfe, 0x93, 0xbf, 0xbe, 0xde, 0xb6, 0xbe, 0x7a, 0xbd, 0x6d,
0xfd, 0xeb, 0xf5, 0xb6, 0xf5, 0xe5, 0x9b, 0xed, 0x7b, 0x5f, 0xbd, 0xd9, 0xbe, 0xf7, 0x8f, 0x37,
0xdb, 0xf7, 0x40, 0xff, 0xa9, 0x76, 0x62, 0x7d, 0xba, 0x16, 0xb0, 0x98, 0x78, 0x6c, 0xa4, 0x01,
0x3f, 0xb8, 0x7a, 0x72, 0x51, 0x93, 0x87, 0x3e, 0xfd, 0x5f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x61,
0xbb, 0x15, 0x8a, 0x8d, 0x13, 0x00, 0x00,
// 1790 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x58, 0xcd, 0x6e, 0x1b, 0xc9,
0x11, 0xf6, 0x88, 0xff, 0x45, 0x49, 0x96, 0x5a, 0xfc, 0x13, 0x25, 0x8b, 0xd4, 0x2c, 0x92, 0x68,
0x1d, 0x43, 0x8c, 0x65, 0x24, 0x0b, 0xec, 0x62, 0x11, 0x48, 0xb2, 0x77, 0xa1, 0xc0, 0x41, 0x9c,
0x91, 0x85, 0x00, 0xbb, 0x07, 0x61, 0xcc, 0x6e, 0x31, 0x9d, 0x1d, 0x4e, 0x8f, 0x67, 0x9a, 0xe2,
0x2a, 0xc7, 0x5c, 0x72, 0x35, 0x90, 0xd7, 0x08, 0x90, 0x73, 0x80, 0x3c, 0x40, 0x0e, 0x39, 0x2c,
0x90, 0x4b, 0x4e, 0x9b, 0xc0, 0x0e, 0x90, 0x53, 0x2e, 0x7e, 0x80, 0x20, 0xe8, 0xbf, 0x21, 0x7b,
0xe8, 0xf1, 0x4a, 0xf6, 0x8d, 0x55, 0x5d, 0xfd, 0x55, 0x75, 0xd5, 0xd7, 0xd5, 0x35, 0x84, 0x75,
0x3f, 0xa2, 0x83, 0xcb, 0xfb, 0x83, 0x49, 0x42, 0xe2, 0xfd, 0x28, 0x66, 0x9c, 0xa1, 0xb2, 0x1f,
0xd1, 0xfd, 0xcb, 0xfb, 0xdd, 0xde, 0x88, 0xb1, 0x51, 0x40, 0x06, 0x52, 0xfb, 0x6c, 0x72, 0x31,
0xe0, 0x74, 0x4c, 0x12, 0xee, 0x8f, 0x23, 0x65, 0xd8, 0x6d, 0x8c, 0xd8, 0x88, 0xc9, 0x9f, 0x03,
0xf1, 0x4b, 0x6b, 0xb7, 0xf5, 0x36, 0x01, 0xec, 0x87, 0x21, 0xe3, 0x3e, 0xa7, 0x2c, 0x4c, 0xf4,
0xea, 0x56, 0x16, 0x94, 0x8c, 0x23, 0x7e, 0xa5, 0x17, 0xdb, 0x3a, 0x98, 0x88, 0xc4, 0x63, 0x9a,
0x24, 0x94, 0x85, 0x7a, 0xa1, 0xa9, 0x17, 0x30, 0x9b, 0x86, 0x01, 0xf3, 0xb1, 0x52, 0xbb, 0xff,
0x2d, 0x41, 0xf1, 0x2c, 0x21, 0x31, 0xfa, 0x04, 0xaa, 0x01, 0x1b, 0xd1, 0xf0, 0xdc, 0xe7, 0x9d,
0x8d, 0xbe, 0xb3, 0x57, 0x3f, 0xe8, 0xee, 0x2b, 0x47, 0xfb, 0xc6, 0xd1, 0xfe, 0x53, 0x13, 0xfd,
0x51, 0xf1, 0xc5, 0x3f, 0x7b, 0x8e, 0x57, 0x91, 0x3b, 0x0e, 0x39, 0xfa, 0x29, 0xc0, 0x30, 0x26,
0x3e, 0x27, 0x58, 0x6c, 0x6f, 0x5c, 0x73, 0x7b, 0x4d, 0xef, 0x51, 0x00, 0x93, 0x08, 0x1b, 0x80,
0xe6, 0x75, 0x01, 0xf4, 0x9e, 0x43, 0x8e, 0x56, 0x61, 0x89, 0xe2, 0x8e, 0xd3, 0x77, 0xf6, 0x0a,
0xde, 0x12, 0xc5, 0xa8, 0x0b, 0x55, 0x51, 0x8f, 0xd0, 0x1f, 0x93, 0xce, 0x52, 0xdf, 0xd9, 0xab,
0x79, 0xa9, 0x8c, 0x5a, 0x50, 0x1e, 0xb3, 0x67, 0x34, 0x20, 0x9d, 0x82, 0x5c, 0xd1, 0x12, 0x6a,
0x40, 0x89, 0x8c, 0x7d, 0x1a, 0x74, 0x8a, 0x52, 0xad, 0x04, 0xd4, 0x81, 0x8a, 0x8f, 0x71, 0x4c,
0x92, 0xa4, 0x53, 0x92, 0x7a, 0x23, 0xa2, 0x6d, 0xa8, 0x25, 0x74, 0x14, 0xfa, 0x7c, 0x12, 0x93,
0x4e, 0x59, 0xae, 0xcd, 0x14, 0xc8, 0x85, 0x95, 0xc0, 0x4f, 0xf8, 0xb9, 0xca, 0x2a, 0x8d, 0x3a,
0x15, 0x69, 0x51, 0x17, 0xca, 0xc7, 0x42, 0x77, 0x12, 0xa1, 0x1e, 0xd4, 0x63, 0x32, 0xa2, 0x09,
0x27, 0xb1, 0xb0, 0xa8, 0x4a, 0x0b, 0x30, 0xaa, 0x93, 0x08, 0x6d, 0x41, 0x0d, 0xb3, 0xe1, 0xf9,
0x90, 0x4d, 0x42, 0xde, 0xa9, 0xf5, 0x9d, 0xbd, 0x92, 0x57, 0xc5, 0x6c, 0x78, 0x2c, 0x64, 0xb4,
0x0b, 0xcb, 0x17, 0x2c, 0x08, 0xd8, 0x54, 0xaf, 0x83, 0x5c, 0xaf, 0x2b, 0x9d, 0x32, 0xb9, 0x03,
0x70, 0xe1, 0x87, 0x89, 0x36, 0xa8, 0x4b, 0x83, 0x9a, 0xd0, 0xa8, 0xe5, 0xef, 0xc1, 0xea, 0x85,
0x7f, 0xc9, 0x62, 0xca, 0x89, 0x36, 0x59, 0x96, 0x26, 0x2b, 0x46, 0xab, 0xcc, 0x3e, 0x80, 0x95,
0x21, 0x1b, 0x8f, 0x49, 0xc8, 0xb5, 0xd5, 0x8a, 0xb4, 0x5a, 0xd6, 0x4a, 0x65, 0xd4, 0x82, 0x72,
0xc2, 0x7d, 0x3e, 0x49, 0x3a, 0xab, 0x72, 0x55, 0x4b, 0x42, 0xef, 0x5f, 0xfa, 0xdc, 0x8f, 0x3b,
0xb7, 0x55, 0xb6, 0x95, 0x24, 0x2a, 0x44, 0x31, 0x09, 0x39, 0xe5, 0x57, 0x9d, 0x35, 0x55, 0x21,
0x23, 0x8b, 0xb5, 0x98, 0xf8, 0x81, 0xac, 0xde, 0xba, 0x5a, 0x33, 0x32, 0xda, 0x84, 0xea, 0x28,
0x66, 0x93, 0xe8, 0x9c, 0xe2, 0x0e, 0xea, 0x17, 0xf6, 0x0a, 0x5e, 0x45, 0xca, 0x27, 0x58, 0x24,
0x64, 0x18, 0x13, 0x4c, 0x4d, 0x98, 0x2d, 0x95, 0x10, 0xa5, 0x93, 0x51, 0xba, 0xff, 0x71, 0xa0,
0xed, 0xe9, 0xfc, 0x1e, 0x86, 0x58, 0x16, 0xc2, 0x23, 0xcf, 0x27, 0x24, 0xe1, 0xe8, 0xa3, 0x39,
0xce, 0x08, 0x26, 0xd5, 0x8e, 0xb6, 0x5e, 0x7f, 0xdb, 0x6b, 0x5f, 0xfa, 0x01, 0x15, 0x34, 0xfb,
0xd8, 0x1d, 0xd3, 0xf0, 0xd3, 0x07, 0xf7, 0xc6, 0xfe, 0xd7, 0x9f, 0x3e, 0x38, 0x70, 0xe7, 0x08,
0xf5, 0x23, 0xa8, 0x46, 0x7e, 0x92, 0x4c, 0x59, 0x8c, 0x15, 0xd9, 0x8e, 0x1a, 0xaf, 0xbf, 0xed,
0xad, 0xd9, 0x1b, 0x7f, 0xe2, 0x7a, 0xa9, 0x95, 0x20, 0xd5, 0xd0, 0x8f, 0xf8, 0xf0, 0xd7, 0xbe,
0xe6, 0xa0, 0x11, 0x45, 0xc5, 0xf4, 0x4f, 0x71, 0x40, 0xc5, 0xc4, 0x9a, 0xd6, 0x9c, 0xe0, 0x19,
0x47, 0x4b, 0xf3, 0x1c, 0x45, 0x50, 0x1c, 0x32, 0x6c, 0x48, 0x28, 0x7f, 0xbb, 0x2f, 0x1c, 0x68,
0x9c, 0x92, 0x10, 0x3f, 0x12, 0x16, 0xc7, 0x0c, 0x13, 0x73, 0xcc, 0x14, 0xc2, 0xc9, 0xd0, 0xdc,
0x44, 0xb4, 0xf4, 0xb6, 0x88, 0x0a, 0xd9, 0x88, 0x3e, 0x84, 0x22, 0xbf, 0x8a, 0x88, 0x0c, 0x75,
0xf5, 0xa0, 0xb9, 0xaf, 0x5a, 0xdf, 0x7e, 0xea, 0xf6, 0xe9, 0x55, 0x44, 0x3c, 0x69, 0xe2, 0xfe,
0x10, 0x9a, 0x9f, 0x13, 0x2e, 0xda, 0xcd, 0xb1, 0xda, 0x6e, 0x42, 0x42, 0x1a, 0x43, 0x45, 0xa4,
0x8c, 0x1f, 0x02, 0xe8, 0xea, 0x44, 0xc1, 0x95, 0x08, 0x9a, 0xb3, 0xaf, 0x48, 0x68, 0x82, 0x96,
0x02, 0xea, 0x43, 0x51, 0x14, 0x41, 0x46, 0x5c, 0x3f, 0x58, 0x36, 0xbe, 0x85, 0x07, 0x4f, 0xae,
0xb8, 0x1f, 0xc0, 0xfa, 0x43, 0x12, 0x10, 0x4e, 0xa4, 0x4e, 0xbb, 0x33, 0xcd, 0xa2, 0xa0, 0x9a,
0x85, 0xdb, 0x87, 0x55, 0x1d, 0x57, 0xd6, 0x42, 0xb7, 0x13, 0xf7, 0x8f, 0x0e, 0x6c, 0x7c, 0x46,
0x43, 0xfc, 0x44, 0x17, 0xf0, 0xed, 0xb9, 0x4c, 0x83, 0x5d, 0x9a, 0x0f, 0x76, 0x9e, 0x25, 0x85,
0x9b, 0xb2, 0xa4, 0xf8, 0xb6, 0x9a, 0x94, 0x32, 0x35, 0x71, 0xff, 0xe6, 0xc0, 0xed, 0xc7, 0x34,
0xb1, 0x8e, 0x84, 0xa0, 0x18, 0xf9, 0x23, 0xa2, 0x0f, 0x25, 0x7f, 0x0b, 0x5d, 0x42, 0x7f, 0xab,
0x3a, 0x64, 0xc1, 0x93, 0xbf, 0xc5, 0xd1, 0xa7, 0xa6, 0xcc, 0x4b, 0x53, 0x2c, 0x6d, 0x58, 0xcc,
0x75, 0x04, 0xf2, 0xb7, 0x4e, 0x4f, 0xc9, 0x24, 0xd0, 0xba, 0x93, 0x65, 0xfb, 0x4e, 0xce, 0xda,
0x42, 0xa5, 0x5f, 0x98, 0x6b, 0x0b, 0x0d, 0x28, 0x05, 0x74, 0x4c, 0xb9, 0x6c, 0x7a, 0x05, 0x4f,
0x09, 0x42, 0x7b, 0x41, 0x49, 0x80, 0x3b, 0xb5, 0x7e, 0x41, 0x64, 0x4e, 0x0a, 0xee, 0xe7, 0xb0,
0x32, 0x3b, 0x4d, 0xca, 0x06, 0xee, 0x07, 0xfa, 0x30, 0x4a, 0x98, 0x63, 0x43, 0x21, 0x87, 0x0d,
0x5f, 0xc1, 0x46, 0x96, 0x80, 0x02, 0xae, 0x05, 0x65, 0x12, 0xfa, 0xcf, 0x02, 0x95, 0x9c, 0xaa,
0xa7, 0x25, 0x7d, 0x4c, 0x55, 0x44, 0x71, 0xcc, 0xfc, 0x5b, 0x8b, 0xe6, 0x2e, 0x81, 0x21, 0xf0,
0xef, 0x1d, 0xd8, 0x3c, 0x93, 0x0f, 0x94, 0x70, 0x98, 0x65, 0x4e, 0xf6, 0xc1, 0xda, 0x85, 0x65,
0x16, 0xe0, 0x73, 0xbb, 0x8f, 0x78, 0x75, 0x16, 0xa4, 0x9c, 0x43, 0x1f, 0xc1, 0x72, 0x48, 0xa6,
0xe7, 0xd7, 0x22, 0x51, 0x3d, 0x24, 0x53, 0xb3, 0xd1, 0xfd, 0x39, 0xb4, 0xf5, 0xb1, 0x9f, 0xa4,
0x63, 0x41, 0xa2, 0x8e, 0x7e, 0x00, 0x30, 0x1b, 0x15, 0xe4, 0x95, 0xa8, 0x1f, 0x20, 0x93, 0xb9,
0x99, 0xb5, 0x37, 0x67, 0xe5, 0xfe, 0xc5, 0x81, 0xd5, 0xd3, 0xb7, 0xde, 0x17, 0xab, 0x95, 0x2e,
0xbd, 0x6b, 0x2b, 0xbd, 0xde, 0x25, 0x99, 0xe7, 0x5e, 0xd1, 0xe6, 0xde, 0x1b, 0x9b, 0xa5, 0xfb,
0x3f, 0x07, 0x2a, 0x0f, 0xaf, 0x42, 0x7f, 0x4c, 0x87, 0x0b, 0x71, 0xb7, 0xa1, 0x22, 0x42, 0x39,
0xd7, 0x65, 0x2f, 0x78, 0x65, 0x21, 0x9e, 0xa8, 0xd2, 0xb3, 0x90, 0x93, 0x90, 0xa7, 0xa5, 0x57,
0xa2, 0x55, 0xfa, 0x92, 0x2a, 0xbd, 0x35, 0x7d, 0x54, 0x32, 0xd3, 0x87, 0x3d, 0x2b, 0x95, 0xde,
0x77, 0x56, 0x2a, 0xdf, 0x78, 0x56, 0x72, 0x3f, 0x83, 0x96, 0xb9, 0x4e, 0x3a, 0x0f, 0x37, 0xec,
0x11, 0x3f, 0x2b, 0x56, 0x0b, 0x6b, 0x45, 0xf7, 0x57, 0xd0, 0x58, 0xc0, 0xc9, 0xbf, 0x9d, 0x1f,
0x42, 0x05, 0x2b, 0x2b, 0x7d, 0x41, 0x6f, 0x1b, 0x9a, 0x99, 0xcd, 0x66, 0xdd, 0xfd, 0x93, 0x03,
0xc5, 0x53, 0x3a, 0x0a, 0xaf, 0x5f, 0x9e, 0x36, 0x54, 0xc4, 0xe4, 0x25, 0x12, 0x52, 0xd0, 0xd3,
0x07, 0x1d, 0x85, 0x7a, 0x2e, 0x8c, 0xf4, 0xb5, 0x5c, 0xa2, 0xd1, 0xfb, 0x67, 0xbf, 0x01, 0x25,
0x7f, 0xea, 0xc7, 0x58, 0x26, 0xbe, 0xe4, 0x29, 0xc1, 0x3d, 0x84, 0x76, 0x9a, 0x0a, 0x3d, 0x60,
0xdf, 0x30, 0xa7, 0xee, 0x97, 0xd0, 0x5c, 0x84, 0xc8, 0x4f, 0xe7, 0x3d, 0xa8, 0x9a, 0x51, 0x5e,
0xe7, 0x73, 0x2d, 0xcd, 0xa7, 0xd9, 0x9e, 0x5a, 0xdc, 0x3d, 0x82, 0x15, 0xeb, 0x41, 0x46, 0x9b,
0xd0, 0xb4, 0x5f, 0x68, 0x3d, 0x13, 0xad, 0xdd, 0x42, 0x2d, 0x40, 0xd6, 0x92, 0x7c, 0x85, 0xd7,
0x9c, 0x83, 0x3f, 0xdf, 0x86, 0x8a, 0x88, 0xee, 0xf0, 0xc9, 0x09, 0xf2, 0xa1, 0x6a, 0x76, 0xa0,
0x9e, 0xf1, 0x9b, 0x33, 0x57, 0x75, 0xd3, 0x7e, 0x32, 0x7b, 0xcf, 0xdd, 0xfe, 0xef, 0xfe, 0xfe,
0xef, 0x3f, 0x2c, 0x75, 0xdd, 0xe6, 0x60, 0xee, 0xeb, 0x69, 0x60, 0x26, 0xdf, 0x8f, 0x9d, 0xbb,
0xe8, 0x4b, 0x28, 0x49, 0xfb, 0x77, 0xc3, 0xbf, 0x23, 0xf1, 0xdb, 0x2e, 0xb2, 0xf0, 0xe5, 0x2c,
0x2e, 0xc0, 0xcf, 0xa0, 0xfc, 0x98, 0x8d, 0xd8, 0x84, 0xa3, 0xd6, 0x42, 0xf1, 0x1f, 0x89, 0xcf,
0xa9, 0x6e, 0x8e, 0xde, 0xdd, 0x92, 0xc0, 0xcd, 0xbb, 0x1b, 0x59, 0x60, 0x01, 0xf6, 0x08, 0x2a,
0xba, 0xd1, 0xa2, 0x96, 0x09, 0xca, 0x9e, 0x2c, 0xba, 0xd6, 0xb3, 0xe4, 0x36, 0x24, 0xda, 0x2a,
0x5a, 0x9e, 0x47, 0x43, 0xcf, 0x01, 0x2d, 0x3e, 0x1c, 0x68, 0x37, 0xdd, 0x99, 0xf7, 0xa8, 0xe4,
0x06, 0xad, 0xb3, 0xdd, 0xb5, 0xb3, 0x6d, 0x5a, 0xa8, 0x48, 0xc8, 0x17, 0xb0, 0x3e, 0x07, 0x1b,
0xb3, 0x0b, 0xf1, 0x41, 0x64, 0xc5, 0x9a, 0x0b, 0xde, 0x93, 0xe0, 0x9b, 0xdd, 0x86, 0x0d, 0xae,
0x30, 0x54, 0xb2, 0x61, 0x36, 0x83, 0xa1, 0xcd, 0x94, 0xa6, 0xd9, 0xb9, 0x2c, 0xd7, 0x83, 0xce,
0xd2, 0x5d, 0x3b, 0x4b, 0x1e, 0x54, 0x0e, 0x31, 0xb6, 0x93, 0x6d, 0x3f, 0x4b, 0xb9, 0x80, 0x6d,
0x09, 0xb8, 0xee, 0x5a, 0x80, 0x22, 0x54, 0x0f, 0x2a, 0xa7, 0xd9, 0x02, 0xde, 0x0c, 0xb3, 0xbb,
0x80, 0x79, 0x06, 0x55, 0x73, 0xb1, 0x51, 0x3b, 0xa5, 0xaa, 0x3d, 0x9d, 0x75, 0x9b, 0x8b, 0x0b,
0x82, 0xc6, 0x9b, 0x12, 0x74, 0x03, 0xad, 0xdb, 0x6c, 0xa3, 0x09, 0x47, 0xbf, 0x49, 0x87, 0xd6,
0x63, 0x33, 0x14, 0x66, 0x28, 0x67, 0x0f, 0xd9, 0xdd, 0xad, 0xbc, 0x65, 0xe1, 0x68, 0x5b, 0x3a,
0x6a, 0x21, 0xbb, 0x88, 0x66, 0xbc, 0x09, 0x01, 0x2d, 0x0e, 0x10, 0xb9, 0x57, 0xa7, 0x97, 0x71,
0x94, 0x1d, 0x3a, 0x0c, 0x63, 0x50, 0xdb, 0x66, 0x4c, 0x6a, 0x86, 0xc6, 0x80, 0x8e, 0xfd, 0xf0,
0xe4, 0x2c, 0x12, 0xcd, 0xeb, 0x21, 0x1b, 0x4e, 0xc4, 0x67, 0xe6, 0x8d, 0xaf, 0xea, 0x0f, 0xa4,
0x9b, 0x5d, 0xd4, 0xcb, 0x9c, 0x29, 0xa4, 0x13, 0x09, 0x8c, 0x0d, 0xf0, 0x78, 0x36, 0x2d, 0x9b,
0xc1, 0x60, 0x27, 0x5b, 0x0f, 0xfb, 0xa5, 0xec, 0x6e, 0xe7, 0xae, 0xe7, 0x67, 0x53, 0x3f, 0x6f,
0xe8, 0x31, 0xd4, 0xc4, 0xeb, 0xf6, 0x94, 0x61, 0xff, 0x2a, 0xf7, 0x50, 0xe9, 0xdd, 0x13, 0xa6,
0x86, 0x07, 0x5d, 0x9b, 0x07, 0xe2, 0x8d, 0x43, 0xbf, 0x94, 0x3c, 0x10, 0x56, 0x04, 0xbf, 0x03,
0x24, 0x7a, 0x03, 0xe4, 0x73, 0x58, 0xcb, 0x3e, 0x45, 0xb3, 0x2e, 0x9c, 0xf3, 0xce, 0x75, 0xef,
0xe4, 0x1b, 0xcc, 0x35, 0x64, 0x64, 0xb7, 0x20, 0xf3, 0x40, 0xa1, 0xaf, 0xed, 0xef, 0xab, 0x53,
0x4e, 0xa2, 0x5f, 0x84, 0x04, 0xa5, 0x9c, 0x7d, 0xc3, 0xc7, 0x57, 0x6e, 0xdd, 0xef, 0x49, 0x57,
0xdf, 0x77, 0x77, 0x2d, 0x57, 0x17, 0x34, 0xc4, 0xa6, 0xe3, 0x0d, 0x12, 0x4e, 0x22, 0x16, 0xca,
0xee, 0xf4, 0x06, 0xcf, 0x4f, 0xa7, 0xec, 0xbd, 0x3c, 0x77, 0xbf, 0xc3, 0x33, 0x9f, 0x32, 0xe1,
0x99, 0xc2, 0x8a, 0xf5, 0x81, 0x8e, 0xb6, 0x67, 0x2d, 0x67, 0xf1, 0xbb, 0x3d, 0xd7, 0xa9, 0x2b,
0x9d, 0x6e, 0xbb, 0xf6, 0x6d, 0x92, 0xb3, 0xee, 0x60, 0xc8, 0xb0, 0x38, 0xe4, 0xd1, 0x8f, 0xff,
0xfa, 0x72, 0xc7, 0xf9, 0xe6, 0xe5, 0x8e, 0xf3, 0xaf, 0x97, 0x3b, 0xce, 0x8b, 0x57, 0x3b, 0xb7,
0xbe, 0x79, 0xb5, 0x73, 0xeb, 0x1f, 0xaf, 0x76, 0x6e, 0x81, 0xfe, 0xab, 0xf2, 0x89, 0xf3, 0xc5,
0xfa, 0x98, 0xc5, 0x04, 0xb3, 0xa1, 0x86, 0xf9, 0xe4, 0xf2, 0xfe, 0xb3, 0xb2, 0x74, 0xf5, 0xe0,
0xff, 0x01, 0x00, 0x00, 0xff, 0xff, 0x85, 0xf6, 0xe0, 0xad, 0xe3, 0x14, 0x00, 0x00,
}
// Reference imports to suppress errors if they are not otherwise used.
@ -1577,6 +1686,8 @@ type UserAPIClient interface {
FindPasswordStepOne(ctx context.Context, in *FindPasswordRequest, opts ...grpc.CallOption) (*emptypb.Empty, error)
// 找回密码:第二步,修改密码
FindPasswordStepTwo(ctx context.Context, in *FindPasswordRequest, opts ...grpc.CallOption) (*emptypb.Empty, error)
// 发送邮箱验证码。
SendEmailCode(ctx context.Context, in *SendEmailCodeRequest, opts ...grpc.CallOption) (*emptypb.Empty, error)
}
type userAPIClient struct {
@ -1758,6 +1869,15 @@ func (c *userAPIClient) FindPasswordStepTwo(ctx context.Context, in *FindPasswor
return out, nil
}
func (c *userAPIClient) SendEmailCode(ctx context.Context, in *SendEmailCodeRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) {
out := new(emptypb.Empty)
err := c.cc.Invoke(ctx, "/api.v1.UserAPI/SendEmailCode", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
// UserAPIServer is the server API for UserAPI service.
type UserAPIServer interface {
// 用户注册
@ -1801,6 +1921,8 @@ type UserAPIServer interface {
FindPasswordStepOne(context.Context, *FindPasswordRequest) (*emptypb.Empty, error)
// 找回密码:第二步,修改密码
FindPasswordStepTwo(context.Context, *FindPasswordRequest) (*emptypb.Empty, error)
// 发送邮箱验证码。
SendEmailCode(context.Context, *SendEmailCodeRequest) (*emptypb.Empty, error)
}
// UnimplementedUserAPIServer can be embedded to have forward compatible implementations.
@ -1864,6 +1986,9 @@ func (*UnimplementedUserAPIServer) FindPasswordStepOne(ctx context.Context, req
func (*UnimplementedUserAPIServer) FindPasswordStepTwo(ctx context.Context, req *FindPasswordRequest) (*emptypb.Empty, error) {
return nil, status.Errorf(codes.Unimplemented, "method FindPasswordStepTwo not implemented")
}
func (*UnimplementedUserAPIServer) SendEmailCode(ctx context.Context, req *SendEmailCodeRequest) (*emptypb.Empty, error) {
return nil, status.Errorf(codes.Unimplemented, "method SendEmailCode not implemented")
}
func RegisterUserAPIServer(s *grpc.Server, srv UserAPIServer) {
s.RegisterService(&_UserAPI_serviceDesc, srv)
@ -2211,6 +2336,24 @@ func _UserAPI_FindPasswordStepTwo_Handler(srv interface{}, ctx context.Context,
return interceptor(ctx, in, info, handler)
}
func _UserAPI_SendEmailCode_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(SendEmailCodeRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(UserAPIServer).SendEmailCode(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/api.v1.UserAPI/SendEmailCode",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(UserAPIServer).SendEmailCode(ctx, req.(*SendEmailCodeRequest))
}
return interceptor(ctx, in, info, handler)
}
var _UserAPI_serviceDesc = grpc.ServiceDesc{
ServiceName: "api.v1.UserAPI",
HandlerType: (*UserAPIServer)(nil),
@ -2291,6 +2434,10 @@ var _UserAPI_serviceDesc = grpc.ServiceDesc{
MethodName: "FindPasswordStepTwo",
Handler: _UserAPI_FindPasswordStepTwo_Handler,
},
{
MethodName: "SendEmailCode",
Handler: _UserAPI_SendEmailCode_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "api/v1/user.proto",
@ -2512,6 +2659,13 @@ func (m *RegisterAndLoginRequest) MarshalToSizedBuffer(dAtA []byte) (int, error)
_ = i
var l int
_ = l
if len(m.Code) > 0 {
i -= len(m.Code)
copy(dAtA[i:], m.Code)
i = encodeVarintUser(dAtA, i, uint64(len(m.Code)))
i--
dAtA[i] = 0x32
}
if len(m.Email) > 0 {
i -= len(m.Email)
copy(dAtA[i:], m.Email)
@ -2550,6 +2704,55 @@ func (m *RegisterAndLoginRequest) MarshalToSizedBuffer(dAtA []byte) (int, error)
return len(dAtA) - i, nil
}
func (m *SendEmailCodeRequest) Marshal() (dAtA []byte, err error) {
size := m.Size()
dAtA = make([]byte, size)
n, err := m.MarshalToSizedBuffer(dAtA[:size])
if err != nil {
return nil, err
}
return dAtA[:n], nil
}
func (m *SendEmailCodeRequest) MarshalTo(dAtA []byte) (int, error) {
size := m.Size()
return m.MarshalToSizedBuffer(dAtA[:size])
}
func (m *SendEmailCodeRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) {
i := len(dAtA)
_ = i
var l int
_ = l
if m.Type != 0 {
i = encodeVarintUser(dAtA, i, uint64(m.Type))
i--
dAtA[i] = 0x20
}
if len(m.CaptchaId) > 0 {
i -= len(m.CaptchaId)
copy(dAtA[i:], m.CaptchaId)
i = encodeVarintUser(dAtA, i, uint64(len(m.CaptchaId)))
i--
dAtA[i] = 0x1a
}
if len(m.Captcha) > 0 {
i -= len(m.Captcha)
copy(dAtA[i:], m.Captcha)
i = encodeVarintUser(dAtA, i, uint64(len(m.Captcha)))
i--
dAtA[i] = 0x12
}
if len(m.Email) > 0 {
i -= len(m.Email)
copy(dAtA[i:], m.Email)
i = encodeVarintUser(dAtA, i, uint64(len(m.Email)))
i--
dAtA[i] = 0xa
}
return len(dAtA) - i, nil
}
func (m *GetUserCaptchaRequest) Marshal() (dAtA []byte, err error) {
size := m.Size()
dAtA = make([]byte, size)
@ -3522,6 +3725,34 @@ func (m *RegisterAndLoginRequest) Size() (n int) {
if l > 0 {
n += 1 + l + sovUser(uint64(l))
}
l = len(m.Code)
if l > 0 {
n += 1 + l + sovUser(uint64(l))
}
return n
}
func (m *SendEmailCodeRequest) Size() (n int) {
if m == nil {
return 0
}
var l int
_ = l
l = len(m.Email)
if l > 0 {
n += 1 + l + sovUser(uint64(l))
}
l = len(m.Captcha)
if l > 0 {
n += 1 + l + sovUser(uint64(l))
}
l = len(m.CaptchaId)
if l > 0 {
n += 1 + l + sovUser(uint64(l))
}
if m.Type != 0 {
n += 1 + sovUser(uint64(m.Type))
}
return n
}
@ -4803,6 +5034,203 @@ func (m *RegisterAndLoginRequest) Unmarshal(dAtA []byte) error {
}
m.Email = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
case 6:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Code", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowUser
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthUser
}
postIndex := iNdEx + intStringLen
if postIndex < 0 {
return ErrInvalidLengthUser
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Code = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipUser(dAtA[iNdEx:])
if err != nil {
return err
}
if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthUser
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func (m *SendEmailCodeRequest) Unmarshal(dAtA []byte) error {
l := len(dAtA)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowUser
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: SendEmailCodeRequest: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: SendEmailCodeRequest: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Email", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowUser
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthUser
}
postIndex := iNdEx + intStringLen
if postIndex < 0 {
return ErrInvalidLengthUser
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Email = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
case 2:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Captcha", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowUser
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthUser
}
postIndex := iNdEx + intStringLen
if postIndex < 0 {
return ErrInvalidLengthUser
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Captcha = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
case 3:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field CaptchaId", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowUser
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthUser
}
postIndex := iNdEx + intStringLen
if postIndex < 0 {
return ErrInvalidLengthUser
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.CaptchaId = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
case 4:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field Type", wireType)
}
m.Type = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowUser
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
m.Type |= EmailCodeType(b&0x7F) << shift
if b < 0x80 {
break
}
}
default:
iNdEx = preIndex
skippy, err := skipUser(dAtA[iNdEx:])

@ -612,6 +612,40 @@ func local_request_UserAPI_FindPasswordStepTwo_0(ctx context.Context, marshaler
}
func request_UserAPI_SendEmailCode_0(ctx context.Context, marshaler runtime.Marshaler, client UserAPIClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq SendEmailCodeRequest
var metadata runtime.ServerMetadata
newReader, berr := utilities.IOReaderFactory(req.Body)
if berr != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
}
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
msg, err := client.SendEmailCode(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return msg, metadata, err
}
func local_request_UserAPI_SendEmailCode_0(ctx context.Context, marshaler runtime.Marshaler, server UserAPIServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq SendEmailCodeRequest
var metadata runtime.ServerMetadata
newReader, berr := utilities.IOReaderFactory(req.Body)
if berr != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
}
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
msg, err := server.SendEmailCode(ctx, &protoReq)
return msg, metadata, err
}
// RegisterUserAPIHandlerServer registers the http handlers for service UserAPI to "mux".
// UnaryRPC :call UserAPIServer directly.
// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.
@ -1055,6 +1089,29 @@ func RegisterUserAPIHandlerServer(ctx context.Context, mux *runtime.ServeMux, se
})
mux.Handle("POST", pattern_UserAPI_SendEmailCode_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
var stream runtime.ServerTransportStream
ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := local_request_UserAPI_SendEmailCode_0(rctx, inboundMarshaler, server, req, pathParams)
md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_UserAPI_SendEmailCode_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
return nil
}
@ -1476,6 +1533,26 @@ func RegisterUserAPIHandlerClient(ctx context.Context, mux *runtime.ServeMux, cl
})
mux.Handle("POST", pattern_UserAPI_SendEmailCode_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
rctx, err := runtime.AnnotateContext(ctx, mux, req)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := request_UserAPI_SendEmailCode_0(rctx, inboundMarshaler, client, req, pathParams)
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_UserAPI_SendEmailCode_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
return nil
}
@ -1517,6 +1594,8 @@ var (
pattern_UserAPI_FindPasswordStepOne_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4}, []string{"api", "v1", "user", "findpassword", "stepone"}, "", runtime.AssumeColonVerbOpt(true)))
pattern_UserAPI_FindPasswordStepTwo_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4}, []string{"api", "v1", "user", "findpassword", "steptwo"}, "", runtime.AssumeColonVerbOpt(true)))
pattern_UserAPI_SendEmailCode_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4}, []string{"api", "v1", "user", "email", "code"}, "", runtime.AssumeColonVerbOpt(true)))
)
var (
@ -1557,4 +1636,6 @@ var (
forward_UserAPI_FindPasswordStepOne_0 = runtime.ForwardResponseMessage
forward_UserAPI_FindPasswordStepTwo_0 = runtime.ForwardResponseMessage
forward_UserAPI_SendEmailCode_0 = runtime.ForwardResponseMessage
)

@ -51,6 +51,20 @@ message RegisterAndLoginRequest {
string captcha = 3; //
string captcha_id = 4; // ID
string email = 5; //
string code = 6; // ()
}
enum EmailCodeType {
EmailCodeTypeRegister = 0; //
EmailCodeTypeLogin = 1; //
// EmailCodeTypeFindPassword = 2; //
}
message SendEmailCodeRequest {
string email = 1; //
string captcha = 2;
string captcha_id = 3;
EmailCodeType type = 4;
}
//
@ -324,4 +338,12 @@ service UserAPI {
body : '*',
};
}
//
rpc SendEmailCode(SendEmailCodeRequest) returns (google.protobuf.Empty) {
option (google.api.http) = {
post : '/api/v1/user/email/code',
body : '*',
};
}
}

@ -38,6 +38,11 @@ type AttachmentAPIService struct {
logger *zap.Logger
}
var errorHash = map[string]interface{}{
"code": http.StatusBadRequest,
"message": "hash值必须32位",
}
func NewAttachmentAPIService(dbModel *model.DBModel, logger *zap.Logger) (service *AttachmentAPIService) {
return &AttachmentAPIService{dbModel: dbModel, logger: logger.Named("AttachmentAPIService")}
}
@ -243,7 +248,7 @@ func (s *AttachmentAPIService) UploadConfig(ctx *gin.Context) {
func (s *AttachmentAPIService) ViewDocumentPages(ctx *gin.Context) {
hash := ctx.Param("hash")
if len(hash) != 32 {
ctx.JSON(http.StatusNotFound, nil)
ctx.JSON(http.StatusNotFound, errorHash)
return
}
page := strings.TrimLeft(ctx.Param("page"), "./")
@ -261,6 +266,11 @@ func (s *AttachmentAPIService) ViewDocumentPages(ctx *gin.Context) {
func (s *AttachmentAPIService) ViewDocumentCover(ctx *gin.Context) {
hash := ctx.Param("hash")
if len(hash) != 32 {
ctx.JSON(http.StatusNotFound, errorHash)
return
}
file := fmt.Sprintf("documents/%s/%s/cover.png", strings.Join(strings.Split(hash, "")[:5], "/"), hash)
if len(hash) != 32 {
ctx.JSON(http.StatusNotFound, map[string]interface{}{"code": http.StatusNotFound, "message": "文件不存在"})
@ -278,10 +288,11 @@ func (s *AttachmentAPIService) DownloadDocument(ctx *gin.Context) {
jwtToken, err := jwt.ParseWithClaims(token, claims, func(t *jwt.Token) (interface{}, error) {
return []byte(cfg.SecretKey), nil
})
if err != nil || !jwtToken.Valid {
if err != nil || !jwtToken.Valid || len(claims.Id) != 32 {
ctx.String(http.StatusBadRequest, "下载链接已失效")
return
}
filename := ctx.Query("filename")
file := fmt.Sprintf("documents/%s/%s%s", strings.Join(strings.Split(claims.Id, "")[:5], "/"), claims.Id, filepath.Ext(filename))
ctx.FileAttachment(file, filename)

@ -43,7 +43,7 @@ func (s *CommentAPIService) CreateComment(ctx context.Context, req *pb.CreateCom
// 评论验证码错误
cfg := s.dbModel.GetConfigOfSecurity(model.ConfigSecurityEnableCaptchaComment)
if cfg.EnableCaptchaComment && !captcha.VerifyCaptcha(req.CaptchaId, req.Captcha) {
if cfg.EnableCaptchaComment && !captcha.VerifyCaptcha(req.CaptchaId, req.Captcha, true) {
return nil, status.Errorf(codes.InvalidArgument, "验证码错误")
}

@ -51,9 +51,10 @@ func (s *ConfigAPIService) UpdateConfig(ctx context.Context, req *pb.Configs) (*
doesUpdateSEO := false
isEmail := false
for idx, cfg := range cfgs {
if cfg.Category == model.ConfigCategoryEmail && cfg.Name == model.ConfigEmailPassword && cfg.Value == "******" {
// 6个星号不修改密码
cfgs[idx].Value = s.dbModel.GetConfigOfEmail(model.ConfigEmailPassword).Password
if cfg.Value == "******" {
// 6个星号不修改原值
exist, _ := s.dbModel.GetConfigByNameCategory(cfg.Name, cfg.Category)
cfgs[idx].Value = exist.Value
}
isEmail = isEmail || cfg.Category == model.ConfigCategoryEmail
if cfg.Category == model.ConfigCategorySystem {
@ -101,15 +102,15 @@ func (s *ConfigAPIService) ListConfig(ctx context.Context, req *pb.ListConfigReq
return nil, status.Error(codes.Internal, err.Error())
}
var pbConfigs []*pb.Config
util.CopyStruct(&configs, &pbConfigs)
for idx, cfg := range pbConfigs {
if cfg.Category == model.ConfigCategoryEmail && cfg.Name == model.ConfigEmailPassword {
pbConfigs[idx].Value = "******"
for idx, cfg := range configs {
if cfg.IsSecret && cfg.Value != "" {
configs[idx].Value = "******"
}
}
var pbConfigs []*pb.Config
util.CopyStruct(&configs, &pbConfigs)
return &pb.Configs{Config: pbConfigs}, nil
}
@ -237,12 +238,19 @@ func (s *ConfigAPIService) GetEnvs(ctx context.Context, req *emptypb.Empty) (res
Cmd: "mutool",
IsRequired: true,
},
{
// mupdf
Name: "ImageMagick",
Description: "ImageMagick是一个用于创建、编辑、合成和转换位图图像的自由软件套件。魔豆文库用于将PDF转为svg、png、jpg等图片。",
Cmd: "convert",
IsRequired: true,
},
{
// inkscape
Name: "Inkscape",
Description: "Inkscape是一个自由开源的矢量图形编辑器。在mupdf处理PDF出现兼容问题失败时自动切换inkscape来处理。",
Cmd: "inkscape",
IsRequired: false,
IsRequired: true,
},
{
Name: "SVGO",

@ -72,6 +72,7 @@ func (s *UserAPIService) Register(ctx context.Context, req *pb.RegisterAndLoginR
model.ConfigSecurityEnableCaptchaRegister,
model.ConfigSecurityEnableRegister,
model.ConfigSecurityIsClose,
model.ConfigSecurityEnableVerifyRegisterEmail,
)
if !cfg.EnableRegister {
@ -82,10 +83,23 @@ func (s *UserAPIService) Register(ctx context.Context, req *pb.RegisterAndLoginR
return nil, status.Errorf(codes.InvalidArgument, "网站已关闭,暂时不允许注册")
}
if cfg.EnableCaptchaRegister && !captcha.VerifyCaptcha(req.CaptchaId, req.Captcha) {
if cfg.EnableCaptchaRegister && !captcha.VerifyCaptcha(req.CaptchaId, req.Captcha, true) {
return nil, status.Errorf(codes.InvalidArgument, "验证码错误")
}
var latestEmailCode model.EmailCode
if cfg.EnableVerifyRegisterEmail { // 启用了邮箱验证
latestEmailCode = s.dbModel.GetLatestEmailCode(req.Email, int32(pb.EmailCodeType_EmailCodeTypeRegister))
if latestEmailCode.Id == 0 || latestEmailCode.Code != req.Code || latestEmailCode.IsUsed {
return nil, status.Errorf(codes.InvalidArgument, "邮箱验证码错误")
}
// 邮箱验证码是否已过期
if latestEmailCode.CreatedAt.Add(time.Minute * 30).Before(time.Now()) {
return nil, status.Errorf(codes.InvalidArgument, "邮箱验证码已过期")
}
}
exist, _ := s.dbModel.GetUserByUsername(req.Username, "id")
if exist.Id > 0 {
return nil, status.Errorf(codes.AlreadyExists, "用户名已存在")
@ -133,6 +147,11 @@ func (s *UserAPIService) Register(ctx context.Context, req *pb.RegisterAndLoginR
pbUser := &pb.User{}
util.CopyStruct(&user, pbUser)
if latestEmailCode.Id > 0 {
// 标记邮箱验证码已使用
s.dbModel.UpdateEmailCode(&model.EmailCode{Id: latestEmailCode.Id, IsUsed: true}, "is_used")
}
return &pb.LoginReply{Token: token, User: pbUser}, nil
}
@ -146,7 +165,7 @@ func (s *UserAPIService) Login(ctx context.Context, req *pb.RegisterAndLoginRequ
// 如果启用了验证码,则需要进行验证码验证
cfg := s.dbModel.GetConfigOfSecurity(model.ConfigSecurityEnableCaptchaLogin)
if cfg.EnableCaptchaLogin && !captcha.VerifyCaptcha(req.CaptchaId, req.Captcha) {
if cfg.EnableCaptchaLogin && !captcha.VerifyCaptcha(req.CaptchaId, req.Captcha, true) {
return nil, status.Errorf(codes.InvalidArgument, "验证码错误")
}
@ -633,7 +652,7 @@ func (s *UserAPIService) FindPasswordStepOne(ctx context.Context, req *v1.FindPa
}
cfgSec := s.dbModel.GetConfigOfSecurity(model.ConfigSecurityEnableCaptchaFindPassword)
if cfgSec.EnableCaptchaFindPassword && !captcha.VerifyCaptcha(req.CaptchaId, req.Captcha) {
if cfgSec.EnableCaptchaFindPassword && !captcha.VerifyCaptcha(req.CaptchaId, req.Captcha, true) {
return nil, status.Errorf(codes.InvalidArgument, "验证码错误")
}
@ -709,7 +728,7 @@ func (s *UserAPIService) FindPasswordStepTwo(ctx context.Context, req *v1.FindPa
}
cfgSec := s.dbModel.GetConfigOfSecurity(model.ConfigSecurityEnableCaptchaFindPassword)
if cfgSec.EnableCaptchaFindPassword && !captcha.VerifyCaptcha(req.CaptchaId, req.Captcha) {
if cfgSec.EnableCaptchaFindPassword && !captcha.VerifyCaptcha(req.CaptchaId, req.Captcha, true) {
return nil, status.Errorf(codes.InvalidArgument, "验证码错误")
}
@ -762,3 +781,83 @@ func (s *UserAPIService) ListUserDownload(ctx context.Context, req *v1.ListUserD
}
return &v1.ListUserDownloadReply{Download: downloads, Total: total}, nil
}
// 发送邮箱验证码
// TODO: 当前只对注册功能生效。后续可以考虑对其他功能
func (s *UserAPIService) SendEmailCode(ctx context.Context, req *v1.SendEmailCodeRequest) (res *emptypb.Empty, err error) {
if !util.IsValidEmail(req.Email) {
return nil, status.Errorf(codes.InvalidArgument, "邮箱格式不正确")
}
existUser, _ := s.dbModel.GetUserByEmail(req.Email, "id")
if existUser.Id > 0 {
return nil, status.Errorf(codes.AlreadyExists, "邮箱已存在")
}
cfgSec := s.dbModel.GetConfigOfSecurity(model.ConfigSecurityEnableCaptchaRegister, model.ConfigSecurityEnableRegister, model.ConfigSecurityEnableVerifyRegisterEmail)
if !cfgSec.EnableRegister {
return nil, status.Errorf(codes.InvalidArgument, "系统未开放注册")
}
if !cfgSec.EnableVerifyRegisterEmail {
return nil, status.Errorf(codes.InvalidArgument, "系统未开启注册邮箱验证功能")
}
if cfgSec.EnableCaptchaRegister && !captcha.VerifyCaptcha(req.CaptchaId, req.Captcha, false) {
return nil, status.Errorf(codes.InvalidArgument, "验证码错误")
}
code := s.dbModel.GetLatestEmailCode(req.Email, int32(req.Type))
// 如果邮件发送早于1分钟则不再发送
if code.Id > 0 && time.Now().Sub(*code.CreatedAt).Seconds() < 60 {
return nil, status.Errorf(codes.InvalidArgument, "发送太频繁,请稍后再试")
}
ip := ""
if ips, _ := util.GetGRPCRemoteIP(ctx); len(ips) > 0 {
ip = ips[0]
}
cfgSystem := s.dbModel.GetConfigOfSystem(model.ConfigSystemSitename, model.ConfigSystemDomain)
codeStr := unchained.GetRandomString(4)
body := fmt.Sprintf(`
<div class="wrapper" style="margin: 20px auto 0; width: 500px; padding-top:16px; padding-bottom:10px;">
<div class="content" style="background: none repeat scroll 0 0 #FFFFFF; border: 1px solid #E9E9E9; margin: 2px 0 0; padding: 30px;">
<p>: </p>
<p> <a href="%s">%s</a> %s30 </p>
</div>
</div>
`,
cfgSystem.Domain,
cfgSystem.Sitename,
codeStr,
)
// 发送邮件
err = s.dbModel.SendMail(
"邮箱验证码",
req.Email,
body,
)
// 生成验证码
code = model.EmailCode{
Email: req.Email,
Code: codeStr,
Ip: ip,
Success: true,
}
if err != nil {
code.Error = err.Error()
code.Success = false
}
err = s.dbModel.CreateEmailCode(&code)
if err != nil {
s.logger.Error("创建验证码失败", zap.Error(err))
return nil, status.Errorf(codes.Internal, err.Error())
}
return &emptypb.Empty{}, nil
}

@ -0,0 +1,66 @@
/*
Copyright © 2023 NAME HERE <EMAIL ADDRESS>
*/
package cmd
import (
"fmt"
"moredoc/service"
"strings"
"github.com/spf13/cobra"
)
var (
ext string // 指定的文件后缀png、jpg、webp
documentId int64 // 指定的文档ID, 0表示全部大于0表示指定文档
)
// reconvertCmd represents the reconvert command
var reconvertCmd = &cobra.Command{
Use: "reconvert",
Short: "文档重转",
Long: `pngjpgwebp便
pngjpgwebp
`,
Run: func(cmd *cobra.Command, args []string) {
// ext必须是png、jpg、webp中的一种
ext = strings.ToLower(ext)
if ext != "png" && ext != "jpg" && ext != "webp" {
ext = "webp"
}
// 必须指定documentId
if documentId < 0 {
fmt.Println("\n请用--id指定的文档ID, 0表示全部大于0表示指定文档。如需重转全部文档建议先指定一个文档进行测试查验效果是否符合需求。")
fmt.Println("\n按回车键退出...")
fmt.Scanln()
return
}
// 提示用户输入Y确认否则退出
fmt.Println("\n请确认是否重转文档")
if documentId == 0 {
fmt.Print("转换文档:全部文档")
} else {
fmt.Print("转换文档ID", documentId)
}
fmt.Println(";文档预览格式:", ext)
fmt.Println("按 Y 确认,按其他键取消和退出...")
var confirm string
fmt.Scanln(&confirm)
if confirm != "Y" && confirm != "y" {
fmt.Println("\n已取消重转文档。")
return
}
service.Reconvert(cfg, logger, ext, documentId)
},
}
func init() {
rootCmd.AddCommand(reconvertCmd)
reconvertCmd.Flags().StringVarP(&ext, "ext", "e", "webp", "指定的文档预览格式png、jpg、webp")
reconvertCmd.Flags().Int64VarP(&documentId, "id", "d", -1, "指定的文档ID, 0表示全部大于0表示指定文档。如需重转全部文档建议先指定一个文档进行测试查验效果是否符合需求。")
}

@ -39,13 +39,8 @@ var (
// rootCmd represents the base command when called without any subcommands
var rootCmd = &cobra.Command{
Use: "moredoc",
Short: "A brief description of your application",
Long: `A longer description that spans multiple lines and likely contains
examples and usage of using your application. For example:
Cobra is a CLI library for Go that empowers applications.
This application is a tool to generate the needed files
to quickly create a Cobra application.`,
Short: "魔豆文库,文库系统解决方案",
Long: `魔豆文库使用Go语言开发的类似百度文库、新浪爱问文库的文库系统解决方案支持 TXT、PDF、EPUB、MOBI、Office 等格式文档的在线预览与管理,为 dochub文库的重构版本。`,
}
// Execute adds all child commands to the root command and sets flags appropriately.

@ -30,8 +30,8 @@ import (
// serveCmd represents the serve command
var serveCmd = &cobra.Command{
Use: "serve",
Short: "start a server",
Long: `start a server`,
Short: "启动服务",
Long: `启动魔豆文库程序服务,提供文档管理与预览。`,
Run: func(cmd *cobra.Command, args []string) {
util.Version = Version
util.Hash = GitHash

@ -5,7 +5,7 @@ Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
@ -24,8 +24,8 @@ import (
// syncdbCmd represents the syncdb command
var syncdbCmd = &cobra.Command{
Use: "syncdb",
Short: "sync database scheme",
Long: `sync database scheme.`,
Short: "同步数据库",
Long: `同步数据库表结构以及初始化数据。`,
Run: func(cmd *cobra.Command, args []string) {
service.SyncDB(cfg, logger)
},

@ -5,7 +5,7 @@ Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
@ -27,11 +27,11 @@ var (
BuildAt = "unknown"
)
//versionCmd represents the version command
// versionCmd represents the version command
var versionCmd = &cobra.Command{
Use: "version",
Short: "show current version information.",
Long: `show current version information.`,
Short: "查看版本信息",
Long: `查看魔豆文库版本信息如版本号、构建时间、Git提交哈希值等。`,
Run: func(cmd *cobra.Command, args []string) {
fmt.Println("")
fmt.Println("AppName: ", "moredoc")

@ -63,6 +63,7 @@ type Config struct {
Options string `form:"options" json:"options,omitempty" gorm:"column:options;type:text;comment:针对checkbox等的枚举值;"`
CreatedAt *time.Time `form:"created_at" json:"created_at,omitempty" gorm:"column:created_at;type:datetime;comment:创建时间;"`
UpdatedAt *time.Time `form:"updated_at" json:"updated_at,omitempty" gorm:"column:updated_at;type:datetime;comment:更新时间;"`
IsSecret bool `form:"is_secret" json:"is_secret,omitempty" gorm:"column:is_secret;type:tinyint(1);size:1;default:0;comment:是否是私密信息;"`
}
func (Config) TableName() string {
@ -243,6 +244,7 @@ const (
ConfigSecurityDocumentAllowedExt = "document_allowed_ext" // 允许上传的文档类型
ConfigSecurityLoginRequired = "login_required" // 是否需要登录才能查看文档
ConfigSecurityAttachmentRetentionMinute = "attachment_retention_minute" // 被删除的附件,保留时长,单位分钟
ConfigSecurityEnableVerifyRegisterEmail = "enable_verify_register_email" // 是否开启注册邮箱验证
)
type ConfigSecurity struct {
@ -257,6 +259,7 @@ type ConfigSecurity struct {
EnableCaptchaRegister bool `json:"enable_captcha_register"` // 是否启用注册验证码
EnableCaptchaComment bool `json:"enable_captcha_comment"` // 是否启用评论验证码
EnableCaptchaFindPassword bool `json:"enable_captcha_find_password"` // 找回密码是否需要验证码
EnableVerifyRegisterEmail bool `json:"enable_verify_register_email"` // 是否开启注册邮箱验证
DocumentAllowedExt []string `json:"document_allowed_ext"` // 允许上传的文档类型
LoginRequired bool `json:"login_required"` // 是否需要登录才能查看文档
}
@ -655,6 +658,7 @@ func (m *DBModel) initConfig() (err error) {
cfgs := []Config{
// 系统配置项
{Category: ConfigCategorySystem, Name: ConfigSystemSitename, Label: "网站名称", Value: "魔豆文库", Placeholder: "请输入您网站的名称,如:魔豆文库", InputType: InputTypeText, Sort: 10, Options: ""},
{Category: ConfigCategorySystem, Name: ConfigSystemDomain, Label: "【重要】网站域名", Value: "https://moredoc.mnt.ltd", Placeholder: "请输入您网站的域名访问地址,带 https:// 或 http:// 如 https://moredoc.mnt.ltd用以生成网站地图sitemap", InputType: InputTypeText, Sort: 11, Options: ""},
{Category: ConfigCategorySystem, Name: ConfigSystemTitle, Label: "首页标题", Value: "MOREDOC · 魔豆文库", Placeholder: "请输入您网站的首页标题,如:魔豆文库,强大、专业的文库系统", InputType: InputTypeText, Sort: 20, Options: ""},
{Category: ConfigCategorySystem, Name: ConfigSystemKeywords, Label: "网站关键字", Value: "MOREDOC · 魔豆文库", Placeholder: "请输入您网站的关键字", InputType: InputTypeText, Sort: 30, Options: ""},
{Category: ConfigCategorySystem, Name: ConfigSystemDescription, Label: "网站描述", Value: "MOREDOC · 魔豆文库", Placeholder: "请输入您网站的描述", InputType: InputTypeTextarea, Sort: 40, Options: ""},
@ -665,7 +669,6 @@ func (m *DBModel) initConfig() (err error) {
{Category: ConfigCategorySystem, Name: ConfigSystemLoginBackground, Label: "登录页背景图", Value: "", Placeholder: "请上传一张图片作为登录页背景图", InputType: InputTypeImage, Sort: 63, Options: ""},
{Category: ConfigCategorySystem, Name: ConfigSystemSecIcp, Label: "京公网安备", Value: "", Placeholder: "请输入您网站的京公网安备备案号", InputType: InputTypeText, Sort: 68, Options: ""},
{Category: ConfigCategorySystem, Name: ConfigSystemIcp, Label: "网站备案号", Value: "", Placeholder: "请输入您网站的备案号", InputType: InputTypeText, Sort: 69, Options: ""},
{Category: ConfigCategorySystem, Name: ConfigSystemDomain, Label: "网站域名", Value: "https://moredoc.mnt.ltd", Placeholder: "请输入您网站的域名访问地址,带 https:// 或 http:// 如 https://moredoc.mnt.ltd用以生成网站地图sitemap", InputType: InputTypeText, Sort: 70, Options: ""},
{Category: ConfigCategorySystem, Name: ConfigSystemCopyrightStartYear, Label: "版权起始年", Value: "2019", Placeholder: "请输入您网站版权起始年2019则前台会显示如 ©2019 - 20xx 的字样", InputType: InputTypeText, Sort: 80, Options: ""},
{Category: ConfigCategorySystem, Name: ConfigSystemAnalytics, Label: "网站统计代码", Value: "", Placeholder: "请输入您网站的统计代码,当前只支持百度统计", InputType: InputTypeTextarea, Sort: 90, Options: ""},
@ -689,6 +692,7 @@ func (m *DBModel) initConfig() (err error) {
{Category: ConfigCategorySecurity, Name: ConfigSecurityEnableCaptchaRegister, Label: "是否开启注册验证码", Value: "true", Placeholder: "请选择是否开启注册验证码", InputType: InputTypeSwitch, Sort: 20, Options: ""},
{Category: ConfigCategorySecurity, Name: ConfigSecurityEnableCaptchaComment, Label: "是否开启评论验证码", Value: "true", Placeholder: "请选择是否开启评论验证码", InputType: InputTypeSwitch, Sort: 21, Options: ""},
{Category: ConfigCategorySecurity, Name: ConfigSecurityEnableCaptchaFindPassword, Label: "是否开启找回密码验证码", Value: "true", Placeholder: "请选择是否开启找回密码验证码", InputType: InputTypeSwitch, Sort: 22, Options: ""},
{Category: ConfigCategorySecurity, Name: ConfigSecurityEnableVerifyRegisterEmail, Label: "是否开启注册邮箱验证", Value: "false", Placeholder: "用户注册时是否需要验证邮箱", InputType: InputTypeSwitch, Sort: 50, Options: ""},
// 底部链接
{Category: ConfigCategoryFooter, Name: ConfigFooterAbout, Label: "关于我们", Value: "/article/about", Placeholder: "请输入关于我们的链接地址,留空表示不显示", InputType: InputTypeText, Sort: 24, Options: ""},
@ -700,7 +704,7 @@ func (m *DBModel) initConfig() (err error) {
// 转换配置项
{Category: ConfigCategoryConverter, Name: ConfigConverterMaxPreview, Label: "最大预览页数", Value: "12", Placeholder: "文档允许的最大预览页数0表示不限制", InputType: InputTypeNumber, Sort: 0, Options: ""},
{Category: ConfigCategoryConverter, Name: ConfigConverterTimeout, Label: "转换超时(分钟)", Value: "30", Placeholder: "文档转换超时时间默认为30分钟", InputType: InputTypeNumber, Sort: 10, Options: ""},
{Category: ConfigCategoryConverter, Name: ConfigConverterExtension, Label: "预览格式", Value: "svg", Placeholder: "将文档转为特定格式以供预览", InputType: InputTypeSelect, Sort: 20, Options: "svg:SVG\njpg:JPEG\npng:PNG"},
{Category: ConfigCategoryConverter, Name: ConfigConverterExtension, Label: "预览格式", Value: "svg", Placeholder: "将文档转为特定格式以供预览", InputType: InputTypeSelect, Sort: 20, Options: "svg:SVG\njpg:JPEG\npng:PNG\nwebp:WEBP"},
{Category: ConfigCategoryConverter, Name: ConfigConverterEnableGZIP, Label: "是否启用GZIP压缩", Value: "true", Placeholder: "是否对文档SVG预览文件启用GZIP压缩启用后转换效率会【稍微】下降但相对直接的SVG文件减少75%的存储空间", InputType: InputTypeSwitch, Sort: 30, Options: ""},
{Category: ConfigCategoryConverter, Name: ConfigConverterEnableSVGO, Label: "是否启用SVGO", Value: "false", Placeholder: "是否对文档SVG预览文件启用SVGO压缩启用后转换效率会【明显】下降但相对直接的SVG文件减少50%左右的存储空间", InputType: InputTypeSwitch, Sort: 40, Options: ""},
{Category: ConfigCategoryConverter, Name: ConfigConverterEnableConvertRepeatedDocument, Label: "是否转换重复文档", Value: "false", Placeholder: "对于已转换过的文档,再次被上传时是否再转换一次", InputType: InputTypeSwitch, Sort: 50, Options: ""},
@ -732,7 +736,7 @@ func (m *DBModel) initConfig() (err error) {
{Category: ConfigCategoryEmail, Name: ConfigEmailIsTLS, Label: "是否启用TLS", Value: "true", Placeholder: "如果是TLS端口请启用", InputType: InputTypeSwitch, Sort: 40, Options: ""},
{Category: ConfigCategoryEmail, Name: ConfigEmailFromName, Label: "发件人名称", Value: "", Placeholder: "请输入您要展示的发件人名称", InputType: InputTypeText, Sort: 50, Options: ""},
{Category: ConfigCategoryEmail, Name: ConfigEmailUsername, Label: "SMTP 账号", Value: "", Placeholder: "请输入您的邮箱账户", InputType: InputTypeText, Sort: 60, Options: ""},
{Category: ConfigCategoryEmail, Name: ConfigEmailPassword, Label: "SMTP 密码", Value: "", Placeholder: "请输入您的邮箱密码", InputType: InputTypePassword, Sort: 70, Options: ""},
{Category: ConfigCategoryEmail, Name: ConfigEmailPassword, Label: "SMTP 密码", Value: "", Placeholder: "请输入您的邮箱密码", InputType: InputTypePassword, Sort: 70, Options: "", IsSecret: true},
{Category: ConfigCategoryEmail, Name: ConfigEmailDuration, Label: "邮件有效期", Value: "30", Placeholder: "找回密码时链接有效期默认为30表示30分钟", InputType: InputTypeNumber, Sort: 80, Options: ""},
{Category: ConfigCategoryEmail, Name: ConfigEmailSecret, Label: "签名密钥", Value: "moredoc", Placeholder: "找回密码链接签名密钥", InputType: InputTypeText, Sort: 80, Options: ""},
{Category: ConfigCategoryEmail, Name: ConfigEmailTestEmail, Label: "测试邮箱", Value: "", Placeholder: "用于每次变更配置时保存发送测试邮件", InputType: InputTypeText, Sort: 90, Options: ""},

@ -740,7 +740,7 @@ func (m *DBModel) ConvertDocument() (err error) {
document.Status = DocumentStatusConverted
document.EnableGZIP = cfg.EnableGZIP
document.PreviewExt = ext
document.PreviewExt = strings.TrimPrefix(ext, ".gzip")
err = m.db.Select("description", "cover", "width", "height", "preview", "pages", "status", "enable_gzip", "preview_ext").Where("id = ?", document.Id).Updates(document).Error
if err != nil {
m.SetDocumentStatus(document.Id, DocumentStatusFailed)

@ -0,0 +1,133 @@
package model
import (
"time"
"go.uber.org/zap"
"gorm.io/gorm"
)
type EmailCode struct {
Id int64 `form:"id" json:"id,omitempty" gorm:"primaryKey;autoIncrement;column:id;comment:;"`
Email string `form:"email" json:"email,omitempty" gorm:"column:email;type:varchar(64);size:64;index:idx_email;comment:邮箱;"`
Ip string `form:"ip" json:"ip,omitempty" gorm:"column:ip;type:varchar(64);size:64;comment:IP地址;"`
Code string `form:"code" json:"code,omitempty" gorm:"column:code;type:varchar(16);size:16;comment:邮箱验证码;"`
CodeType int `form:"code_type" json:"code_type,omitempty" gorm:"column:code_type;type:smallint(6);size:6;default:0;comment:验证码类型,0注册,1登录;"`
Success bool `form:"success" json:"success,omitempty" gorm:"column:success;type:tinyint(1);size:1;default:0;comment:是否发送成功;"`
Error string `form:"error" json:"error,omitempty" gorm:"column:error;type:text;comment:错误信息;"`
CreatedAt *time.Time `form:"created_at" json:"created_at,omitempty" gorm:"column:created_at;type:datetime;comment:;"`
UpdatedAt *time.Time `form:"updated_at" json:"updated_at,omitempty" gorm:"column:updated_at;type:datetime;comment:;"`
IsUsed bool `form:"is_used" json:"is_used,omitempty" gorm:"column:is_used;type:tinyint(1);size:1;default:0;comment:是否已使用;"`
}
func (EmailCode) TableName() string {
return tablePrefix + "email_code"
}
// CreateEmailCode 创建EmailCode
func (m *DBModel) CreateEmailCode(emailCode *EmailCode) (err error) {
err = m.db.Create(emailCode).Error
if err != nil {
m.logger.Error("CreateEmailCode", zap.Error(err))
return
}
return
}
// UpdateEmailCode 更新EmailCode如果需要更新指定字段则请指定updateFields参数
func (m *DBModel) UpdateEmailCode(emailCode *EmailCode, updateFields ...string) (err error) {
db := m.db.Model(emailCode)
tableName := EmailCode{}.TableName()
updateFields = m.FilterValidFields(tableName, updateFields...)
if len(updateFields) > 0 { // 更新指定字段
db = db.Select(updateFields)
} else { // 更新全部字段,包括零值字段
db = db.Select(m.GetTableFields(tableName))
}
err = db.Where("id = ?", emailCode.Id).Updates(emailCode).Error
if err != nil {
m.logger.Error("UpdateEmailCode", zap.Error(err))
}
return
}
// GetEmailCode 根据id获取EmailCode
func (m *DBModel) GetEmailCode(id int64, fields ...string) (emailCode EmailCode, err error) {
db := m.db
fields = m.FilterValidFields(EmailCode{}.TableName(), fields...)
if len(fields) > 0 {
db = db.Select(fields)
}
err = db.Where("id = ?", id).First(&emailCode).Error
return
}
type OptionGetEmailCodeList struct {
Page int
Size int
WithCount bool // 是否返回总数
Ids []int64 // id列表
SelectFields []string // 查询字段
QueryRange map[string][2]interface{} // map[field][]{min,max}
QueryIn map[string][]interface{} // map[field][]{value1,value2,...}
QueryLike map[string][]interface{} // map[field][]{value1,value2,...}
Sort []string
}
// GetEmailCodeList 获取EmailCode列表
func (m *DBModel) GetEmailCodeList(opt *OptionGetEmailCodeList) (emailCodeList []EmailCode, total int64, err error) {
tableName := EmailCode{}.TableName()
db := m.db.Model(&EmailCode{})
db = m.generateQueryRange(db, tableName, opt.QueryRange)
db = m.generateQueryIn(db, tableName, opt.QueryIn)
db = m.generateQueryLike(db, tableName, opt.QueryLike)
if len(opt.Ids) > 0 {
db = db.Where("id in (?)", opt.Ids)
}
if opt.WithCount {
err = db.Count(&total).Error
if err != nil {
m.logger.Error("GetEmailCodeList", zap.Error(err))
return
}
}
opt.SelectFields = m.FilterValidFields(tableName, opt.SelectFields...)
if len(opt.SelectFields) > 0 {
db = db.Select(opt.SelectFields)
}
db = m.generateQuerySort(db, tableName, opt.Sort)
db = db.Offset((opt.Page - 1) * opt.Size).Limit(opt.Size)
err = db.Find(&emailCodeList).Error
if err != nil && err != gorm.ErrRecordNotFound {
m.logger.Error("GetEmailCodeList", zap.Error(err))
}
return
}
// DeleteEmailCode 删除数据
func (m *DBModel) DeleteEmailCode(ids []int64) (err error) {
err = m.db.Where("id in (?)", ids).Delete(&EmailCode{}).Error
if err != nil {
m.logger.Error("DeleteEmailCode", zap.Error(err))
}
return
}
// 获取最新一条邮箱验证码
func (m *DBModel) GetLatestEmailCode(email string, codeType int32) (code EmailCode) {
err := m.db.Where("email = ? and code_type = ?", email, codeType).Order("id desc").Find(&code).Error
if err != nil {
m.logger.Error("GetLatestEmailCode", zap.Error(err))
}
return
}

@ -175,6 +175,7 @@ func (m *DBModel) SyncDB() (err error) {
&Report{},
&Navigation{},
&Punishment{},
&EmailCode{},
}
m.alterTableBeforeSyncDB()

@ -2,7 +2,12 @@ package model
import (
"bytes"
"compress/gzip"
"errors"
"fmt"
"io"
"moredoc/util"
"moredoc/util/converter"
"moredoc/util/sitemap"
"os"
"path/filepath"
@ -15,8 +20,13 @@ import (
"gorm.io/gorm"
)
type reconvertDocument struct {
Id int64 `json:"id"`
}
var (
isCreatingSitemap bool
cacheReconvert = "cache/reconvert"
)
// UpdateSitemap 更新站点地图
@ -325,3 +335,182 @@ func (m *DBModel) loopCovertDocument() {
}
}
}
func (m *DBModel) ReconvertDocoument(documentId int64, ext string) {
ext = "." + strings.TrimLeft(ext, ".")
os.RemoveAll(cacheReconvert)
os.MkdirAll(cacheReconvert, os.ModePerm)
if documentId <= 0 {
m.reconvertAllDocument(ext)
return
}
doc, err := m.GetDocument(documentId)
if err != nil {
m.logger.Error("ReconvertDocoument", zap.Error(err))
return
}
if doc.Status != DocumentStatusConverted {
m.logger.Error("ReconvertDocoument", zap.Error(errors.New("文档不是已转换的文档,不能重转")))
return
}
m.reconvertDocument(&doc, ext)
}
func (m *DBModel) reconvertDocument(doc *Document, ext string) {
m.logger.Debug("reconvertDocument", zap.Any("doc", doc), zap.String("ext", ext))
if doc.PreviewExt == ext {
m.logger.Info("reconvertDocument", zap.String("msg", "文档预览文件格式与指定格式一致,无需重转"), zap.String("document", doc.Title+doc.Ext))
return
}
// 1. 下载文档预览文件
attachment := m.GetAttachmentByTypeAndTypeId(AttachmentTypeDocument, doc.Id, "id", "hash")
if attachment.Id == 0 {
m.logger.Error("reconvertDocument", zap.String("msg", "文档预览文件不存在"), zap.String("document", doc.Title+doc.Ext))
return
}
cacheDir := filepath.Join(cacheReconvert, strconv.FormatInt(doc.Id, 10))
os.MkdirAll(cacheDir, os.ModePerm)
defer os.RemoveAll(cacheDir)
totalPreview := doc.Preview
if totalPreview == 0 {
totalPreview = doc.Pages
}
var (
convertedTargets []string
oldSrcFiles []string
)
for i := 1; i <= totalPreview; i++ {
// 已存在的预览文件
isGZIP := false
oldExt := doc.PreviewExt
if doc.EnableGZIP && strings.HasSuffix(oldExt, ".svg") {
oldExt = ".gzip.svg"
isGZIP = true
}
// 目标文件
dstFile := filepath.Join(cacheDir, fmt.Sprintf("%d%s", i, oldExt))
// 源文件
srcFile := fmt.Sprintf("documents/%s/%s/%d%s", strings.Join(strings.Split(attachment.Hash, "")[:5], "/"), attachment.Hash, i, oldExt)
oldSrcFiles = append(oldSrcFiles, srcFile)
err := util.CopyFile(srcFile, dstFile)
if err != nil {
m.logger.Error("reconvertDocument", zap.String("msg", "下载文档预览文件失败"), zap.String("document", doc.Title+doc.Ext), zap.Error(err))
return
}
m.logger.Debug("reconvertDocument", zap.Bool("isGZIP", isGZIP), zap.String("msg", "下载文档预览文件成功"), zap.String("document", doc.Title+doc.Ext), zap.String("srcFile", srcFile), zap.String("dstFile", dstFile))
if isGZIP { // 解压缩
m.ungzipSVG(dstFile)
}
// 2. 转换文档预览文件
convertedTargetFile := filepath.Join(cacheDir, fmt.Sprintf("%d%s", i, ext))
if strings.HasSuffix(oldExt, ".svg") {
// 如果是svg文件则需要使用inkscape预先转为png
tmpFile := filepath.Join(cacheDir, fmt.Sprintf("tmp-%d.png", i))
err = converter.ConvertByInkscape(dstFile, tmpFile)
if err == nil {
if strings.HasSuffix(convertedTargetFile, ".png") {
// 如果目标文件是png则直接使用inkscape转换后的文件
convertedTargetFile = tmpFile
} else {
// 如果目标文件不是png则需要使用ImageMagick转换
err = converter.ConvertByImageMagick(tmpFile, convertedTargetFile)
os.RemoveAll(tmpFile)
}
}
} else {
err = converter.ConvertByImageMagick(dstFile, convertedTargetFile)
}
if err != nil {
m.logger.Error("reconvertDocument", zap.String("msg", "转换文档预览文件失败"), zap.String("document", doc.Title+doc.Ext), zap.Error(err))
return
}
convertedTargets = append(convertedTargets, convertedTargetFile)
}
// 3. 上传文档预览文件
for i, srcFile := range convertedTargets {
dstFile := fmt.Sprintf("documents/%s/%s/%d%s", strings.Join(strings.Split(attachment.Hash, "")[:5], "/"), attachment.Hash, i+1, ext)
err := util.CopyFile(srcFile, dstFile)
if err != nil {
m.logger.Error("reconvertDocument", zap.String("msg", "上传文档预览文件失败"), zap.String("document", doc.Title+doc.Ext), zap.Error(err))
return
}
}
// 4. 更新数据库表的预览后缀
// 查询同一hash的文档
var (
attachemnts []Attachment
err error
data = map[string]interface{}{
"preview_ext": ext,
"enable_gzip": false,
}
)
m.db.Select("id", "type_id").Where("hash = ? and `type` = ?", attachment.Hash, AttachmentTypeDocument).Find(&attachemnts)
if len(attachemnts) > 0 {
var ids []int64
for _, attachemnt := range attachemnts {
ids = append(ids, attachemnt.TypeId)
}
err = m.db.Model(&Document{}).Where("id IN (?)", ids).Updates(data).Error
} else {
err = m.db.Model(doc).Updates(data).Error
}
if err != nil {
m.logger.Error("reconvertDocument", zap.String("msg", "更新文档预览文件后缀失败"), zap.String("document", doc.Title+doc.Ext), zap.Error(err))
return
}
// 5. 删除缓存文件,删除原预览文件
for _, file := range oldSrcFiles {
os.Remove(file)
}
}
func (m *DBModel) reconvertAllDocument(ext string) {
var cfg reconvertDocument
bytes, _ := os.ReadFile("cache/reconvert.json")
json.Unmarshal(bytes, &cfg)
for {
var doc Document
m.db.Where("id > ?", cfg.Id).Where("status = ?", DocumentStatusConverted).Order("id asc").Find(&doc)
if doc.Id == 0 {
break
}
m.reconvertDocument(&doc, ext)
cfg.Id = doc.Id
bytes, _ = json.Marshal(cfg)
os.WriteFile("cache/reconvert.json", bytes, os.ModePerm)
}
}
func (m *DBModel) ungzipSVG(svg string) {
m.logger.Info("ungzipSVG", zap.String("svg", svg))
bs, err := os.ReadFile(svg)
if err != nil {
m.logger.Error("ungzipSVG", zap.Error(err))
return
}
gz, err := gzip.NewReader(bytes.NewReader(bs))
if err != nil {
m.logger.Error("ungzipSVG", zap.Error(err))
return
}
defer gz.Close()
fp, err := os.Create(svg)
if err != nil {
m.logger.Error("ungzipSVG", zap.Error(err))
return
}
defer fp.Close()
io.Copy(fp, gz)
}

@ -0,0 +1,19 @@
package service
import (
"moredoc/conf"
"moredoc/model"
"go.uber.org/zap"
)
func Reconvert(cfg *conf.Config, logger *zap.Logger, ext string, documentId int64) {
db, err := model.NewDBModel(&cfg.Database, logger)
if err != nil {
logger.Fatal("NewDBModel", zap.Error(err))
return
}
logger.Info("Reconvert", zap.Int64("documentId", documentId), zap.String("ext", ext))
db.ReconvertDocoument(documentId, ext)
logger.Info("Reconvert", zap.Int64("documentId", documentId), zap.String("ext", ext), zap.String("status", "done!"))
}

@ -73,6 +73,6 @@ func GenerateCaptcha(captchaType string, length, width, height int) (id, b64s st
}
// VerifyCaptcha 验证验证码
func VerifyCaptcha(id string, captchaValue string) (ok bool) {
return store.Verify(id, captchaValue, true)
func VerifyCaptcha(id string, captchaValue string, clear bool) (ok bool) {
return store.Verify(id, captchaValue, clear)
}

@ -176,15 +176,25 @@ type OptionConvertPages struct {
// ConvertPDFToPages 将PDF转为预览页
func (c *Converter) ConvertPDFToPages(src string, fromPage, toPage int, option *OptionConvertPages) (pages []Page, err error) {
switch strings.TrimLeft(option.Extension, ".") {
ext := strings.TrimLeft(option.Extension, ".")
switch ext {
case "png":
return c.ConvertPDFToPNG(src, fromPage, toPage)
case "jpg":
case "jpg", "webp":
// 见将pdf转为png然后png再转为jpg
pages, err = c.ConvertPDFToPNG(src, fromPage, toPage)
// 通过imagemagick将图片转为jpg
var (
dst string
errConvert error
)
for idx, page := range pages {
if dst, errConvert := c.ConvertPNGToJPG(page.PagePath); errConvert == nil {
if ext != "webp" {
dst, errConvert = c.ConvertPNGToJPG(page.PagePath)
} else {
dst, errConvert = c.ConvertPNGToWEBP(page.PagePath)
}
if errConvert == nil {
os.Remove(page.PagePath)
page.PagePath = dst
pages[idx] = page
@ -212,6 +222,22 @@ func (c *Converter) ConvertPNGToJPG(src string) (dst string, err error) {
return
}
// 将png转为webp
func (c *Converter) ConvertPNGToWEBP(src string) (dst string, err error) {
dst = strings.TrimSuffix(src, filepath.Ext(src)) + ".webp"
// 通过imagemagick将图片转为jpg
args := []string{
src,
dst,
}
c.logger.Debug("convert png to webp", zap.String("cmd", imageMagick), zap.Strings("args", args))
_, err = command.ExecCommand(imageMagick, args, c.timeout)
if err != nil {
c.logger.Error("convert png to webp", zap.String("cmd", imageMagick), zap.Strings("args", args), zap.Error(err))
}
return
}
func (c *Converter) ConvertPDFToJPG(src string, fromPage, toPage int) (pages []Page, err error) {
return c.convertPDFToPage(src, fromPage, toPage, ".jpg")
}
@ -512,3 +538,22 @@ func (c *Converter) Clean() (err error) {
}
return
}
func ConvertByImageMagick(src, dst string, moreArgs ...string) (err error) {
args := []string{src}
args = append(args, moreArgs...)
args = append(args, dst)
_, err = command.ExecCommand(imageMagick, args)
return
}
// 通过Inksacpe进行转换如将svg转为png
func ConvertByInkscape(src, dst string, moreArgs ...string) (err error) {
args := []string{
"-o", dst,
}
args = append(args, moreArgs...)
args = append(args, src)
_, err = command.ExecCommand(inkscape, args)
return
}

Loading…
Cancel
Save