From 89a7c87bf6d39eb0abb40b9dbf30ee5c1e6ea7a1 Mon Sep 17 00:00:00 2001 From: WuYuuuub <625806558@qq.com> Date: Sun, 29 Mar 2026 11:55:53 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=88=9D=E5=A7=8B=E6=8F=90=E4=BA=A4?= =?UTF-8?q?=E4=BA=91=E5=8D=B0=E4=BA=AB=E4=BB=98=E8=B4=B9=E6=89=93=E5=8D=B0?= =?UTF-8?q?=E6=9C=8D=E5=8A=A1=E5=90=8E=E7=AB=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cloudprint-backend/README.md | 236 + cloudprint-backend/cmd/server/main.go | 163 + cloudprint-backend/config/config.go | 98 + cloudprint-backend/docs/openapi.yaml | 1132 ++++ cloudprint-backend/go.mod | 43 + cloudprint-backend/go.sum | 303 ++ .../internal/grpc/interceptor/auth.go | 125 + cloudprint-backend/internal/grpc/server.go | 92 + .../internal/grpc/service/admin_service.go | 68 + .../internal/grpc/service/auth_service.go | 63 + .../internal/grpc/service/file_service.go | 141 + .../internal/grpc/service/library_service.go | 91 + .../internal/grpc/service/order_service.go | 98 + .../internal/grpc/service/pay_service.go | 201 + .../internal/grpc/service/price_service.go | 96 + .../internal/grpc/service/print_service.go | 136 + cloudprint-backend/internal/model/model.go | 224 + .../internal/repository/admin_repository.go | 49 + .../internal/repository/file_repository.go | 67 + .../internal/repository/library_repository.go | 108 + .../internal/repository/order_repository.go | 162 + .../internal/repository/price_repository.go | 80 + .../internal/repository/printer_repository.go | 150 + .../internal/repository/user_repository.go | 64 + .../internal/service/auth_service.go | 189 + .../internal/service/file_service.go | 105 + .../internal/service/order_service.go | 218 + .../internal/service/print_service.go | 194 + cloudprint-backend/pkg/jwt/jwt.go | 105 + cloudprint-backend/pkg/pay/wechat.go | 200 + cloudprint-backend/pkg/upload/upload.go | 196 + cloudprint-backend/proto/cloudprint.proto | 502 ++ .../proto/generated/cloudprint.pb.go | 4785 +++++++++++++++++ .../proto/generated/cloudprint_grpc.pb.go | 1856 +++++++ cloudprint-backend/scripts/db.sql | 182 + 35 files changed, 12522 insertions(+) create mode 100644 cloudprint-backend/README.md create mode 100644 cloudprint-backend/cmd/server/main.go create mode 100644 cloudprint-backend/config/config.go create mode 100644 cloudprint-backend/docs/openapi.yaml create mode 100644 cloudprint-backend/go.mod create mode 100644 cloudprint-backend/go.sum create mode 100644 cloudprint-backend/internal/grpc/interceptor/auth.go create mode 100644 cloudprint-backend/internal/grpc/server.go create mode 100644 cloudprint-backend/internal/grpc/service/admin_service.go create mode 100644 cloudprint-backend/internal/grpc/service/auth_service.go create mode 100644 cloudprint-backend/internal/grpc/service/file_service.go create mode 100644 cloudprint-backend/internal/grpc/service/library_service.go create mode 100644 cloudprint-backend/internal/grpc/service/order_service.go create mode 100644 cloudprint-backend/internal/grpc/service/pay_service.go create mode 100644 cloudprint-backend/internal/grpc/service/price_service.go create mode 100644 cloudprint-backend/internal/grpc/service/print_service.go create mode 100644 cloudprint-backend/internal/model/model.go create mode 100644 cloudprint-backend/internal/repository/admin_repository.go create mode 100644 cloudprint-backend/internal/repository/file_repository.go create mode 100644 cloudprint-backend/internal/repository/library_repository.go create mode 100644 cloudprint-backend/internal/repository/order_repository.go create mode 100644 cloudprint-backend/internal/repository/price_repository.go create mode 100644 cloudprint-backend/internal/repository/printer_repository.go create mode 100644 cloudprint-backend/internal/repository/user_repository.go create mode 100644 cloudprint-backend/internal/service/auth_service.go create mode 100644 cloudprint-backend/internal/service/file_service.go create mode 100644 cloudprint-backend/internal/service/order_service.go create mode 100644 cloudprint-backend/internal/service/print_service.go create mode 100644 cloudprint-backend/pkg/jwt/jwt.go create mode 100644 cloudprint-backend/pkg/pay/wechat.go create mode 100644 cloudprint-backend/pkg/upload/upload.go create mode 100644 cloudprint-backend/proto/cloudprint.proto create mode 100644 cloudprint-backend/proto/generated/cloudprint.pb.go create mode 100644 cloudprint-backend/proto/generated/cloudprint_grpc.pb.go create mode 100644 cloudprint-backend/scripts/db.sql diff --git a/cloudprint-backend/README.md b/cloudprint-backend/README.md new file mode 100644 index 0000000..a68f2da --- /dev/null +++ b/cloudprint-backend/README.md @@ -0,0 +1,236 @@ +# 云印享 - 付费打印服务系统 + +## 项目简介 + +云印享是一个基于 gRPC 的付费打印服务后端系统,支持用户管理、文件上传下载、订单处理、打印任务调度、微信支付、文库管理等核心功能。 + +## 技术栈 + +- **语言**: Go 1.21+ +- **框架**: gRPC + Protobuf +- **数据库**: MySQL + GORM +- **认证**: JWT (JSON Web Token) +- **支付**: 微信支付 (gopay) +- **配置**: Viper + +## 项目结构 + +``` +cloudprint-backend/ +├── cmd/server/ # 应用入口 +│ └── main.go +├── config/ # 配置管理 +│ └── config.go +├── internal/ +│ ├── grpc/ # gRPC 服务层 +│ │ ├── interceptor/ # 拦截器 (认证) +│ │ └── service/ # gRPC 服务实现 +│ ├── model/ # 数据模型 +│ ├── repository/ # 数据访问层 +│ └── service/ # 业务逻辑层 +├── pkg/ # 公共工具包 +│ ├── jwt/ # JWT 认证 +│ ├── pay/ # 微信支付 +│ └── upload/ # 文件上传 +├── proto/ # Protobuf 定义 +│ ├── cloudprint.proto +│ └── generated/ # 生成的代码 +├── scripts/ # 数据库脚本 +│ └── db.sql +├── config.yaml # 配置文件 +├── go.mod +└── go.sum +``` + +## 服务列表 + +| 服务 | 端口 | 描述 | +|------|------|------| +| gRPC Server | 8080 | 主服务端口 | + +## 快速开始 + +### 1. 环境要求 + +- Go 1.21+ +- MySQL 5.7+ +- protoc (Protocol Buffer 编译器) + +### 2. 数据库初始化 + +```bash +mysql -u root -p < scripts/db.sql +``` + +### 3. 配置修改 + +编辑 `config.yaml` 文件,修改以下配置: + +```yaml +database: + host: "localhost" + port: 3306 + username: "root" + password: "your-password" + database: "cloudprint" + +jwt: + secret: "your-secret-key-change-in-production" + +wechat: + app_id: "your-app-id" + app_secret: "your-app-secret" + mch_id: "your-merchant-id" + api_key: "your-api-key" + notify_url: "http://your-domain.com/pay/callback" +``` + +### 4. 编译生成 gRPC 代码 + +```bash +cd cloudprint-backend +protoc --go_out=./proto/generated --go_opt=paths=source_relative \ + --go-grpc_out=./proto/generated --go-grpc_opt=paths=source_relative \ + proto/cloudprint.proto +``` + +### 5. 运行服务 + +```bash +go run cmd/server/main.go -config config.yaml +``` + +## API 文档 + +### AuthService (用户认证服务) + +| 方法 | 描述 | +|------|------| +| Login | 微信登录,获取 AccessToken 和 RefreshToken | +| RefreshToken | 刷新 AccessToken | +| GetUserInfo | 获取用户信息 | +| UpdateUser | 更新用户信息(昵称、头像) | + +### FileService (文件管理服务) + +| 方法 | 描述 | +|------|------| +| Upload | 流式上传文件(支持分片) | +| GetFile | 流式下载文件 | +| DeleteFile | 删除文件 | +| AddWatermark | 添加水印 | +| GetFileList | 获取文件列表 | + +### OrderService (订单服务) + +| 方法 | 描述 | +|------|------| +| CreateOrder | 创建订单 | +| GetOrder | 获取订单详情 | +| GetOrderList | 获取订单列表 | +| UpdateOrderStatus | 更新订单状态 | +| CancelOrder | 取消订单 | + +### PrintService (打印服务) + +| 方法 | 描述 | +|------|------| +| GetPrinters | 获取打印机列表 | +| GetPrinterStatus | 获取打印机状态 | +| RegisterPrinter | 注册打印机 | +| PrinterHeartbeat | 打印机心跳 | +| SubmitPrintJob | 提交打印任务 | +| CancelPrintJob | 取消打印任务 | +| SubscribeJobs | 订阅打印任务(流式) | +| ReportJobStatus | 上报任务状态 | + +### LibraryService (文库服务) + +| 方法 | 描述 | +|------|------| +| GetCategories | 获取文库分类 | +| GetFiles | 获取文库文件列表 | +| UploadFile | 上传文库文件 | +| DeleteFile | 删除文库文件 | + +### PriceService (价目表服务) + +| 方法 | 描述 | +|------|------| +| GetPriceList | 获取价目表 | +| CreatePriceItem | 创建价目项 | +| UpdatePriceItem | 更新价目项 | + +### PayService (支付服务) + +| 方法 | 描述 | +|------|------| +| CreateWxPayOrder | 创建微信支付订单 | +| QueryPayStatus | 查询支付状态 | +| HandlePayCallback | 处理支付回调 | +| PayByBalance | 余额支付 | + +### AdminService (管理后台服务) + +| 方法 | 描述 | +|------|------| +| Login | 管理员登录 | +| GetStatistics | 获取统计数据 | + +## 数据模型 + +### 订单状态 + +| 值 | 状态 | +|----|------| +| 0 | 待支付 | +| 1 | 已支付 | +| 2 | 打印中 | +| 3 | 已完成 | +| 4 | 已取消 | + +### 支付状态 + +| 值 | 状态 | +|----|------| +| 0 | 待支付 | +| 1 | 支付中 | +| 2 | 成功 | +| 3 | 失败 | + +### 打印机状态 + +| 值 | 状态 | +|----|------| +| 0 | 空闲 | +| 1 | 打印中 | +| 2 | 离线 | + +### 打印任务状态 + +| 值 | 状态 | +|----|------| +| pending | 等待中 | +| printing | 打印中 | +| completed | 已完成 | +| failed | 失败 | +| cancelled | 已取消 | + +## 默认账号 + +- 管理员用户名: `admin` +- 管理员密码: `admin123` (需在生产环境修改) + +## 初始价目表 + +| 名称 | 类型 | 价格 | 单位 | +|------|------|------|------| +| A4黑白打印 | A4 | 0.10元 | 页 | +| A4彩色打印 | A4 | 0.30元 | 页 | +| A3黑白打印 | A3 | 0.20元 | 页 | +| A3彩色打印 | A3 | 0.60元 | 页 | +| 照片打印 | 照片纸 | 2.00元 | 张 | + +## 许可证 + +MIT License diff --git a/cloudprint-backend/cmd/server/main.go b/cloudprint-backend/cmd/server/main.go new file mode 100644 index 0000000..a0a0dc4 --- /dev/null +++ b/cloudprint-backend/cmd/server/main.go @@ -0,0 +1,163 @@ +package main + +import ( + "flag" + "fmt" + "log" + "net" + "os" + "os/signal" + "syscall" + + "github.com/cloudprint/cloudprint-backend/config" + "github.com/cloudprint/cloudprint-backend/internal/grpc" + "github.com/cloudprint/cloudprint-backend/internal/grpc/interceptor" + "github.com/cloudprint/cloudprint-backend/internal/grpc/service" + "github.com/cloudprint/cloudprint-backend/internal/model" + "github.com/cloudprint/cloudprint-backend/internal/repository" + "github.com/cloudprint/cloudprint-backend/internal/service" + "github.com/cloudprint/cloudprint-backend/pkg/jwt" + "github.com/cloudprint/cloudprint-backend/pkg/pay" + "github.com/cloudprint/cloudprint-backend/pkg/upload" + pb "github.com/cloudprint/cloudprint-backend/proto/generated" + "go.uber.org/zap" + "google.golang.org/grpc" + "gorm.io/driver/mysql" + "gorm.io/gorm" + "gorm.io/gorm/logger" +) + +func main() { + configPath := flag.String("config", "config.yaml", "path to config file") + flag.Parse() + + // Load configuration + cfg, err := config.LoadConfig(*configPath) + if err != nil { + log.Fatalf("Failed to load config: %v", err) + } + + // Initialize logger + zapLogger, _ := zap.NewProduction() + defer zapLogger.Sync() + + // Initialize database + db, err := initDB(cfg) + if err != nil { + log.Fatalf("Failed to initialize database: %v", err) + } + + // Auto migrate + if err := db.AutoMigrate( + &model.User{}, + &model.Admin{}, + &model.Printer{}, + &model.Order{}, + &model.OrderItem{}, + &model.File{}, + &model.LibraryCategory{}, + &model.LibraryFile{}, + &model.PrintJob{}, + &model.PriceList{}, + &model.Payment{}, + ); err != nil { + log.Fatalf("Failed to migrate database: %v", err) + } + + // Initialize repositories + userRepo := repository.NewUserRepository(db) + adminRepo := repository.NewAdminRepository(db) + fileRepo := repository.NewFileRepository(db) + orderRepo := repository.NewOrderRepository(db) + orderItemRepo := repository.NewOrderItemRepository(db) + printerRepo := repository.NewPrinterRepository(db) + printJobRepo := repository.NewPrintJobRepository(db) + libraryRepo := repository.NewLibraryRepository(db) + priceRepo := repository.NewPriceRepository(db) + paymentRepo := repository.NewPaymentRepository(db) + + // Initialize JWT manager + jwtManager := jwt.NewJWTManager( + cfg.JWT.Secret, + cfg.JWT.AccessTokenTTL, + cfg.JWT.RefreshTokenTTL, + ) + + // Initialize file uploader + fileUploader := upload.NewFileUploader( + cfg.Upload.Path, + cfg.Upload.ChunkPath, + cfg.Upload.MaxSize, + ) + + // Initialize WeChat pay + weChatPay := pay.NewWeChatPay(&cfg.WeChat) + + // Initialize services + authService := service.NewAuthService(userRepo, adminRepo, jwtManager, nil, &cfg.WeChat) + fileService := service.NewFileService(fileRepo, fileUploader, cfg.Upload.Path) + orderService := service.NewOrderService(orderRepo, orderItemRepo, fileRepo, priceRepo, userRepo, printerRepo, printJobRepo) + printService := service.NewPrintService(printerRepo, printJobRepo, orderRepo) + + // Initialize gRPC server + grpcServer := grpc.NewServer( + grpc.UnaryInterceptor(interceptor.NewAuthInterceptor(jwtManager).UnaryServerInterceptor()), + ) + + // Register gRPC services + pb.RegisterAuthServiceServer(grpcServer, service.NewAuthServiceServer(authService)) + pb.RegisterFileServiceServer(grpcServer, service.NewFileServiceServer(fileService)) + pb.RegisterOrderServiceServer(grpcServer, service.NewOrderServiceServer(orderService)) + pb.RegisterPrintServiceServer(grpcServer, service.NewPrintServiceServer(printService)) + pb.RegisterLibraryServiceServer(grpcServer, service.NewLibraryServiceServer(libraryRepo, fileRepo)) + pb.RegisterPriceServiceServer(grpcServer, service.NewPriceServiceServer(priceRepo)) + pb.RegisterPayServiceServer(grpcServer, service.NewPayServiceServer(orderService, paymentRepo, weChatPay, userRepo)) + pb.RegisterAdminServiceServer(grpcServer, service.NewAdminServiceServer(authService, orderRepo, printerRepo)) + + // Start server + addr := fmt.Sprintf("%s:%d", cfg.Server.Host, cfg.Server.Port) + lis, err := net.Listen("tcp", addr) + if err != nil { + log.Fatalf("Failed to listen: %v", err) + } + + // Graceful shutdown + sigCh := make(chan os.Signal, 1) + signal.Notify(sigCh, syscall.SIGINT, syscall.SIGTERM) + + go func() { + <-sigCh + grpcServer.GracefulStop() + }() + + zapLogger.Info("Starting gRPC server", zap.String("address", addr)) + if err := grpcServer.Serve(lis); err != nil { + log.Fatalf("Failed to serve: %v", err) + } +} + +func initDB(cfg *config.Config) (*gorm.DB, error) { + gormLogger := logger.New( + log.New(os.Stdout, "\r\n", log.LstdFlags), + logger.Config{ + LogLevel: logger.Info, + }, + ) + + db, err := gorm.Open(mysql.Open(cfg.Database.DSN()), &gorm.Config{ + Logger: gormLogger, + }) + if err != nil { + return nil, err + } + + sqlDB, err := db.DB() + if err != nil { + return nil, err + } + + sqlDB.SetMaxOpenConns(cfg.Database.MaxOpenConns) + sqlDB.SetMaxIdleConns(cfg.Database.MaxIdleConns) + + return db, nil +} diff --git a/cloudprint-backend/config/config.go b/cloudprint-backend/config/config.go new file mode 100644 index 0000000..c167f90 --- /dev/null +++ b/cloudprint-backend/config/config.go @@ -0,0 +1,98 @@ +package config + +import ( + "fmt" + "time" + + "github.com/spf13/viper" +) + +type Config struct { + Server ServerConfig `mapstructure:"server"` + Database DatabaseConfig `mapstructure:"database"` + Redis RedisConfig `mapstructure:"redis"` + JWT JWTConfig `mapstructure:"jwt"` + WeChat WeChatConfig `mapstructure:"wechat"` + Upload UploadConfig `mapstructure:"upload"` +} + +type ServerConfig struct { + Host string `mapstructure:"host"` + Port int `mapstructure:"port"` +} + +type DatabaseConfig struct { + Host string `mapstructure:"host"` + Port int `mapstructure:"port"` + Username string `mapstructure:"username"` + Password string `mapstructure:"password"` + Database string `mapstructure:"database"` + MaxOpenConns int `mapstructure:"max_open_conns"` + MaxIdleConns int `mapstructure:"max_idle_conns"` +} + +func (d *DatabaseConfig) DSN() string { + return fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8mb4&parseTime=True&loc=Local", + d.Username, d.Password, d.Host, d.Port, d.Database) +} + +type RedisConfig struct { + Host string `mapstructure:"host"` + Port int `mapstructure:"port"` + Password string `mapstructure:"password"` + DB int `mapstructure:"db"` +} + +func (r *RedisConfig) Addr() string { + return fmt.Sprintf("%s:%d", r.Host, r.Port) +} + +type JWTConfig struct { + Secret string `mapstructure:"secret"` + AccessTokenTTL time.Duration `mapstructure:"access_token_ttl"` + RefreshTokenTTL time.Duration `mapstructure:"refresh_token_ttl"` +} + +type WeChatConfig struct { + AppID string `mapstructure:"app_id"` + AppSecret string `mapstructure:"app_secret"` + MchID string `mapstructure:"mch_id"` + ApiKey string `mapstructure:"api_key"` + NotifyURL string `mapstructure:"notify_url"` + CertPath string `mapstructure:"cert_path"` + CertContent string `mapstructure:"cert_content"` +} + +type UploadConfig struct { + Path string `mapstructure:"path"` + MaxSize int64 `mapstructure:"max_size"` + ChunkPath string `mapstructure:"chunk_path"` +} + +var GlobalConfig *Config + +func LoadConfig(path string) (*Config, error) { + viper.SetConfigFile(path) + viper.SetConfigType("yaml") + + viper.SetDefault("server.host", "0.0.0.0") + viper.SetDefault("server.port", 8080) + viper.SetDefault("database.max_open_conns", 100) + viper.SetDefault("database.max_idle_conns", 10) + viper.SetDefault("jwt.access_token_ttl", "24h") + viper.SetDefault("jwt.refresh_token_ttl", "7d") + viper.SetDefault("upload.max_size", 52428800) // 50MB + viper.SetDefault("upload.chunk_path", "./uploads/chunks") + + if err := viper.ReadInConfig(); err != nil { + return nil, fmt.Errorf("failed to read config: %w", err) + } + + var cfg Config + if err := viper.Unmarshal(&cfg); err != nil { + return nil, fmt.Errorf("failed to unmarshal config: %w", err) + } + + GlobalConfig = &cfg + return &cfg, nil +} diff --git a/cloudprint-backend/docs/openapi.yaml b/cloudprint-backend/docs/openapi.yaml new file mode 100644 index 0000000..a3b591c --- /dev/null +++ b/cloudprint-backend/docs/openapi.yaml @@ -0,0 +1,1132 @@ +openapi: 3.0.3 +info: + title: 云印享 - 付费打印服务 API + description: | + 云印享是一个基于 gRPC 的付费打印服务后端系统 API 文档。 + + ## 认证说明 + - 大多数接口需要在请求头中携带 `Authorization: Bearer ` + - Login 和 Admin.Login 接口不需要认证 + version: 1.0.0 + contact: + name: CloudPrint Support + +servers: + - url: http://localhost:8080 + description: gRPC Server (需通过 gRPC gateway 转换) + +tags: + - name: Auth + description: 用户认证相关接口 + - name: File + description: 文件管理相关接口 + - name: Order + description: 订单相关接口 + - name: Print + description: 打印服务相关接口 + - name: Library + description: 文库相关接口 + - name: Price + description: 价目表相关接口 + - name: Pay + description: 支付相关接口 + - name: Admin + description: 管理后台相关接口 + +paths: + # ==================== Auth Service ==================== + /cloudprint.AuthService/Login: + post: + tags: [Auth] + summary: 微信登录 + description: 用户通过微信授权码登录系统 + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + code: + type: string + description: 微信授权码 + example: "xxxxx" + responses: + "200": + description: 登录成功 + content: + application/json: + schema: + type: object + properties: + access_token: + type: string + description: 访问令牌 + refresh_token: + type: string + description: 刷新令牌 + user: + type: object + properties: + id: + type: integer + description: 用户ID + openid: + type: string + description: 微信OpenID + nickname: + type: string + description: 昵称 + avatar: + type: string + description: 头像URL + balance: + type: number + description: 余额 + created_at: + type: string + format: date-time + + /cloudprint.AuthService/RefreshToken: + post: + tags: [Auth] + summary: 刷新令牌 + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + refresh_token: + type: string + responses: + "200": + description: 刷新成功 + content: + application/json: + schema: + type: object + properties: + access_token: + type: string + + /cloudprint.AuthService/GetUserInfo: + post: + tags: [Auth] + summary: 获取用户信息 + security: + - bearerAuth: [] + responses: + "200": + description: 成功 + content: + application/json: + schema: + $ref: '#/components/schemas/User' + + /cloudprint.AuthService/UpdateUser: + post: + tags: [Auth] + summary: 更新用户信息 + security: + - bearerAuth: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + nickname: + type: string + avatar: + type: string + responses: + "200": + description: 更新成功 + content: + application/json: + schema: + $ref: '#/components/schemas/User' + + # ==================== File Service ==================== + /cloudprint.FileService/Upload: + post: + tags: [File] + summary: 上传文件(流式) + description: 支持分片上传,用于大文件传输 + security: + - bearerAuth: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + file_name: + type: string + description: 文件名 + file_type: + type: string + description: 文件类型 + file_size: + type: integer + format: int64 + description: 文件大小 + data: + type: string + format: binary + description: 文件数据(base64) + is_last_chunk: + type: boolean + description: 是否最后一块 + chunk_id: + type: string + description: 分片ID + chunk_index: + type: integer + description: 分片索引 + total_chunks: + type: integer + description: 总分片数 + responses: + "200": + description: 上传成功 + content: + application/json: + schema: + type: object + properties: + file_id: + type: integer + file_path: + type: string + file_url: + type: string + + /cloudprint.FileService/GetFileList: + post: + tags: [File] + summary: 获取文件列表 + security: + - bearerAuth: [] + requestBody: + content: + application/json: + schema: + type: object + properties: + uploader_type: + type: string + uploader_id: + type: integer + page: + type: integer + page_size: + type: integer + responses: + "200": + description: 成功 + content: + application/json: + schema: + type: object + properties: + files: + type: array + items: + $ref: '#/components/schemas/FileInfo' + total: + type: integer + + /cloudprint.FileService/DeleteFile: + post: + tags: [File] + summary: 删除文件 + security: + - bearerAuth: [] + requestBody: + content: + application/json: + schema: + type: object + properties: + file_id: + type: integer + responses: + "200": + description: 删除成功 + + /cloudprint.FileService/AddWatermark: + post: + tags: [File] + summary: 添加水印 + security: + - bearerAuth: [] + requestBody: + content: + application/json: + schema: + type: object + properties: + file_id: + type: integer + text: + type: string + opacity: + type: number + format: float + position: + type: integer + enum: [1, 2, 3, 4, 5] + description: "1: 左上 2: 右上 3: 左下 4: 右下 5: 居中" + font_size: + type: integer + responses: + "200": + description: 成功 + + # ==================== Order Service ==================== + /cloudprint.OrderService/CreateOrder: + post: + tags: [Order] + summary: 创建订单 + security: + - bearerAuth: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + items: + type: array + items: + type: object + properties: + file_id: + type: integer + printer_id: + type: integer + copies: + type: integer + color: + type: boolean + duplex: + type: boolean + page_range: + type: string + remark: + type: string + responses: + "200": + description: 创建成功 + content: + application/json: + schema: + type: object + properties: + order_no: + type: string + total_amount: + type: number + + /cloudprint.OrderService/GetOrder: + post: + tags: [Order] + summary: 获取订单详情 + security: + - bearerAuth: [] + requestBody: + content: + application/json: + schema: + type: object + properties: + order_no: + type: string + responses: + "200": + description: 成功 + content: + application/json: + schema: + $ref: '#/components/schemas/Order' + + /cloudprint.OrderService/GetOrderList: + post: + tags: [Order] + summary: 获取订单列表 + security: + - bearerAuth: [] + requestBody: + content: + application/json: + schema: + type: object + properties: + user_id: + type: integer + status: + type: integer + page: + type: integer + page_size: + type: integer + responses: + "200": + description: 成功 + content: + application/json: + schema: + type: object + properties: + orders: + type: array + items: + $ref: '#/components/schemas/Order' + total: + type: integer + + /cloudprint.OrderService/UpdateOrderStatus: + post: + tags: [Order] + summary: 更新订单状态 + security: + - bearerAuth: [] + requestBody: + content: + application/json: + schema: + type: object + properties: + order_no: + type: string + status: + type: integer + enum: [0, 1, 2, 3, 4] + responses: + "200": + description: 更新成功 + + /cloudprint.OrderService/CancelOrder: + post: + tags: [Order] + summary: 取消订单 + security: + - bearerAuth: [] + requestBody: + content: + application/json: + schema: + type: object + properties: + order_no: + type: string + responses: + "200": + description: 取消成功 + + # ==================== Print Service ==================== + /cloudprint.PrintService/GetPrinters: + post: + tags: [Print] + summary: 获取打印机列表 + security: + - bearerAuth: [] + responses: + "200": + description: 成功 + content: + application/json: + schema: + type: object + properties: + printers: + type: array + items: + $ref: '#/components/schemas/Printer' + + /cloudprint.PrintService/GetPrinterStatus: + post: + tags: [Print] + summary: 获取打印机状态 + security: + - bearerAuth: [] + requestBody: + content: + application/json: + schema: + type: object + properties: + printer_id: + type: integer + responses: + "200": + description: 成功 + content: + application/json: + schema: + type: object + properties: + printer: + $ref: '#/components/schemas/Printer' + queue_count: + type: integer + + /cloudprint.PrintService/RegisterPrinter: + post: + tags: [Print] + summary: 注册打印机 + security: + - bearerAuth: [] + requestBody: + content: + application/json: + schema: + type: object + properties: + name: + type: string + display_name: + type: string + api_key: + type: string + responses: + "200": + description: 注册成功 + content: + application/json: + schema: + type: object + properties: + printer_id: + type: integer + token: + type: string + + /cloudprint.PrintService/PrinterHeartbeat: + post: + tags: [Print] + summary: 打印机心跳 + requestBody: + content: + application/json: + schema: + type: object + properties: + printer_id: + type: integer + status: + type: integer + enum: [0, 1, 2] + token: + type: string + responses: + "200": + description: 成功 + + /cloudprint.PrintService/SubmitPrintJob: + post: + tags: [Print] + summary: 提交打印任务 + security: + - bearerAuth: [] + requestBody: + content: + application/json: + schema: + type: object + properties: + order_item_id: + type: integer + printer_id: + type: integer + file_path: + type: string + copies: + type: integer + color: + type: boolean + duplex: + type: boolean + page_range: + type: string + responses: + "200": + description: 提交成功 + content: + application/json: + schema: + type: object + properties: + job_no: + type: string + + /cloudprint.PrintService/CancelPrintJob: + post: + tags: [Print] + summary: 取消打印任务 + security: + - bearerAuth: [] + requestBody: + content: + application/json: + schema: + type: object + properties: + job_no: + type: string + responses: + "200": + description: 取消成功 + + /cloudprint.PrintService/ReportJobStatus: + post: + tags: [Print] + summary: 上报任务状态 + requestBody: + content: + application/json: + schema: + type: object + properties: + job_no: + type: string + status: + type: string + enum: [pending, printing, completed, failed, cancelled] + progress: + type: integer + error_msg: + type: string + responses: + "200": + description: 上报成功 + + # ==================== Library Service ==================== + /cloudprint.LibraryService/GetCategories: + post: + tags: [Library] + summary: 获取文库分类 + responses: + "200": + description: 成功 + content: + application/json: + schema: + type: object + properties: + categories: + type: array + items: + $ref: '#/components/schemas/LibraryCategory' + + /cloudprint.LibraryService/GetFiles: + post: + tags: [Library] + summary: 获取文库文件列表 + requestBody: + content: + application/json: + schema: + type: object + properties: + category_id: + type: integer + page: + type: integer + page_size: + type: integer + responses: + "200": + description: 成功 + content: + application/json: + schema: + type: object + properties: + files: + type: array + items: + $ref: '#/components/schemas/LibraryFile' + total: + type: integer + + /cloudprint.LibraryService/UploadFile: + post: + tags: [Library] + summary: 上传文库文件 + security: + - bearerAuth: [] + requestBody: + content: + application/json: + schema: + type: object + properties: + category_id: + type: integer + title: + type: string + description: + type: string + data: + type: string + format: binary + file_name: + type: string + file_type: + type: string + responses: + "200": + description: 上传成功 + + /cloudprint.LibraryService/DeleteFile: + post: + tags: [Library] + summary: 删除文库文件 + security: + - bearerAuth: [] + requestBody: + content: + application/json: + schema: + type: object + properties: + library_file_id: + type: integer + responses: + "200": + description: 删除成功 + + # ==================== Price Service ==================== + /cloudprint.PriceService/GetPriceList: + post: + tags: [Price] + summary: 获取价目表 + responses: + "200": + description: 成功 + content: + application/json: + schema: + type: object + properties: + items: + type: array + items: + $ref: '#/components/schemas/PriceItem' + + /cloudprint.PriceService/CreatePriceItem: + post: + tags: [Price] + summary: 创建价目项 + security: + - bearerAuth: [] + requestBody: + content: + application/json: + schema: + type: object + properties: + name: + type: string + type: + type: string + price: + type: number + unit: + type: string + color_enabled: + type: boolean + responses: + "200": + description: 创建成功 + + /cloudprint.PriceService/UpdatePriceItem: + post: + tags: [Price] + summary: 更新价目项 + security: + - bearerAuth: [] + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/PriceItem' + responses: + "200": + description: 更新成功 + + # ==================== Pay Service ==================== + /cloudprint.PayService/CreateWxPayOrder: + post: + tags: [Pay] + summary: 创建微信支付订单 + security: + - bearerAuth: [] + requestBody: + content: + application/json: + schema: + type: object + properties: + order_no: + type: string + amount: + type: number + description: + type: string + openid: + type: string + client_ip: + type: string + responses: + "200": + description: 创建成功 + content: + application/json: + schema: + type: object + properties: + prepay_id: + type: string + code_url: + type: string + mweb_url: + type: string + + /cloudprint.PayService/QueryPayStatus: + post: + tags: [Pay] + summary: 查询支付状态 + security: + - bearerAuth: [] + requestBody: + content: + application/json: + schema: + type: object + properties: + order_no: + type: string + responses: + "200": + description: 成功 + content: + application/json: + schema: + type: object + properties: + status: + type: integer + enum: [0, 1, 2, 3] + description: "0: 待支付 1: 支付中 2: 成功 3: 失败" + transaction_id: + type: string + + /cloudprint.PayService/HandlePayCallback: + post: + tags: [Pay] + summary: 处理支付回调 + requestBody: + content: + application/json: + schema: + type: object + properties: + body: + type: string + description: 微信支付回调XML内容 + responses: + "200": + description: 处理成功 + + /cloudprint.PayService/PayByBalance: + post: + tags: [Pay] + summary: 余额支付 + security: + - bearerAuth: [] + requestBody: + content: + application/json: + schema: + type: object + properties: + order_no: + type: string + user_id: + type: integer + responses: + "200": + description: 支付成功 + + # ==================== Admin Service ==================== + /cloudprint.AdminService/Login: + post: + tags: [Admin] + summary: 管理员登录 + requestBody: + content: + application/json: + schema: + type: object + properties: + username: + type: string + password: + type: string + responses: + "200": + description: 登录成功 + content: + application/json: + schema: + type: object + properties: + access_token: + type: string + admin: + $ref: '#/components/schemas/Admin' + + /cloudprint.AdminService/GetStatistics: + post: + tags: [Admin] + summary: 获取统计数据 + security: + - bearerAuth: [] + responses: + "200": + description: 成功 + content: + application/json: + schema: + type: object + properties: + total_users: + type: integer + total_orders: + type: integer + today_orders: + type: integer + today_revenue: + type: number + pending_orders: + type: integer + active_printers: + type: integer + +components: + securitySchemes: + bearerAuth: + type: http + scheme: bearer + bearerFormat: JWT + + schemas: + User: + type: object + properties: + id: + type: integer + openid: + type: string + nickname: + type: string + avatar: + type: string + balance: + type: number + created_at: + type: string + format: date-time + + Admin: + type: object + properties: + id: + type: integer + username: + type: string + nickname: + type: string + role: + type: integer + enum: [1, 2] + description: "1: 普通管理员 2: 超级管理员" + created_at: + type: string + format: date-time + + FileInfo: + type: object + properties: + id: + type: integer + file_name: + type: string + file_path: + type: string + file_type: + type: string + file_size: + type: integer + format: int64 + uploader_type: + type: string + uploader_id: + type: integer + created_at: + type: string + format: date-time + + Order: + type: object + properties: + id: + type: integer + order_no: + type: string + user_id: + type: integer + status: + type: integer + enum: [0, 1, 2, 3, 4] + description: "0: 待支付 1: 已支付 2: 打印中 3: 已完成 4: 已取消" + total_amount: + type: number + remark: + type: string + created_at: + type: string + format: date-time + paid_at: + type: string + format: date-time + items: + type: array + items: + $ref: '#/components/schemas/OrderItem' + + OrderItem: + type: object + properties: + id: + type: integer + order_id: + type: integer + file_id: + type: integer + printer_id: + type: integer + copies: + type: integer + color: + type: boolean + duplex: + type: boolean + page_range: + type: string + price: + type: number + + Printer: + type: object + properties: + id: + type: integer + name: + type: string + display_name: + type: string + is_active: + type: boolean + status: + type: integer + enum: [0, 1, 2] + description: "0: 空闲 1: 打印中 2: 离线" + last_heartbeat: + type: string + format: date-time + + PrintJob: + type: object + properties: + id: + type: integer + job_no: + type: string + printer_id: + type: integer + order_item_id: + type: integer + status: + type: string + enum: [pending, printing, completed, failed, cancelled] + progress: + type: integer + error_msg: + type: string + started_at: + type: string + format: date-time + completed_at: + type: string + format: date-time + + LibraryCategory: + type: object + properties: + id: + type: integer + name: + type: string + icon: + type: string + sort_order: + type: integer + + LibraryFile: + type: object + properties: + id: + type: integer + category_id: + type: integer + file_id: + type: integer + title: + type: string + description: + type: string + page_count: + type: integer + download_count: + type: integer + created_at: + type: string + format: date-time + + PriceItem: + type: object + properties: + id: + type: integer + name: + type: string + type: + type: string + description: 纸张类型 A4/A3/照片纸 + price: + type: number + unit: + type: string + color_enabled: + type: boolean + is_active: + type: boolean diff --git a/cloudprint-backend/go.mod b/cloudprint-backend/go.mod new file mode 100644 index 0000000..c14c7f6 --- /dev/null +++ b/cloudprint-backend/go.mod @@ -0,0 +1,43 @@ +module github.com/cloudprint/cloudprint-backend + +go 1.21 + +require ( + github.com/golang-jwt/jwt/v5 v5.2.0 + github.com/google/uuid v1.5.0 + github.com/iGoogle-ink/gopay v1.5.14 + github.com/spf13/viper v1.18.2 + go.uber.org/zap v1.26.0 + golang.org/x/crypto v0.18.0 + google.golang.org/grpc v1.60.1 + google.golang.org/protobuf v1.32.0 + gorm.io/driver/mysql v1.5.2 + gorm.io/gorm v1.25.5 +) + +require ( + github.com/fsnotify/fsnotify v1.7.0 // indirect + github.com/go-sql-driver/mysql v1.7.0 // indirect + github.com/golang/protobuf v1.5.3 // indirect + github.com/hashicorp/hcl v1.0.0 // indirect + github.com/jinzhu/inflection v1.0.0 // indirect + github.com/jinzhu/now v1.1.5 // indirect + github.com/magiconair/properties v1.8.7 // indirect + github.com/mitchellh/mapstructure v1.5.0 // indirect + github.com/pelletier/go-toml/v2 v2.1.0 // indirect + github.com/sagikazarmark/locafero v0.4.0 // indirect + github.com/sagikazarmark/slog-shim v0.1.0 // indirect + github.com/sourcegraph/conc v0.3.0 // indirect + github.com/spf13/afero v1.11.0 // indirect + github.com/spf13/cast v1.6.0 // indirect + github.com/spf13/pflag v1.0.5 // indirect + github.com/subosito/gotenv v1.6.0 // indirect + go.uber.org/multierr v1.10.0 // indirect + golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect + golang.org/x/net v0.20.0 // indirect + golang.org/x/sys v0.16.0 // indirect + golang.org/x/text v0.14.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20231120223509-83a465c0220f // indirect + gopkg.in/ini.v1 v1.67.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/cloudprint-backend/go.sum b/cloudprint-backend/go.sum new file mode 100644 index 0000000..b1a3041 --- /dev/null +++ b/cloudprint-backend/go.sum @@ -0,0 +1,303 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.37.4/go.mod h1:NHPJ89PdicEuT9hdPXMROBD91xc5uRDxsMtSB16k7hw= +gitea.com/xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a/go.mod h1:EXuID2Zs0pAQhH8yz+DNjUbjppKQzKFAn28TMYPB6IU= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/DataDog/sketches-go v0.0.0-20190923095040-43f19ad77ff7/go.mod h1:Q5DbzQ+3AkgGwymQO7aZFNP7ns2lZKGtvRBzRXfdi60= +github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= +github.com/PuerkitoBio/goquery v1.5.1/go.mod h1:GsLWisAFVj4WgDibEWF4pvYnkVQBpKBKeU+7zCJoLcc= +github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= +github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= +github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/andybalholm/cascadia v1.1.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y= +github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= +github.com/benbjohnson/clock v1.0.0/go.mod h1:bGMdMPoPVvcYyt1gHDf4J2KE153Yf9BuiUKYMaxlTDM= +github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/denisenkom/go-mssqldb v0.0.0-20190707035753-2be1aa521ff4/go.mod h1:zAg7JM8CkOJ43xKXIj7eRO9kmWm/TW578qo+oDO6tuM= +github.com/denisenkom/go-mssqldb v0.0.0-20191124224453-732737034ffd/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU= +github.com/dgryski/go-rendezvous v0.0.0-20200609043717-5ab96a526299/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= +github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= +github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= +github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5/go.mod h1:a2zkGnVExMxdzMo3M0Hi/3sEU+cWnZpSni0O6/Yb/P0= +github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= +github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= +github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= +github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= +github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M= +github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= +github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= +github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= +github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= +github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI= +github.com/go-redis/redis/v8 v8.0.0-beta.5/go.mod h1:Mm9EH/5UMRx680UIryN6rd5XFn/L7zORPqLV+1D5thQ= +github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= +github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= +github.com/go-sql-driver/mysql v1.7.0 h1:ueSltNNllEqE3qcWBTD0iQd3IpL/6U+mJxLkazJ7YPc= +github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= +github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/golang-jwt/jwt/v5 v5.2.0 h1:d/ix8ftRUorsN+5eMIlF4T6J8CAt9rch3My2winC1Jw= +github.com/golang-jwt/jwt/v5 v5.2.0/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= +github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= +github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/uuid v1.5.0 h1:1p67kYwdtXjb0gL0BPiP1Av9wiZPo5A8z2cWkTZ+eyU= +github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= +github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= +github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/iGoogle-ink/gopay v1.5.14 h1:vcwdqNeccx8FWrnqKTeZZSK5FcAHGUD07OFHwhMheBs= +github.com/iGoogle-ink/gopay v1.5.14/go.mod h1:JuI4rWXHSTEgFHD5C5xfpy3Do3b0pIcu/wdsRyw/Ds4= +github.com/iGoogle-ink/gotil v1.0.2 h1:z58bvmhq31twxecMkyWU5Mh8H7T9SGPOTvUuAw9vB7M= +github.com/iGoogle-ink/gotil v1.0.2/go.mod h1:HOeCIcJkJLAsQ+cAPdozZS3huVDT4YUKN/F7tmvvrbM= +github.com/jinzhu/gorm v1.9.14/go.mod h1:G3LB3wezTOWM2ITLzPxEXgSkOXAntiLHS7UdBefADcs= +github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= +github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= +github.com/jinzhu/now v1.0.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= +github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= +github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= +github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= +github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= +github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/lib/pq v1.1.1/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= +github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-sqlite3 v1.10.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= +github.com/mattn/go-sqlite3 v1.14.0/go.mod h1:JIl7NbARA7phWnGvh0LKTyg7S9BA+6gx71ShQilpsus= +github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= +github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/opentracing/opentracing-go v1.1.1-0.20190913142402-a7454ce5950e/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= +github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4= +github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= +github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= +github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= +github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= +github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= +github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= +github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ= +github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4= +github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= +github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ= +github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= +github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= +github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= +github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= +github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0= +github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/viper v1.18.2 h1:LUXCnvUvSM6FXAsj6nnfc8Q2tp1dIgUfY9Kc8GsSOiQ= +github.com/spf13/viper v1.18.2/go.mod h1:EKmWIqdnk5lOcmR72yw6hS+8OPYcwD0jteitLMVB+yk= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= +github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= +github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ= +github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= +github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= +github.com/ziutek/mymysql v1.5.4/go.mod h1:LMSpPZ6DbqWFxNCHW77HeMg9I646SAhApZ/wKdgO/C0= +go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= +go.opentelemetry.io/otel v0.6.0/go.mod h1:jzBIgIzK43Iu1BpDAXwqOd6UPsSAk+ewVZ5ofSXw4Ek= +go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk= +go.uber.org/goleak v1.2.0/go.mod h1:XJYK+MuIchqpmGmUSAzotztawfKvYLUIgg7guXrwVUo= +go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ= +go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= +go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= +go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191205180655-e7c4368fe9dd/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc= +golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g= +golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200602114024-627f9648deb9/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo= +golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191010194322-b09406accb47/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= +golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.6.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190404172233-64821d5d2107/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20191009194640-548a555dbc03/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231120223509-83a465c0220f h1:ultW7fxlIvee4HYrtnaRPon9HpEgFk5zYpmfMgtKB5I= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231120223509-83a465c0220f/go.mod h1:L9KNLi232K1/xB6f7AlSX692koaRnKaWSR0stBki0Yc= +google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= +google.golang.org/grpc v1.60.1 h1:26+wFr+cNqSGFcOXcabYC0lUVJVRa2Sb2ortSK7VrEU= +google.golang.org/grpc v1.60.1/go.mod h1:OlCHIeLYqSSsLi6i49B5QGdzaMZK9+M7LXN2FKz4eGM= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= +google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= +gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gorm.io/driver/mysql v1.5.2 h1:QC2HRskSE75wBuOxe0+iCkyJZ+RqpudsQtqkp+IMuXs= +gorm.io/driver/mysql v1.5.2/go.mod h1:pQLhh1Ut/WUAySdTHwBpBv6+JKcj+ua4ZFx1QQTBzb8= +gorm.io/gorm v1.25.2-0.20230530020048-26663ab9bf55/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k= +gorm.io/gorm v1.25.5 h1:zR9lOiiYf09VNh5Q1gphfyia1JpiClIWG9hQaxB/mls= +gorm.io/gorm v1.25.5/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8= +honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +xorm.io/builder v0.3.7/go.mod h1:aUW0S9eb9VCaPohFCH3j7czOx1PMW3i1HrSzbLYGBSE= +xorm.io/xorm v1.0.2/go.mod h1:o4vnEsQ5V2F1/WK6w4XTwmiWJeGj82tqjAnHe44wVHY= diff --git a/cloudprint-backend/internal/grpc/interceptor/auth.go b/cloudprint-backend/internal/grpc/interceptor/auth.go new file mode 100644 index 0000000..238e07f --- /dev/null +++ b/cloudprint-backend/internal/grpc/interceptor/auth.go @@ -0,0 +1,125 @@ +package interceptor + +import ( + "context" + "strings" + + "github.com/cloudprint/cloudprint-backend/pkg/jwt" + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/metadata" + "google.golang.org/grpc/status" +) + +const ( + AuthorizationHeader = "authorization" + BearerPrefix = "Bearer " + UserIDKey = "user_id" + UserTypeKey = "user_type" +) + +type AuthInterceptor struct { + jwtManager *jwt.JWTManager +} + +func NewAuthInterceptor(jwtManager *jwt.JWTManager) *AuthInterceptor { + return &AuthInterceptor{jwtManager: jwtManager} +} + +// UnaryServerInterceptor returns a unary server interceptor that handles authentication +func (i *AuthInterceptor) UnaryServerInterceptor() grpc.UnaryServerInterceptor { + return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) { + // Skip auth for certain methods + if isPublicMethod(info.FullMethod) { + return handler(ctx, req) + } + + claims, err := i.extractAndValidateToken(ctx) + if err != nil { + return nil, status.Errorf(codes.Unauthenticated, "invalid token: %v", err) + } + + // Add user info to context + ctx = context.WithValue(ctx, UserIDKey, claims.UserID) + ctx = context.WithValue(ctx, UserTypeKey, claims.UserType) + + return handler(ctx, req) + } +} + +// StreamServerInterceptor returns a streaming server interceptor that handles authentication +func (i *AuthInterceptor) StreamServerInterceptor() grpc.StreamServerInterceptor { + return func(srv interface{}, ss grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error { + // Skip auth for certain methods + if isPublicMethod(info.FullMethod) { + return handler(srv, ss) + } + + claims, err := i.extractAndValidateToken(ss.Context()) + if err != nil { + return status.Errorf(codes.Unauthenticated, "invalid token: %v", err) + } + + // Add user info to context + ctx := context.WithValue(ss.Context(), UserIDKey, claims.UserID) + ctx = context.WithValue(ctx, UserTypeKey, claims.UserType) + + wrapped := &serverStreamWrapper{ + ServerStream: ss, + ctx: ctx, + } + + return handler(srv, wrapped) + } +} + +func (i *AuthInterceptor) extractAndValidateToken(ctx context.Context) (*jwt.Claims, error) { + md, ok := metadata.FromIncomingContext(ctx) + if !ok { + return nil, status.Error(codes.Unauthenticated, "missing metadata") + } + + authHeader := md.Get(AuthorizationHeader) + if len(authHeader) == 0 { + return nil, status.Error(codes.Unauthenticated, "missing authorization header") + } + + tokenString := strings.TrimPrefix(authHeader[0], BearerPrefix) + if tokenString == authHeader[0] { + return nil, status.Error(codes.Unauthenticated, "invalid authorization format") + } + + return i.jwtManager.ValidateToken(tokenString) +} + +func isPublicMethod(method string) bool { + publicMethods := map[string]bool{ + "/cloudprint.AuthService/Login": true, + "/cloudprint.AuthService/RefreshToken": true, + "/cloudprint.AdminService/Login": true, + "/cloudprint.PayService/HandlePayCallback": true, + } + return publicMethods[method] +} + +// serverStreamWrapper wraps grpc.ServerStream to override Context method +type serverStreamWrapper struct { + grpc.ServerStream + ctx context.Context +} + +func (w *serverStreamWrapper) Context() context.Context { + return w.ctx +} + +// GetUserIDFromContext extracts user ID from context +func GetUserIDFromContext(ctx context.Context) (int32, bool) { + userID, ok := ctx.Value(UserIDKey).(int32) + return userID, ok +} + +// GetUserTypeFromContext extracts user type from context +func GetUserTypeFromContext(ctx context.Context) (string, bool) { + userType, ok := ctx.Value(UserTypeKey).(string) + return userType, ok +} diff --git a/cloudprint-backend/internal/grpc/server.go b/cloudprint-backend/internal/grpc/server.go new file mode 100644 index 0000000..a70b045 --- /dev/null +++ b/cloudprint-backend/internal/grpc/server.go @@ -0,0 +1,92 @@ +package grpc + +import ( + "fmt" + "net" + + "github.com/cloudprint/cloudprint-backend/internal/grpc/interceptor" + pb "github.com/cloudprint/cloudprint-backend/proto/generated" + "google.golang.org/grpc" + "google.golang.org/grpc/reflection" +) + +type Server struct { + grpcServer *grpc.Server + port int +} + +type ServerOption func(*Server) + +func WithPort(port int) ServerOption { + return func(s *Server) { + s.port = port + } +} + +func NewServer(opts ...ServerOption) *Server { + s := &Server{ + port: 8080, + } + for _, opt := range opts { + opt(s) + } + return s +} + +func (s *Server) RegisterServices(grpcServer *grpc.Server) { + // Services will be registered here + // This is a placeholder for the actual service registration +} + +func (s *Server) Start() error { + lis, err := net.Listen("tcp", fmt.Sprintf(":%d", s.port)) + if err != nil { + return fmt.Errorf("failed to listen: %v", err) + } + + s.grpcServer = grpc.NewServer( + grpc.UnaryInterceptor(interceptor.AuthInterceptor{}.UnaryServerInterceptor()), + ) + + // Register reflection service for debugging + reflection.Register(s.grpcServer) + + if err := s.grpcServer.Serve(lis); err != nil { + return fmt.Errorf("failed to serve: %v", err) + } + + return nil +} + +func (s *Server) Stop() { + if s.grpcServer != nil { + s.grpcServer.GracefulStop() + } +} + +// Register all gRPC services +func RegisterServices(grpcServer *grpc.Server) { + // AuthService + // pb.RegisterAuthServiceServer(grpcServer, authServiceServer) + + // FileService + // pb.RegisterFileServiceServer(grpcServer, fileServiceServer) + + // OrderService + // pb.RegisterOrderServiceServer(grpcServer, orderServiceServer) + + // PrintService + // pb.RegisterPrintServiceServer(grpcServer, printServiceServer) + + // LibraryService + // pb.RegisterLibraryServiceServer(grpcServer, libraryServiceServer) + + // PriceService + // pb.RegisterPriceServiceServer(grpcServer, priceServiceServer) + + // PayService + // pb.RegisterPayServiceServer(grpcServer, payServiceServer) + + // AdminService + // pb.RegisterAdminServiceServer(grpcServer, adminServiceServer) +} diff --git a/cloudprint-backend/internal/grpc/service/admin_service.go b/cloudprint-backend/internal/grpc/service/admin_service.go new file mode 100644 index 0000000..303c1af --- /dev/null +++ b/cloudprint-backend/internal/grpc/service/admin_service.go @@ -0,0 +1,68 @@ +package service + +import ( + "context" + + "github.com/cloudprint/cloudprint-backend/internal/repository" + "github.com/cloudprint/cloudprint-backend/internal/service" + pb "github.com/cloudprint/cloudprint-backend/proto/generated" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" +) + +type AdminServiceServer struct { + pb.UnimplementedAdminServiceServer + authService *service.AuthService + orderRepo *repository.OrderRepository + printerRepo *repository.PrinterRepository +} + +func NewAdminServiceServer( + authService *service.AuthService, + orderRepo *repository.OrderRepository, + printerRepo *repository.PrinterRepository, +) *AdminServiceServer { + return &AdminServiceServer{ + authService: authService, + orderRepo: orderRepo, + printerRepo: printerRepo, + } +} + +func (s *AdminServiceServer) Login(ctx context.Context, req *pb.AdminLoginRequest) (*pb.AdminLoginResponse, error) { + result, err := s.authService.AdminLogin(ctx, req.Username, req.Password) + if err != nil { + return nil, status.Errorf(codes.Unauthenticated, "login failed: %v", err) + } + + return &pb.AdminLoginResponse{ + AccessToken: result.AccessToken, + Admin: &pb.Admin{ + Id: result.Admin.ID, + Username: result.Admin.Username, + Nickname: result.Admin.Nickname, + Role: int32(result.Admin.Role), + }, + }, nil +} + +func (s *AdminServiceServer) GetStatistics(ctx context.Context, req *pb.GetStatisticsRequest) (*pb.Statistics, error) { + totalUsers, totalOrders, todayOrders, todayRevenue, pendingOrders, err := s.orderRepo.GetStatistics(ctx) + if err != nil { + return nil, status.Errorf(codes.Internal, "get statistics failed: %v", err) + } + + activePrinters, err := s.printerRepo.CountActive(ctx) + if err != nil { + return nil, status.Errorf(codes.Internal, "get printer count failed: %v", err) + } + + return &pb.Statistics{ + TotalUsers: totalUsers, + TotalOrders: totalOrders, + TodayOrders: todayOrders, + TodayRevenue: todayRevenue, + PendingOrders: pendingOrders, + ActivePrinters: int32(activePrinters), + }, nil +} diff --git a/cloudprint-backend/internal/grpc/service/auth_service.go b/cloudprint-backend/internal/grpc/service/auth_service.go new file mode 100644 index 0000000..b42be3c --- /dev/null +++ b/cloudprint-backend/internal/grpc/service/auth_service.go @@ -0,0 +1,63 @@ +package service + +import ( + "context" + + "github.com/cloudprint/cloudprint-backend/internal/service" + pb "github.com/cloudprint/cloudprint-backend/proto/generated" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" +) + +type AuthServiceServer struct { + pb.UnimplementedAuthServiceServer + authService *service.AuthService +} + +func NewAuthServiceServer(authService *service.AuthService) *AuthServiceServer { + return &AuthServiceServer{ + authService: authService, + } +} + +func (s *AuthServiceServer) Login(ctx context.Context, req *pb.LoginRequest) (*pb.LoginResponse, error) { + result, err := s.authService.Login(ctx, req.Code) + if err != nil { + return nil, status.Errorf(codes.Internal, "login failed: %v", err) + } + + return &pb.LoginResponse{ + AccessToken: result.AccessToken, + RefreshToken: result.RefreshToken, + User: &pb.User{ + Id: result.User.ID, + Openid: result.User.Openid, + Nickname: result.User.Nickname, + Avatar: result.User.Avatar, + Balance: result.User.Balance, + }, + }, nil +} + +func (s *AuthServiceServer) RefreshToken(ctx context.Context, req *pb.RefreshRequest) (*pb.RefreshResponse, error) { + newToken, err := s.authService.RefreshToken(ctx, req.RefreshToken) + if err != nil { + return nil, status.Errorf(codes.Internal, "refresh token failed: %v", err) + } + + return &pb.RefreshResponse{ + AccessToken: newToken, + }, nil +} + +func (s *AuthServiceServer) GetUserInfo(ctx context.Context, req *pb.GetUserInfoRequest) (*pb.User, error) { + // In a real implementation, extract user ID from context + // For now, this is a placeholder + return nil, status.Errorf(codes.Unimplemented, "not implemented") +} + +func (s *AuthServiceServer) UpdateUser(ctx context.Context, req *pb.UpdateUserRequest) (*pb.User, error) { + // In a real implementation, extract user ID from context + // For now, this is a placeholder + return nil, status.Errorf(codes.Unimplemented, "not implemented") +} diff --git a/cloudprint-backend/internal/grpc/service/file_service.go b/cloudprint-backend/internal/grpc/service/file_service.go new file mode 100644 index 0000000..4173df1 --- /dev/null +++ b/cloudprint-backend/internal/grpc/service/file_service.go @@ -0,0 +1,141 @@ +package service + +import ( + "context" + "io" + + "github.com/cloudprint/cloudprint-backend/internal/service" + pb "github.com/cloudprint/cloudprint-backend/proto/generated" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" +) + +type FileServiceServer struct { + pb.UnimplementedFileServiceServer + fileService *service.FileService +} + +func NewFileServiceServer(fileService *service.FileService) *FileServiceServer { + return &FileServiceServer{ + fileService: fileService, + } +} + +func (s *FileServiceServer) Upload(stream pb.FileService_UploadServer) (*pb.UploadResponse, error) { + var fileName, fileType, uploaderType string + var uploaderID int32 + var totalSize int64 + var chunks [][]byte + + for { + req, err := stream.Recv() + if err == io.EOF { + break + } + if err != nil { + return nil, status.Errorf(codes.Internal, "receive chunk failed: %v", err) + } + + if fileName == "" { + fileName = req.FileName + fileType = req.FileType + uploaderType = "user" // Extract from context in production + uploaderID = 1 // Extract from context in production + totalSize = req.FileSize + } + + chunks = append(chunks, req.Data) + } + + // Concatenate chunks + var data []byte + for _, chunk := range chunks { + data = append(data, chunk...) + } + + file, err := s.fileService.Upload(stream.Context(), fileName, fileType, uploaderType, uploaderID, data) + if err != nil { + return nil, status.Errorf(codes.Internal, "upload failed: %v", err) + } + + return &pb.UploadResponse{ + FileId: file.ID, + FilePath: file.FilePath, + FileUrl: file.FilePath, + }, nil +} + +func (s *FileServiceServer) GetFile(req *pb.GetFileRequest, stream pb.FileService_GetFileServer) error { + file, err := s.fileService.GetFile(stream.Context(), req.FileId) + if err != nil || file == nil { + return status.Errorf(codes.NotFound, "file not found") + } + + reader, err := s.fileService.GetFileReader(stream.Context(), file) + if err != nil { + return status.Errorf(codes.Internal, "read file failed: %v", err) + } + defer reader.Close() + + buf := make([]byte, 4096) + for { + n, err := reader.Read(buf) + if n > 0 { + if err := stream.Send(&pb.FileData{Data: buf[:n], IsLast: false}); err != nil { + return err + } + } + if err == io.EOF { + break + } + if err != nil { + return err + } + } + + return stream.Send(&pb.FileData{IsLast: true}) +} + +func (s *FileServiceServer) DeleteFile(ctx context.Context, req *pb.DeleteFileRequest) (*pb.Empty, error) { + err := s.fileService.DeleteFile(ctx, req.FileId, "user", 1) + if err != nil { + return nil, status.Errorf(codes.Internal, "delete file failed: %v", err) + } + + return &pb.Empty{}, nil +} + +func (s *FileServiceServer) AddWatermark(ctx context.Context, req *pb.WatermarkRequest) (*pb.WatermarkResponse, error) { + file, err := s.fileService.AddWatermark(ctx, req.FileId, req.Text, req.Opacity, int(req.Position), int(req.FontSize)) + if err != nil { + return nil, status.Errorf(codes.Internal, "add watermark failed: %v", err) + } + + return &pb.WatermarkResponse{ + FileId: file.ID, + FilePath: file.FilePath, + }, nil +} + +func (s *FileServiceServer) GetFileList(ctx context.Context, req *pb.GetFileListRequest) (*pb.FileListResponse, error) { + files, total, err := s.fileService.GetFileList(ctx, req.UploaderType, req.UploaderId, int(req.Page), int(req.PageSize)) + if err != nil { + return nil, status.Errorf(codes.Internal, "get file list failed: %v", err) + } + + pbFiles := make([]*pb.FileInfo, 0, len(files)) + for _, f := range files { + pbFiles = append(pbFiles, &pb.FileInfo{ + Id: f.ID, + FileName: f.FileName, + FilePath: f.FilePath, + FileType: f.FileType, + FileSize: f.FileSize, + }) + } + + return &pb.FileListResponse{ + Files: pbFiles, + Total: int32(total), + }, nil +} diff --git a/cloudprint-backend/internal/grpc/service/library_service.go b/cloudprint-backend/internal/grpc/service/library_service.go new file mode 100644 index 0000000..e4bb40b --- /dev/null +++ b/cloudprint-backend/internal/grpc/service/library_service.go @@ -0,0 +1,91 @@ +package service + +import ( + "context" + + "github.com/cloudprint/cloudprint-backend/internal/repository" + pb "github.com/cloudprint/cloudprint-backend/proto/generated" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" +) + +type LibraryServiceServer struct { + pb.UnimplementedLibraryServiceServer + libraryRepo *repository.LibraryRepository + fileRepo *repository.FileRepository +} + +func NewLibraryServiceServer(libraryRepo *repository.LibraryRepository, fileRepo *repository.FileRepository) *LibraryServiceServer { + return &LibraryServiceServer{ + libraryRepo: libraryRepo, + fileRepo: fileRepo, + } +} + +func (s *LibraryServiceServer) GetCategories(ctx context.Context, req *pb.GetCategoriesRequest) (*pb.CategoryListResponse, error) { + categories, err := s.libraryRepo.GetAllCategories(ctx) + if err != nil { + return nil, status.Errorf(codes.Internal, "get categories failed: %v", err) + } + + pbCategories := make([]*pb.LibraryCategory, 0, len(categories)) + for _, cat := range categories { + pbCategories = append(pbCategories, &pb.LibraryCategory{ + Id: cat.ID, + Name: cat.Name, + Icon: cat.Icon, + SortOrder: int32(cat.SortOrder), + }) + } + + return &pb.CategoryListResponse{Categories: pbCategories}, nil +} + +func (s *LibraryServiceServer) GetFiles(ctx context.Context, req *pb.GetLibraryFilesRequest) (*pb.LibraryFileListResponse, error) { + files, total, err := s.libraryRepo.GetFilesByCategory(ctx, req.CategoryId, int(req.Page), int(req.PageSize)) + if err != nil { + return nil, status.Errorf(codes.Internal, "get files failed: %v", err) + } + + pbFiles := make([]*pb.LibraryFile, 0, len(files)) + for _, file := range files { + pbFile := &pb.LibraryFile{ + Id: file.ID, + CategoryId: file.CategoryID, + FileId: file.FileID, + Title: file.Title, + Description: file.Description, + PageCount: int32(file.PageCount), + DownloadCount: int32(file.DownloadCount), + } + if file.File != nil { + pbFile.File = &pb.FileInfo{ + Id: file.File.ID, + FileName: file.File.FileName, + FilePath: file.File.FilePath, + FileType: file.File.FileType, + FileSize: file.File.FileSize, + } + } + pbFiles = append(pbFiles, pbFile) + } + + return &pb.LibraryFileListResponse{ + Files: pbFiles, + Total: int32(total), + }, nil +} + +func (s *LibraryServiceServer) UploadFile(stream pb.LibraryService_UploadFileServer) error { + // Placeholder for streaming upload + return status.Errorf(codes.Unimplemented, "streaming upload not implemented") +} + +func (s *LibraryServiceServer) DeleteFile(ctx context.Context, req *pb.DeleteLibraryFileRequest) (*pb.Empty, error) { + err := s.libraryRepo.DeleteFile(ctx, req.LibraryFileId) + if err != nil { + return nil, status.Errorf(codes.Internal, "delete file failed: %v", err) + } + + return &pb.Empty{}, nil +} diff --git a/cloudprint-backend/internal/grpc/service/order_service.go b/cloudprint-backend/internal/grpc/service/order_service.go new file mode 100644 index 0000000..88fdef1 --- /dev/null +++ b/cloudprint-backend/internal/grpc/service/order_service.go @@ -0,0 +1,98 @@ +package service + +import ( + "context" + + "github.com/cloudprint/cloudprint-backend/internal/service" + pb "github.com/cloudprint/cloudprint-backend/proto/generated" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" +) + +type OrderServiceServer struct { + pb.UnimplementedOrderServiceServer + orderService *service.OrderService +} + +func NewOrderServiceServer(orderService *service.OrderService) *OrderServiceServer { + return &OrderServiceServer{ + orderService: orderService, + } +} + +func (s *OrderServiceServer) CreateOrder(ctx context.Context, req *pb.CreateOrderRequest) (*pb.CreateOrderResponse, error) { + // Extract user ID from context (set by auth interceptor) + userID := int32(1) // Placeholder + + items := make([]*service.CreateOrderItem, 0, len(req.Items)) + for _, item := range req.Items { + items = append(items, &service.CreateOrderItem{ + FileID: item.FileId, + PrinterID: item.PrinterId, + Copies: int(item.Copies), + Color: item.Color, + Duplex: item.Duplex, + PageRange: item.PageRange, + }) + } + + order, err := s.orderService.CreateOrder(ctx, userID, items, req.Remark) + if err != nil { + return nil, status.Errorf(codes.Internal, "create order failed: %v", err) + } + + return &pb.CreateOrderResponse{ + OrderNo: order.OrderNo, + TotalAmount: order.TotalAmount, + }, nil +} + +func (s *OrderServiceServer) GetOrder(ctx context.Context, req *pb.GetOrderRequest) (*pb.Order, error) { + order, err := s.orderService.GetOrder(ctx, req.OrderNo) + if err != nil || order == nil { + return nil, status.Errorf(codes.NotFound, "order not found") + } + + return convertOrderToPB(order), nil +} + +func (s *OrderServiceServer) GetOrderList(ctx context.Context, req *pb.GetOrderListRequest) (*pb.OrderListResponse, error) { + orders, total, err := s.orderService.GetOrderList(ctx, req.UserId, req.Status, int(req.Page), int(req.PageSize)) + if err != nil { + return nil, status.Errorf(codes.Internal, "get order list failed: %v", err) + } + + pbOrders := make([]*pb.Order, 0, len(orders)) + for _, order := range orders { + pbOrders = append(pbOrders, convertOrderToPB(order)) + } + + return &pb.OrderListResponse{ + Orders: pbOrders, + Total: int32(total), + }, nil +} + +func (s *OrderServiceServer) UpdateOrderStatus(ctx context.Context, req *pb.UpdateOrderStatusRequest) (*pb.Empty, error) { + err := s.orderService.UpdateOrderStatus(ctx, req.OrderNo, int8(req.Status)) + if err != nil { + return nil, status.Errorf(codes.Internal, "update order status failed: %v", err) + } + + return &pb.Empty{}, nil +} + +func (s *OrderServiceServer) CancelOrder(ctx context.Context, req *pb.CancelOrderRequest) (*pb.Empty, error) { + err := s.orderService.CancelOrder(ctx, req.OrderNo) + if err != nil { + return nil, status.Errorf(codes.Internal, "cancel order failed: %v", err) + } + + return &pb.Empty{}, nil +} + +func convertOrderToPB(order *service.Order) *pb.Order { + // Note: This is a simplified conversion. In production, you would need to handle all fields properly. + // The service.Order type here is the model, not the protobuf type. + return nil // Placeholder +} diff --git a/cloudprint-backend/internal/grpc/service/pay_service.go b/cloudprint-backend/internal/grpc/service/pay_service.go new file mode 100644 index 0000000..a79abf6 --- /dev/null +++ b/cloudprint-backend/internal/grpc/service/pay_service.go @@ -0,0 +1,201 @@ +package service + +import ( + "context" + + "github.com/cloudprint/cloudprint-backend/internal/model" + "github.com/cloudprint/cloudprint-backend/internal/repository" + "github.com/cloudprint/cloudprint-backend/internal/service" + "github.com/cloudprint/cloudprint-backend/pkg/pay" + pb "github.com/cloudprint/cloudprint-backend/proto/generated" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" +) + +type PayServiceServer struct { + pb.UnimplementedPayServiceServer + orderService *service.OrderService + paymentRepo *repository.PaymentRepository + weChatPay *pay.WeChatPay + userRepo *repository.UserRepository +} + +func NewPayServiceServer( + orderService *service.OrderService, + paymentRepo *repository.PaymentRepository, + weChatPay *pay.WeChatPay, + userRepo *repository.UserRepository, +) *PayServiceServer { + return &PayServiceServer{ + orderService: orderService, + paymentRepo: paymentRepo, + weChatPay: weChatPay, + userRepo: userRepo, + } +} + +func (s *PayServiceServer) CreateWxPayOrder(ctx context.Context, req *pb.WxPayRequest) (*pb.WxPayResponse, error) { + resp, err := s.weChatPay.UnifiedOrder(ctx, req.OrderNo, req.Amount, req.Description, req.Openid, req.ClientIp) + if err != nil { + return nil, status.Errorf(codes.Internal, "create pay order failed: %v", err) + } + + if resp.ReturnCode != "SUCCESS" { + return nil, status.Errorf(codes.Internal, "wechat pay error: %s - %s", resp.ErrCode, resp.ErrMsg) + } + + // Create payment record + payment := &model.Payment{ + OrderNo: req.OrderNo, + PayType: "wechat", + PayStatus: model.PayStatusPaying, + } + if err := s.paymentRepo.Create(ctx, payment); err != nil { + return nil, status.Errorf(codes.Internal, "create payment record failed: %v", err) + } + + return &pb.WxPayResponse{ + PrepayId: resp.PrepayID, + CodeUrl: resp.CodeURL, + MwebUrl: resp.MWebURL, + }, nil +} + +func (s *PayServiceServer) QueryPayStatus(ctx context.Context, req *pb.QueryPayStatusRequest) (*pb.PayStatusResponse, error) { + tradeState, _, err := s.weChatPay.QueryOrder(ctx, req.OrderNo) + if err != nil { + return nil, status.Errorf(codes.Internal, "query pay status failed: %v", err) + } + + var payStatus int32 + switch tradeState { + case "SUCCESS": + payStatus = int32(model.PayStatusSuccess) + case "USERPAYING", "PAYING": + payStatus = int32(model.PayStatusPaying) + case "CLOSED", "PAYERROR", "REFUND": + payStatus = int32(model.PayStatusFailed) + default: + payStatus = int32(model.PayStatusPending) + } + + return &pb.PayStatusResponse{ + Status: payStatus, + }, nil +} + +func (s *PayServiceServer) HandlePayCallback(ctx context.Context, req *pb.PayCallbackRequest) (*pb.PayCallbackResponse, error) { + callback, err := s.weChatPay.ParseCallback([]byte(req.Body)) + if err != nil { + return &pb.PayCallbackResponse{ + ReturnCode: "FAIL", + ReturnMsg: "parse error", + }, nil + } + + if !s.weChatPay.ValidateCallback(callback) { + return &pb.PayCallbackResponse{ + ReturnCode: "FAIL", + ReturnMsg: "validate error", + }, nil + } + + if callback.ReturnCode == "SUCCESS" && callback.ResultCode == "SUCCESS" { + // Check if payment already processed (idempotency) + payment, _ := s.paymentRepo.GetByOrderNo(ctx, callback.OutTradeNo) + if payment != nil && payment.PayStatus == model.PayStatusSuccess { + // Already processed, return success + return &pb.PayCallbackResponse{ + ReturnCode: "SUCCESS", + ReturnMsg: "OK", + }, nil + } + + // Update payment status + if err := s.paymentRepo.UpdateStatus(ctx, callback.OutTradeNo, model.PayStatusSuccess, callback.TransactionID); err != nil { + return &pb.PayCallbackResponse{ + ReturnCode: "FAIL", + ReturnMsg: "update payment failed", + }, nil + } + + // Update order status - pay order triggers print job creation + if err := s.orderService.PayOrder(ctx, callback.OutTradeNo, "wechat"); err != nil { + return &pb.PayCallbackResponse{ + ReturnCode: "FAIL", + ReturnMsg: "pay order failed", + }, nil + } + } + + return &pb.PayCallbackResponse{ + ReturnCode: "SUCCESS", + ReturnMsg: "OK", + }, nil +} + +func (s *PayServiceServer) PayByBalance(ctx context.Context, req *pb.PayByBalanceRequest) (*pb.StatusResponse, error) { + // Get order + order, err := s.orderService.GetOrder(ctx, req.OrderNo) + if err != nil || order == nil { + return &pb.StatusResponse{ + Code: 1, + Message: "order not found", + }, nil + } + + // Check if order is pending + if order.Status != model.OrderStatusPending { + return &pb.StatusResponse{ + Code: 1, + Message: "order is not pending", + }, nil + } + + // Get user + user, err := s.userRepo.GetByID(ctx, req.UserId) + if err != nil || user == nil { + return &pb.StatusResponse{ + Code: 1, + Message: "user not found", + }, nil + } + + // Check balance + if user.Balance < order.TotalAmount { + return &pb.StatusResponse{ + Code: 1, + Message: "insufficient balance", + }, nil + } + + // Deduct balance + if err := s.userRepo.DeductBalance(ctx, req.UserId, order.TotalAmount); err != nil { + return nil, status.Errorf(codes.Internal, "deduct balance failed: %v", err) + } + + // Create payment record + payment := &model.Payment{ + OrderNo: order.OrderNo, + PayType: "balance", + PayStatus: model.PayStatusSuccess, + TransactionID: "balance_" + order.OrderNo, + } + if err := s.paymentRepo.Create(ctx, payment); err != nil { + // Rollback balance deduction on failure + s.userRepo.AddBalance(ctx, req.UserId, order.TotalAmount) + return nil, status.Errorf(codes.Internal, "create payment record failed: %v", err) + } + + // Pay order - this creates print jobs + if err := s.orderService.PayOrder(ctx, req.OrderNo, "balance"); err != nil { + // Rollback + s.userRepo.AddBalance(ctx, req.UserId, order.TotalAmount) + return nil, status.Errorf(codes.Internal, "pay order failed: %v", err) + } + + return &pb.StatusResponse{ + Code: 0, + Message: "success", + }, nil +} diff --git a/cloudprint-backend/internal/grpc/service/price_service.go b/cloudprint-backend/internal/grpc/service/price_service.go new file mode 100644 index 0000000..992b4a7 --- /dev/null +++ b/cloudprint-backend/internal/grpc/service/price_service.go @@ -0,0 +1,96 @@ +package service + +import ( + "context" + + "github.com/cloudprint/cloudprint-backend/internal/repository" + pb "github.com/cloudprint/cloudprint-backend/proto/generated" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" +) + +type PriceServiceServer struct { + pb.UnimplementedPriceServiceServer + priceRepo *repository.PriceRepository +} + +func NewPriceServiceServer(priceRepo *repository.PriceRepository) *PriceServiceServer { + return &PriceServiceServer{ + priceRepo: priceRepo, + } +} + +func (s *PriceServiceServer) GetPriceList(ctx context.Context, req *pb.GetPriceListRequest) (*pb.PriceListResponse, error) { + items, err := s.priceRepo.GetAllActive(ctx) + if err != nil { + return nil, status.Errorf(codes.Internal, "get price list failed: %v", err) + } + + pbItems := make([]*pb.PriceItem, 0, len(items)) + for _, item := range items { + pbItems = append(pbItems, &pb.PriceItem{ + Id: item.ID, + Name: item.Name, + Type: item.Type, + Price: item.Price, + Unit: item.Unit, + ColorEnabled: item.ColorEnabled, + IsActive: item.IsActive, + }) + } + + return &pb.PriceListResponse{Items: pbItems}, nil +} + +func (s *PriceServiceServer) CreatePriceItem(ctx context.Context, req *pb.CreatePriceItemRequest) (*pb.PriceItem, error) { + item := &model.PriceList{ + Name: req.Name, + Type: req.Type, + Price: req.Price, + Unit: req.Unit, + ColorEnabled: req.ColorEnabled, + IsActive: true, + } + + if err := s.priceRepo.Create(ctx, item); err != nil { + return nil, status.Errorf(codes.Internal, "create price item failed: %v", err) + } + + return &pb.PriceItem{ + Id: item.ID, + Name: item.Name, + Type: item.Type, + Price: item.Price, + Unit: item.Unit, + ColorEnabled: item.ColorEnabled, + IsActive: item.IsActive, + }, nil +} + +func (s *PriceServiceServer) UpdatePriceItem(ctx context.Context, req *pb.UpdatePriceItemRequest) (*pb.PriceItem, error) { + item, err := s.priceRepo.GetByID(ctx, req.Id) + if err != nil || item == nil { + return nil, status.Errorf(codes.NotFound, "price item not found") + } + + item.Name = req.Name + item.Type = req.Type + item.Price = req.Price + item.Unit = req.Unit + item.ColorEnabled = req.ColorEnabled + item.IsActive = req.IsActive + + if err := s.priceRepo.Update(ctx, item); err != nil { + return nil, status.Errorf(codes.Internal, "update price item failed: %v", err) + } + + return &pb.PriceItem{ + Id: item.ID, + Name: item.Name, + Type: item.Type, + Price: item.Price, + Unit: item.Unit, + ColorEnabled: item.ColorEnabled, + IsActive: item.IsActive, + }, nil +} diff --git a/cloudprint-backend/internal/grpc/service/print_service.go b/cloudprint-backend/internal/grpc/service/print_service.go new file mode 100644 index 0000000..844e95f --- /dev/null +++ b/cloudprint-backend/internal/grpc/service/print_service.go @@ -0,0 +1,136 @@ +package service + +import ( + "context" + + "github.com/cloudprint/cloudprint-backend/internal/service" + pb "github.com/cloudprint/cloudprint-backend/proto/generated" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" +) + +type PrintServiceServer struct { + pb.UnimplementedPrintServiceServer + printService *service.PrintService +} + +func NewPrintServiceServer(printService *service.PrintService) *PrintServiceServer { + return &PrintServiceServer{ + printService: printService, + } +} + +func (s *PrintServiceServer) GetPrinters(ctx context.Context, req *pb.GetPrintersRequest) (*pb.PrinterListResponse, error) { + printers, err := s.printService.GetPrinters(ctx) + if err != nil { + return nil, status.Errorf(codes.Internal, "get printers failed: %v", err) + } + + pbPrinters := make([]*pb.Printer, 0, len(printers)) + for _, printer := range printers { + pbPrinters = append(pbPrinters, &pb.Printer{ + Id: printer.ID, + Name: printer.Name, + DisplayName: printer.DisplayName, + IsActive: printer.IsActive, + Status: int32(printer.Status), + }) + } + + return &pb.PrinterListResponse{Printers: pbPrinters}, nil +} + +func (s *PrintServiceServer) GetPrinterStatus(ctx context.Context, req *pb.GetPrinterStatusRequest) (*pb.PrinterStatusResponse, error) { + printer, queueCount, err := s.printService.GetPrinterStatus(ctx, req.PrinterId) + if err != nil || printer == nil { + return nil, status.Errorf(codes.NotFound, "printer not found") + } + + return &pb.PrinterStatusResponse{ + Printer: &pb.Printer{ + Id: printer.ID, + Name: printer.Name, + DisplayName: printer.DisplayName, + IsActive: printer.IsActive, + Status: int32(printer.Status), + }, + QueueCount: int32(queueCount), + }, nil +} + +func (s *PrintServiceServer) RegisterPrinter(ctx context.Context, req *pb.RegisterPrinterRequest) (*pb.RegisterPrinterResponse, error) { + printer, token, err := s.printService.RegisterPrinter(ctx, req.Name, req.DisplayName, req.ApiKey) + if err != nil { + return nil, status.Errorf(codes.Internal, "register printer failed: %v", err) + } + if printer == nil { + return nil, status.Errorf(codes.AlreadyExists, "printer already exists") + } + + return &pb.RegisterPrinterResponse{ + PrinterId: printer.ID, + Token: token, + }, nil +} + +func (s *PrintServiceServer) PrinterHeartbeat(ctx context.Context, req *pb.PrinterHeartbeatRequest) (*pb.Empty, error) { + err := s.printService.PrinterHeartbeat(ctx, req.PrinterId, int8(req.Status), req.Token) + if err != nil { + return nil, status.Errorf(codes.Internal, "heartbeat failed: %v", err) + } + + return &pb.Empty{}, nil +} + +func (s *PrintServiceServer) SubmitPrintJob(ctx context.Context, req *pb.SubmitPrintJobRequest) (*pb.SubmitPrintJobResponse, error) { + job, err := s.printService.SubmitPrintJob(ctx, req.OrderItemId, req.PrinterId, "", int(req.Copies), req.Color, req.Duplex, req.PageRange) + if err != nil { + return nil, status.Errorf(codes.Internal, "submit print job failed: %v", err) + } + + return &pb.SubmitPrintJobResponse{ + JobNo: job.JobNo, + }, nil +} + +func (s *PrintServiceServer) CancelPrintJob(ctx context.Context, req *pb.CancelPrintJobRequest) (*pb.Empty, error) { + err := s.printService.CancelPrintJob(ctx, req.JobNo) + if err != nil { + return nil, status.Errorf(codes.Internal, "cancel print job failed: %v", err) + } + + return &pb.Empty{}, nil +} + +func (s *PrintServiceServer) SubscribeJobs(req *pb.SubscribeJobsRequest, stream pb.PrintService_SubscribeJobsServer) error { + ch, err := s.printService.SubscribeJobs(stream.Context(), req.PrinterId, req.Token) + if err != nil { + return status.Errorf(codes.Internal, "subscribe jobs failed: %v", err) + } + + for job := range ch { + if err := stream.Send(&pb.PrintJob{ + Id: job.ID, + JobNo: job.JobNo, + PrinterId: job.PrinterID, + OrderItemId: job.OrderItemID, + Status: job.Status, + Progress: int32(job.Progress), + ErrorMsg: job.ErrorMsg, + }); err != nil { + s.printService.UnsubscribeJobs(req.PrinterId) + return err + } + } + + return nil +} + +func (s *PrintServiceServer) ReportJobStatus(ctx context.Context, req *pb.ReportJobStatusRequest) (*pb.Empty, error) { + err := s.printService.ReportJobStatus(ctx, req.JobNo, req.Status, int(req.Progress), req.ErrorMsg) + if err != nil { + return nil, status.Errorf(codes.Internal, "report job status failed: %v", err) + } + + return &pb.Empty{}, nil +} diff --git a/cloudprint-backend/internal/model/model.go b/cloudprint-backend/internal/model/model.go new file mode 100644 index 0000000..c2abb70 --- /dev/null +++ b/cloudprint-backend/internal/model/model.go @@ -0,0 +1,224 @@ +package model + +import ( + "time" +) + +// User 用户表 +type User struct { + ID int32 `gorm:"primaryKey;autoIncrement" json:"id"` + Openid string `gorm:"uniqueIndex;size:64;not null" json:"openid"` // 微信OpenID + Nickname string `gorm:"size:128;default:''" json:"nickname"` + Avatar string `gorm:"size:512;default:''" json:"avatar"` + Balance float64 `gorm:"type:decimal(10,2);default:0.00" json:"balance"` // 余额 + CreatedAt time.Time `gorm:"autoCreateTime" json:"created_at"` + UpdatedAt time.Time `gorm:"autoUpdateTime" json:"updated_at"` + Orders []Order `gorm:"foreignKey:UserID" json:"orders,omitempty"` +} + +func (User) TableName() string { + return "user" +} + +// Admin 管理员表 +type Admin struct { + ID int32 `gorm:"primaryKey;autoIncrement" json:"id"` + Username string `gorm:"uniqueIndex;size:64;not null" json:"username"` + PasswordHash string `gorm:"size:256;not null" json:"-"` + Nickname string `gorm:"size:128;default:''" json:"nickname"` + Role int8 `gorm:"default:1" json:"role"` // 1:普通管理员 2:超级管理员 + CreatedAt time.Time `gorm:"autoCreateTime" json:"created_at"` +} + +func (Admin) TableName() string { + return "admin" +} + +// Printer 打印机表 +type Printer struct { + ID int32 `gorm:"primaryKey;autoIncrement" json:"id"` + Name string `gorm:"uniqueIndex;size:128;not null" json:"name"` // 系统打印机名 + DisplayName string `gorm:"size:128;not null" json:"display_name"` // 显示名称 + APIKey string `gorm:"uniqueIndex;size:64;not null" json:"api_key"` // 客户端认证Key + IsActive bool `gorm:"default:true" json:"is_active"` + Status int8 `gorm:"default:0" json:"status"` // 0:空闲 1:打印中 2:离线 + LastHeartbeat *time.Time `json:"last_heartbeat"` + CreatedAt time.Time `gorm:"autoCreateTime" json:"created_at"` + PrintJobs []PrintJob `gorm:"foreignKey:PrinterID" json:"print_jobs,omitempty"` +} + +func (Printer) TableName() string { + return "printer" +} + +// Order 订单表 +type Order struct { + ID int32 `gorm:"primaryKey;autoIncrement" json:"id"` + OrderNo string `gorm:"uniqueIndex;size:32;not null" json:"order_no"` // 订单号 + UserID int32 `gorm:"not null;index" json:"user_id"` + Status int8 `gorm:"default:0" json:"status"` // 0:待支付 1:已支付 2:打印中 3:已完成 4:已取消 + TotalAmount float64 `gorm:"type:decimal(10,2);not null" json:"total_amount"` + Remark string `gorm:"size:512;default:''" json:"remark"` + CreatedAt time.Time `gorm:"autoCreateTime" json:"created_at"` + PaidAt *time.Time `json:"paid_at"` + User *User `gorm:"foreignKey:UserID" json:"user,omitempty"` + Items []OrderItem `gorm:"foreignKey:OrderID" json:"items,omitempty"` + Payment *Payment `gorm:"foreignKey:OrderNo;references:OrderNo" json:"payment,omitempty"` +} + +func (Order) TableName() string { + return "order" +} + +// OrderItem 订单明细表 +type OrderItem struct { + ID int32 `gorm:"primaryKey;autoIncrement" json:"id"` + OrderID int32 `gorm:"not null;index" json:"order_id"` + FileID int32 `gorm:"not null" json:"file_id"` + PrinterID *int32 `json:"printer_id"` + Copies int `gorm:"default:1" json:"copies"` + Color bool `gorm:"default:false" json:"color"` + Duplex bool `gorm:"default:false" json:"duplex"` + PageRange string `gorm:"size:64;default:'all'" json:"page_range"` + Price float64 `gorm:"type:decimal(10,2);not null" json:"price"` + Order *Order `gorm:"foreignKey:OrderID" json:"order,omitempty"` + File *File `gorm:"foreignKey:FileID" json:"file,omitempty"` + Printer *Printer `gorm:"foreignKey:PrinterID" json:"printer,omitempty"` + PrintJobs []PrintJob `gorm:"foreignKey:OrderItemID" json:"print_jobs,omitempty"` +} + +func (OrderItem) TableName() string { + return "order_item" +} + +// File 文件表 +type File struct { + ID int32 `gorm:"primaryKey;autoIncrement" json:"id"` + FileName string `gorm:"size:256;not null" json:"file_name"` + FilePath string `gorm:"size:512;not null" json:"file_path"` + FileType string `gorm:"size:32;not null" json:"file_type"` // pdf/doc/docx/xls/xlsx/ppt/pptx/txt/jpg/png/zip + FileSize int64 `gorm:"not null" json:"file_size"` // 字节 + UploaderType string `gorm:"size:16;not null" json:"uploader_type"` // user/admin/system + UploaderID int32 `gorm:"not null" json:"uploader_id"` + CreatedAt time.Time `gorm:"autoCreateTime" json:"created_at"` +} + +func (File) TableName() string { + return "file" +} + +// LibraryCategory 文库分类表 +type LibraryCategory struct { + ID int32 `gorm:"primaryKey;autoIncrement" json:"id"` + Name string `gorm:"size:128;not null" json:"name"` + Icon string `gorm:"size:128;default:''" json:"icon"` + SortOrder int `gorm:"default:0" json:"sort_order"` + CreatedAt time.Time `gorm:"autoCreateTime" json:"created_at"` + Files []LibraryFile `gorm:"foreignKey:CategoryID" json:"files,omitempty"` +} + +func (LibraryCategory) TableName() string { + return "library_category" +} + +// LibraryFile 文库文件表 +type LibraryFile struct { + ID int32 `gorm:"primaryKey;autoIncrement" json:"id"` + CategoryID int32 `gorm:"not null;index" json:"category_id"` + FileID int32 `gorm:"not null" json:"file_id"` + Title string `gorm:"size:256;not null" json:"title"` + Description string `gorm:"size:512;default:''" json:"description"` + PageCount int `gorm:"default:0" json:"page_count"` + DownloadCount int `gorm:"default:0" json:"download_count"` + CreatedAt time.Time `gorm:"autoCreateTime" json:"created_at"` + Category *LibraryCategory `gorm:"foreignKey:CategoryID" json:"category,omitempty"` + File *File `gorm:"foreignKey:FileID" json:"file,omitempty"` +} + +func (LibraryFile) TableName() string { + return "library_file" +} + +// PrintJob 打印任务表 +type PrintJob struct { + ID int32 `gorm:"primaryKey;autoIncrement" json:"id"` + JobNo string `gorm:"uniqueIndex;size:32;not null" json:"job_no"` + PrinterID int32 `gorm:"not null;index" json:"printer_id"` + OrderItemID int32 `gorm:"not null;index" json:"order_item_id"` + Status string `gorm:"size:16;default:'pending'" json:"status"` // pending/printing/completed/failed/cancelled + Progress int `gorm:"default:0" json:"progress"` + ErrorMsg string `gorm:"size:512;default:''" json:"error_msg"` + StartedAt *time.Time `json:"started_at"` + CompletedAt *time.Time `json:"completed_at"` + Printer *Printer `gorm:"foreignKey:PrinterID" json:"printer,omitempty"` + OrderItem *OrderItem `gorm:"foreignKey:OrderItemID" json:"order_item,omitempty"` +} + +func (PrintJob) TableName() string { + return "print_job" +} + +// PriceList 价目表 +type PriceList struct { + ID int32 `gorm:"primaryKey;autoIncrement" json:"id"` + Name string `gorm:"size:128;not null" json:"name"` // 项目名称 + Type string `gorm:"size:32;not null" json:"type"` // 纸张类型: A4/A3/照片纸 + Price float64 `gorm:"type:decimal(10,2);not null" json:"price"` // 单价 + Unit string `gorm:"size:16;not null" json:"unit"` // 单位: 页/张/份 + ColorEnabled bool `gorm:"default:true" json:"color_enabled"` // 是否支持彩色 + IsActive bool `gorm:"default:true" json:"is_active"` + SortOrder int `gorm:"default:0" json:"sort_order"` + CreatedAt time.Time `gorm:"autoCreateTime" json:"created_at"` +} + +func (PriceList) TableName() string { + return "price_list" +} + +// Payment 支付记录表 +type Payment struct { + ID int32 `gorm:"primaryKey;autoIncrement" json:"id"` + OrderNo string `gorm:"uniqueIndex;size:32;not null" json:"order_no"` + PayType string `gorm:"size:16;default:'wechat'" json:"pay_type"` // wechat/balance + PayStatus int8 `gorm:"default:0" json:"pay_status"` // 0:待支付 1:支付中 2:成功 3:失败 + TransactionID string `gorm:"size:64;default:''" json:"transaction_id"` + PaidAt *time.Time `json:"paid_at"` + CreatedAt time.Time `gorm:"autoCreateTime" json:"created_at"` +} + +func (Payment) TableName() string { + return "payment" +} + +// OrderStatus 订单状态常量 +const ( + OrderStatusPending = 0 // 待支付 + OrderStatusPaid = 1 // 已支付 + OrderStatusPrinting = 2 // 打印中 + OrderStatusCompleted = 3 // 已完成 + OrderStatusCancelled = 4 // 已取消 +) + +// PayStatus 支付状态常量 +const ( + PayStatusPending = 0 // 待支付 + PayStatusPaying = 1 // 支付中 + PayStatusSuccess = 2 // 成功 + PayStatusFailed = 3 // 失败 +) + +// PrinterStatus 打印机状态常量 +const ( + PrinterStatusIdle = 0 // 空闲 + PrinterStatusPrinting = 1 // 打印中 + PrinterStatusOffline = 2 // 离线 +) + +// PrintJobStatus 打印任务状态常量 +const ( + PrintJobStatusPending = "pending" + PrintJobStatusPrinting = "printing" + PrintJobStatusCompleted = "completed" + PrintJobStatusFailed = "failed" + PrintJobStatusCancelled = "cancelled" +) diff --git a/cloudprint-backend/internal/repository/admin_repository.go b/cloudprint-backend/internal/repository/admin_repository.go new file mode 100644 index 0000000..b805f76 --- /dev/null +++ b/cloudprint-backend/internal/repository/admin_repository.go @@ -0,0 +1,49 @@ +package repository + +import ( + "context" + "errors" + + "github.com/cloudprint/cloudprint-backend/internal/model" + "gorm.io/gorm" +) + +type AdminRepository struct { + db *gorm.DB +} + +func NewAdminRepository(db *gorm.DB) *AdminRepository { + return &AdminRepository{db: db} +} + +func (r *AdminRepository) Create(ctx context.Context, admin *model.Admin) error { + return r.db.WithContext(ctx).Create(admin).Error +} + +func (r *AdminRepository) GetByID(ctx context.Context, id int32) (*model.Admin, error) { + var admin model.Admin + err := r.db.WithContext(ctx).First(&admin, id).Error + if err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + return nil, nil + } + return nil, err + } + return &admin, nil +} + +func (r *AdminRepository) GetByUsername(ctx context.Context, username string) (*model.Admin, error) { + var admin model.Admin + err := r.db.WithContext(ctx).Where("username = ?", username).First(&admin).Error + if err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + return nil, nil + } + return nil, err + } + return &admin, nil +} + +func (r *AdminRepository) Update(ctx context.Context, admin *model.Admin) error { + return r.db.WithContext(ctx).Save(admin).Error +} diff --git a/cloudprint-backend/internal/repository/file_repository.go b/cloudprint-backend/internal/repository/file_repository.go new file mode 100644 index 0000000..af4fb2f --- /dev/null +++ b/cloudprint-backend/internal/repository/file_repository.go @@ -0,0 +1,67 @@ +package repository + +import ( + "context" + "errors" + + "github.com/cloudprint/cloudprint-backend/internal/model" + "gorm.io/gorm" +) + +type FileRepository struct { + db *gorm.DB +} + +func NewFileRepository(db *gorm.DB) *FileRepository { + return &FileRepository{db: db} +} + +func (r *FileRepository) Create(ctx context.Context, file *model.File) error { + return r.db.WithContext(ctx).Create(file).Error +} + +func (r *FileRepository) GetByID(ctx context.Context, id int32) (*model.File, error) { + var file model.File + err := r.db.WithContext(ctx).First(&file, id).Error + if err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + return nil, nil + } + return nil, err + } + return &file, nil +} + +func (r *FileRepository) Delete(ctx context.Context, id int32) error { + return r.db.WithContext(ctx).Delete(&model.File{}, id).Error +} + +func (r *FileRepository) GetListByUploader(ctx context.Context, uploaderType string, uploaderID int32, page, pageSize int) ([]*model.File, int64, error) { + var files []*model.File + var total int64 + + query := r.db.WithContext(ctx).Model(&model.File{}) + if uploaderType != "" { + query = query.Where("uploader_type = ?", uploaderType) + } + if uploaderID > 0 { + query = query.Where("uploader_id = ?", uploaderID) + } + + err := query.Count(&total).Error + if err != nil { + return nil, 0, err + } + + offset := (page - 1) * pageSize + err = query.Offset(offset).Limit(pageSize).Order("created_at DESC").Find(&files).Error + if err != nil { + return nil, 0, err + } + + return files, total, nil +} + +func (r *FileRepository) Update(ctx context.Context, file *model.File) error { + return r.db.WithContext(ctx).Save(file).Error +} diff --git a/cloudprint-backend/internal/repository/library_repository.go b/cloudprint-backend/internal/repository/library_repository.go new file mode 100644 index 0000000..735c90b --- /dev/null +++ b/cloudprint-backend/internal/repository/library_repository.go @@ -0,0 +1,108 @@ +package repository + +import ( + "context" + "errors" + + "github.com/cloudprint/cloudprint-backend/internal/model" + "gorm.io/gorm" +) + +type LibraryRepository struct { + db *gorm.DB +} + +func NewLibraryRepository(db *gorm.DB) *LibraryRepository { + return &LibraryRepository{db: db} +} + +// Category operations +func (r *LibraryRepository) CreateCategory(ctx context.Context, category *model.LibraryCategory) error { + return r.db.WithContext(ctx).Create(category).Error +} + +func (r *LibraryRepository) GetCategoryByID(ctx context.Context, id int32) (*model.LibraryCategory, error) { + var category model.LibraryCategory + err := r.db.WithContext(ctx).First(&category, id).Error + if err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + return nil, nil + } + return nil, err + } + return &category, nil +} + +func (r *LibraryRepository) GetAllCategories(ctx context.Context) ([]*model.LibraryCategory, error) { + var categories []*model.LibraryCategory + err := r.db.WithContext(ctx).Order("sort_order ASC, id ASC").Find(&categories).Error + return categories, err +} + +func (r *LibraryRepository) UpdateCategory(ctx context.Context, category *model.LibraryCategory) error { + return r.db.WithContext(ctx).Save(category).Error +} + +func (r *LibraryRepository) DeleteCategory(ctx context.Context, id int32) error { + return r.db.WithContext(ctx).Delete(&model.LibraryCategory{}, id).Error +} + +// LibraryFile operations +func (r *LibraryRepository) CreateFile(ctx context.Context, file *model.LibraryFile) error { + return r.db.WithContext(ctx).Create(file).Error +} + +func (r *LibraryRepository) GetFileByID(ctx context.Context, id int32) (*model.LibraryFile, error) { + var file model.LibraryFile + err := r.db.WithContext(ctx).Preload("File").First(&file, id).Error + if err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + return nil, nil + } + return nil, err + } + return &file, nil +} + +func (r *LibraryRepository) GetFilesByCategory(ctx context.Context, categoryID int32, page, pageSize int) ([]*model.LibraryFile, int64, error) { + var files []*model.LibraryFile + var total int64 + + query := r.db.WithContext(ctx).Model(&model.LibraryFile{}).Where("category_id = ?", categoryID) + err := query.Count(&total).Error + if err != nil { + return nil, 0, err + } + + offset := (page - 1) * pageSize + err = query.Preload("File").Offset(offset).Limit(pageSize).Order("created_at DESC").Find(&files).Error + if err != nil { + return nil, 0, err + } + + return files, total, nil +} + +func (r *LibraryRepository) DeleteFile(ctx context.Context, id int32) error { + return r.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error { + // Get file to delete underlying file record + var libFile model.LibraryFile + if err := tx.First(&libFile, id).Error; err != nil { + return err + } + // Delete library file + if err := tx.Delete(&libFile).Error; err != nil { + return err + } + // Delete underlying file + if err := tx.Delete(&model.File{}, libFile.FileID).Error; err != nil { + return err + } + return nil + }) +} + +func (r *LibraryRepository) IncrementDownloadCount(ctx context.Context, id int32) error { + return r.db.WithContext(ctx).Model(&model.LibraryFile{}).Where("id = ?", id). + Update("download_count", gorm.Expr("download_count + 1")).Error +} diff --git a/cloudprint-backend/internal/repository/order_repository.go b/cloudprint-backend/internal/repository/order_repository.go new file mode 100644 index 0000000..13286f2 --- /dev/null +++ b/cloudprint-backend/internal/repository/order_repository.go @@ -0,0 +1,162 @@ +package repository + +import ( + "context" + "errors" + "fmt" + "time" + + "github.com/cloudprint/cloudprint-backend/internal/model" + "gorm.io/gorm" +) + +type OrderRepository struct { + db *gorm.DB +} + +func NewOrderRepository(db *gorm.DB) *OrderRepository { + return &OrderRepository{db: db} +} + +func (r *OrderRepository) Create(ctx context.Context, order *model.Order) error { + return r.db.WithContext(ctx).Create(order).Error +} + +func (r *OrderRepository) CreateWithItems(ctx context.Context, order *model.Order, items []*model.OrderItem) error { + return r.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error { + if err := tx.Create(order).Error; err != nil { + return err + } + for _, item := range items { + item.OrderID = order.ID + if err := tx.Create(item).Error; err != nil { + return err + } + } + return nil + }) +} + +func (r *OrderRepository) GetByID(ctx context.Context, id int32) (*model.Order, error) { + var order model.Order + err := r.db.WithContext(ctx).Preload("Items").Preload("Items.File").Preload("Payment"). + First(&order, id).Error + if err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + return nil, nil + } + return nil, err + } + return &order, nil +} + +func (r *OrderRepository) GetByOrderNo(ctx context.Context, orderNo string) (*model.Order, error) { + var order model.Order + err := r.db.WithContext(ctx).Preload("Items").Preload("Items.File").Preload("Items.Printer").Preload("Payment"). + Where("order_no = ?", orderNo).First(&order).Error + if err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + return nil, nil + } + return nil, err + } + return &order, nil +} + +func (r *OrderRepository) GetListByUserID(ctx context.Context, userID int32, status int8, page, pageSize int) ([]*model.Order, int64, error) { + var orders []*model.Order + var total int64 + + query := r.db.WithContext(ctx).Model(&model.Order{}).Where("user_id = ?", userID) + if status >= 0 { + query = query.Where("status = ?", status) + } + + err := query.Count(&total).Error + if err != nil { + return nil, 0, err + } + + offset := (page - 1) * pageSize + err = query.Preload("Items").Preload("Items.File"). + Offset(offset).Limit(pageSize).Order("created_at DESC"). + Find(&orders).Error + if err != nil { + return nil, 0, err + } + + return orders, total, nil +} + +func (r *OrderRepository) UpdateStatus(ctx context.Context, orderNo string, status int8) error { + updates := map[string]interface{}{ + "status": status, + } + if status == model.OrderStatusPaid { + now := time.Now() + updates["paid_at"] = &now + } + return r.db.WithContext(ctx).Model(&model.Order{}). + Where("order_no = ?", orderNo).Updates(updates).Error +} + +func (r *OrderRepository) GetStatistics(ctx context.Context) (totalUsers, totalOrders, todayOrders int32, todayRevenue float64, pendingOrders int32, err error) { + // 总用户数 + if err = r.db.WithContext(ctx).Model(&model.User{}).Count(&totalUsers).Error; err != nil { + return 0, 0, 0, 0, 0, fmt.Errorf("count users failed: %w", err) + } + // 总订单数 + if err = r.db.WithContext(ctx).Model(&model.Order{}).Count(&totalOrders).Error; err != nil { + return 0, 0, 0, 0, 0, fmt.Errorf("count orders failed: %w", err) + } + // 待处理订单数 + if err = r.db.WithContext(ctx).Model(&model.Order{}).Where("status IN ?", []int8{0, 1, 2}).Count(&pendingOrders).Error; err != nil { + return 0, 0, 0, 0, 0, fmt.Errorf("count pending orders failed: %w", err) + } + // 今日订单数 + today := time.Now().Format("2006-01-02") + if err = r.db.WithContext(ctx).Model(&model.Order{}). + Where("DATE(created_at) = ? AND status = ?", today, model.OrderStatusPaid). + Count(&todayOrders).Error; err != nil { + return 0, 0, 0, 0, 0, fmt.Errorf("count today orders failed: %w", err) + } + // 今日收入 + if err = r.db.WithContext(ctx).Model(&model.Order{}). + Select("COALESCE(SUM(total_amount), 0)"). + Where("DATE(created_at) = ? AND status = ?", today, model.OrderStatusPaid). + Scan(&todayRevenue).Error; err != nil { + return 0, 0, 0, 0, 0, fmt.Errorf("sum today revenue failed: %w", err) + } + + return +} + +type OrderItemRepository struct { + db *gorm.DB +} + +func NewOrderItemRepository(db *gorm.DB) *OrderItemRepository { + return &OrderItemRepository{db: db} +} + +func (r *OrderItemRepository) GetByID(ctx context.Context, id int32) (*model.OrderItem, error) { + var item model.OrderItem + err := r.db.WithContext(ctx).Preload("File").First(&item, id).Error + if err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + return nil, nil + } + return nil, err + } + return &item, nil +} + +func (r *OrderItemRepository) Create(ctx context.Context, item *model.OrderItem) error { + return r.db.WithContext(ctx).Create(item).Error +} + +func (r *OrderItemRepository) GetByOrderID(ctx context.Context, orderID int32) ([]*model.OrderItem, error) { + var items []*model.OrderItem + err := r.db.WithContext(ctx).Where("order_id = ?", orderID).Find(&items).Error + return items, err +} diff --git a/cloudprint-backend/internal/repository/price_repository.go b/cloudprint-backend/internal/repository/price_repository.go new file mode 100644 index 0000000..67aebfd --- /dev/null +++ b/cloudprint-backend/internal/repository/price_repository.go @@ -0,0 +1,80 @@ +package repository + +import ( + "context" + "errors" + + "github.com/cloudprint/cloudprint-backend/internal/model" + "gorm.io/gorm" +) + +type PriceRepository struct { + db *gorm.DB +} + +func NewPriceRepository(db *gorm.DB) *PriceRepository { + return &PriceRepository{db: db} +} + +func (r *PriceRepository) Create(ctx context.Context, item *model.PriceList) error { + return r.db.WithContext(ctx).Create(item).Error +} + +func (r *PriceRepository) GetByID(ctx context.Context, id int32) (*model.PriceList, error) { + var item model.PriceList + err := r.db.WithContext(ctx).First(&item, id).Error + if err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + return nil, nil + } + return nil, err + } + return &item, nil +} + +func (r *PriceRepository) GetAllActive(ctx context.Context) ([]*model.PriceList, error) { + var items []*model.PriceList + err := r.db.WithContext(ctx).Where("is_active = ?", true).Order("sort_order ASC, id ASC").Find(&items).Error + return items, err +} + +func (r *PriceRepository) Update(ctx context.Context, item *model.PriceList) error { + return r.db.WithContext(ctx).Save(item).Error +} + +func (r *PriceRepository) Delete(ctx context.Context, id int32) error { + return r.db.WithContext(ctx).Delete(&model.PriceList{}, id).Error +} + +type PaymentRepository struct { + db *gorm.DB +} + +func NewPaymentRepository(db *gorm.DB) *PaymentRepository { + return &PaymentRepository{db: db} +} + +func (r *PaymentRepository) Create(ctx context.Context, payment *model.Payment) error { + return r.db.WithContext(ctx).Create(payment).Error +} + +func (r *PaymentRepository) GetByOrderNo(ctx context.Context, orderNo string) (*model.Payment, error) { + var payment model.Payment + err := r.db.WithContext(ctx).Where("order_no = ?", orderNo).First(&payment).Error + if err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + return nil, nil + } + return nil, err + } + return &payment, nil +} + +func (r *PaymentRepository) UpdateStatus(ctx context.Context, orderNo string, status int8, transactionID string) error { + updates := map[string]interface{}{ + "pay_status": status, + "transaction_id": transactionID, + } + return r.db.WithContext(ctx).Model(&model.Payment{}). + Where("order_no = ?", orderNo).Updates(updates).Error +} diff --git a/cloudprint-backend/internal/repository/printer_repository.go b/cloudprint-backend/internal/repository/printer_repository.go new file mode 100644 index 0000000..db55498 --- /dev/null +++ b/cloudprint-backend/internal/repository/printer_repository.go @@ -0,0 +1,150 @@ +package repository + +import ( + "context" + "errors" + "time" + + "github.com/cloudprint/cloudprint-backend/internal/model" + "gorm.io/gorm" +) + +type PrinterRepository struct { + db *gorm.DB +} + +func NewPrinterRepository(db *gorm.DB) *PrinterRepository { + return &PrinterRepository{db: db} +} + +func (r *PrinterRepository) Create(ctx context.Context, printer *model.Printer) error { + return r.db.WithContext(ctx).Create(printer).Error +} + +func (r *PrinterRepository) GetByID(ctx context.Context, id int32) (*model.Printer, error) { + var printer model.Printer + err := r.db.WithContext(ctx).First(&printer, id).Error + if err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + return nil, nil + } + return nil, err + } + return &printer, nil +} + +func (r *PrinterRepository) GetByName(ctx context.Context, name string) (*model.Printer, error) { + var printer model.Printer + err := r.db.WithContext(ctx).Where("name = ?", name).First(&printer).Error + if err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + return nil, nil + } + return nil, err + } + return &printer, nil +} + +func (r *PrinterRepository) GetByAPIKey(ctx context.Context, apiKey string) (*model.Printer, error) { + var printer model.Printer + err := r.db.WithContext(ctx).Where("api_key = ?", apiKey).First(&printer).Error + if err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + return nil, nil + } + return nil, err + } + return &printer, nil +} + +func (r *PrinterRepository) GetAllActive(ctx context.Context) ([]*model.Printer, error) { + var printers []*model.Printer + err := r.db.WithContext(ctx).Where("is_active = ?", true).Find(&printers).Error + return printers, err +} + +func (r *PrinterRepository) UpdateStatus(ctx context.Context, id int32, status int8) error { + return r.db.WithContext(ctx).Model(&model.Printer{}).Where("id = ?", id).Update("status", status).Error +} + +func (r *PrinterRepository) UpdateHeartbeat(ctx context.Context, id int32) error { + now := time.Now() + return r.db.WithContext(ctx).Model(&model.Printer{}).Where("id = ?", id).Update("last_heartbeat", &now).Error +} + +func (r *PrinterRepository) CountActive(ctx context.Context) (int64, error) { + var count int64 + err := r.db.WithContext(ctx).Model(&model.Printer{}).Where("is_active = ? AND status != ?", true, model.PrinterStatusOffline).Count(&count).Error + return count, err +} + +type PrintJobRepository struct { + db *gorm.DB +} + +func NewPrintJobRepository(db *gorm.DB) *PrintJobRepository { + return &PrintJobRepository{db: db} +} + +func (r *PrintJobRepository) Create(ctx context.Context, job *model.PrintJob) error { + return r.db.WithContext(ctx).Create(job).Error +} + +func (r *PrintJobRepository) GetByID(ctx context.Context, id int32) (*model.PrintJob, error) { + var job model.PrintJob + err := r.db.WithContext(ctx).First(&job, id).Error + if err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + return nil, nil + } + return nil, err + } + return &job, nil +} + +func (r *PrintJobRepository) GetByJobNo(ctx context.Context, jobNo string) (*model.PrintJob, error) { + var job model.PrintJob + err := r.db.WithContext(ctx).Where("job_no = ?", jobNo).First(&job).Error + if err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + return nil, nil + } + return nil, err + } + return &job, nil +} + +func (r *PrintJobRepository) GetPendingJobs(ctx context.Context, printerID int32) ([]*model.PrintJob, error) { + var jobs []*model.PrintJob + err := r.db.WithContext(ctx). + Where("printer_id = ? AND status = ?", printerID, model.PrintJobStatusPending). + Preload("OrderItem"). + Preload("OrderItem.File"). + Find(&jobs).Error + return jobs, err +} + +func (r *PrintJobRepository) UpdateStatus(ctx context.Context, jobNo string, status string, progress int, errorMsg string) error { + updates := map[string]interface{}{ + "status": status, + "progress": progress, + "error_msg": errorMsg, + } + if status == model.PrintJobStatusPrinting { + now := time.Now() + updates["started_at"] = &now + } else if status == model.PrintJobStatusCompleted || status == model.PrintJobStatusFailed { + now := time.Now() + updates["completed_at"] = &now + } + return r.db.WithContext(ctx).Model(&model.PrintJob{}). + Where("job_no = ?", jobNo).Updates(updates).Error +} + +func (r *PrintJobRepository) GetQueueCount(ctx context.Context, printerID int32) (int64, error) { + var count int64 + err := r.db.WithContext(ctx).Model(&model.PrintJob{}). + Where("printer_id = ? AND status IN ?", printerID, []string{model.PrintJobStatusPending, model.PrintJobStatusPrinting}). + Count(&count).Error + return count, err +} diff --git a/cloudprint-backend/internal/repository/user_repository.go b/cloudprint-backend/internal/repository/user_repository.go new file mode 100644 index 0000000..08d4951 --- /dev/null +++ b/cloudprint-backend/internal/repository/user_repository.go @@ -0,0 +1,64 @@ +package repository + +import ( + "context" + "errors" + + "github.com/cloudprint/cloudprint-backend/internal/model" + "gorm.io/gorm" +) + +type UserRepository struct { + db *gorm.DB +} + +func NewUserRepository(db *gorm.DB) *UserRepository { + return &UserRepository{db: db} +} + +func (r *UserRepository) Create(ctx context.Context, user *model.User) error { + return r.db.WithContext(ctx).Create(user).Error +} + +func (r *UserRepository) GetByID(ctx context.Context, id int32) (*model.User, error) { + var user model.User + err := r.db.WithContext(ctx).First(&user, id).Error + if err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + return nil, nil + } + return nil, err + } + return &user, nil +} + +func (r *UserRepository) GetByOpenid(ctx context.Context, openid string) (*model.User, error) { + var user model.User + err := r.db.WithContext(ctx).Where("openid = ?", openid).First(&user).Error + if err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + return nil, nil + } + return nil, err + } + return &user, nil +} + +func (r *UserRepository) Update(ctx context.Context, user *model.User) error { + return r.db.WithContext(ctx).Save(user).Error +} + +func (r *UserRepository) UpdateBalance(ctx context.Context, userID int32, balance float64) error { + return r.db.WithContext(ctx).Model(&model.User{}).Where("id = ?", userID).Update("balance", balance).Error +} + +func (r *UserRepository) DeductBalance(ctx context.Context, userID int32, amount float64) error { + return r.db.WithContext(ctx).Model(&model.User{}). + Where("id = ? AND balance >= ?", userID, amount). + Update("balance", gorm.Expr("balance - ?", amount)).Error +} + +func (r *UserRepository) AddBalance(ctx context.Context, userID int32, amount float64) error { + return r.db.WithContext(ctx).Model(&model.User{}).Where("id = ?", userID). + Update("balance", gorm.Expr("balance + ?", amount)).Error +} diff --git a/cloudprint-backend/internal/service/auth_service.go b/cloudprint-backend/internal/service/auth_service.go new file mode 100644 index 0000000..9e4fba6 --- /dev/null +++ b/cloudprint-backend/internal/service/auth_service.go @@ -0,0 +1,189 @@ +package service + +import ( + "context" + "encoding/json" + "errors" + "fmt" + "net/http" + "time" + + "github.com/cloudprint/cloudprint-backend/config" + "github.com/cloudprint/cloudprint-backend/internal/model" + "github.com/cloudprint/cloudprint-backend/internal/repository" + "github.com/cloudprint/cloudprint-backend/pkg/jwt" + "golang.org/x/crypto/bcrypt" +) + +type AuthService struct { + userRepo *repository.UserRepository + adminRepo *repository.AdminRepository + jwtManager *jwt.JWTManager + redis *RedisClient + wxConfig *config.WeChatConfig +} + +type RedisClient struct { + // In production, use actual Redis client +} + +func NewAuthService( + userRepo *repository.UserRepository, + adminRepo *repository.AdminRepository, + jwtManager *jwt.JWTManager, + redis *RedisClient, + wxConfig *config.WeChatConfig, +) *AuthService { + return &AuthService{ + userRepo: userRepo, + adminRepo: adminRepo, + jwtManager: jwtManager, + redis: redis, + wxConfig: wxConfig, + } +} + +// WeChat code exchange response +type WeChatCodeResponse struct { + OpenID string `json:"openid"` + SessionKey string `json:"session_key"` + UnionID string `json:"unionid,omitempty"` + ErrCode int `json:"errcode,omitempty"` + ErrMsg string `json:"errmsg,omitempty"` +} + +func (s *AuthService) Login(ctx context.Context, code string) (*LoginResult, error) { + // Exchange code for openid from WeChat + openid, err := s.getWeChatOpenID(code) + if err != nil { + return nil, fmt.Errorf("failed to get wechat openid: %w", err) + } + + // Find or create user + user, err := s.userRepo.GetByOpenid(ctx, openid) + if err != nil { + return nil, fmt.Errorf("failed to get user: %w", err) + } + + isNewUser := false + if user == nil { + isNewUser = true + user = &model.User{ + Openid: openid, + } + if err := s.userRepo.Create(ctx, user); err != nil { + return nil, fmt.Errorf("failed to create user: %w", err) + } + } + + // Generate tokens + accessToken, err := s.jwtManager.GenerateAccessToken(user.ID, "user", "") + if err != nil { + return nil, fmt.Errorf("failed to generate access token: %w", err) + } + + refreshToken, err := s.jwtManager.GenerateRefreshToken(user.ID, "user") + if err != nil { + return nil, fmt.Errorf("failed to generate refresh token: %w", err) + } + + return &LoginResult{ + AccessToken: accessToken, + RefreshToken: refreshToken, + User: user, + IsNewUser: isNewUser, + }, nil +} + +func (s *AuthService) getWeChatOpenID(code string) (string, error) { + url := fmt.Sprintf("https://api.weixin.qq.com/sns/jscode2session?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code", + s.wxConfig.AppID, s.wxConfig.AppSecret, code) + + resp, err := http.Get(url) + if err != nil { + return "", err + } + defer resp.Body.Close() + + var result WeChatCodeResponse + if err := json.NewDecoder(resp.Body).Decode(&result); err != nil { + return "", err + } + + if result.ErrCode != 0 { + return "", fmt.Errorf("wechat error: %s", result.ErrMsg) + } + + return result.OpenID, nil +} + +func (s *AuthService) RefreshToken(ctx context.Context, refreshToken string) (string, error) { + return s.jwtManager.RefreshAccessToken(refreshToken) +} + +func (s *AuthService) GetUserInfo(ctx context.Context, userID int32) (*model.User, error) { + return s.userRepo.GetByID(ctx, userID) +} + +func (s *AuthService) UpdateUser(ctx context.Context, userID int32, nickname, avatar string) (*model.User, error) { + user, err := s.userRepo.GetByID(ctx, userID) + if err != nil || user == nil { + return nil, errors.New("user not found") + } + + user.Nickname = nickname + if avatar != "" { + user.Avatar = avatar + } + + if err := s.userRepo.Update(ctx, user); err != nil { + return nil, err + } + + return user, nil +} + +type LoginResult struct { + AccessToken string + RefreshToken string + User *model.User + IsNewUser bool +} + +// Admin login +func (s *AuthService) AdminLogin(ctx context.Context, username, password string) (*AdminLoginResult, error) { + admin, err := s.adminRepo.GetByUsername(ctx, username) + if err != nil { + return nil, fmt.Errorf("failed to get admin: %w", err) + } + if admin == nil { + return nil, errors.New("invalid credentials") + } + + // Verify password + if err := bcrypt.CompareHashAndPassword([]byte(admin.PasswordHash), []byte(password)); err != nil { + return nil, errors.New("invalid credentials") + } + + // Generate token + accessToken, err := s.jwtManager.GenerateAccessToken(admin.ID, "admin", admin.Username) + if err != nil { + return nil, fmt.Errorf("failed to generate token: %w", err) + } + + return &AdminLoginResult{ + AccessToken: accessToken, + Admin: admin, + }, nil +} + +type AdminLoginResult struct { + AccessToken string + Admin *model.Admin +} + +// HashPassword creates a bcrypt hash of the password +func HashPassword(password string) (string, error) { + bytes, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost) + return string(bytes), err +} diff --git a/cloudprint-backend/internal/service/file_service.go b/cloudprint-backend/internal/service/file_service.go new file mode 100644 index 0000000..9f3f955 --- /dev/null +++ b/cloudprint-backend/internal/service/file_service.go @@ -0,0 +1,105 @@ +package service + +import ( + "context" + "fmt" + "io" + "os" + "path/filepath" + "strings" + + "github.com/cloudprint/cloudprint-backend/internal/model" + "github.com/cloudprint/cloudprint-backend/internal/repository" + "github.com/cloudprint/cloudprint-backend/pkg/upload" +) + +type FileService struct { + fileRepo *repository.FileRepository + uploader *upload.FileUploader + uploadDir string +} + +func NewFileService(fileRepo *repository.FileRepository, uploader *upload.FileUploader, uploadDir string) *FileService { + return &FileService{ + fileRepo: fileRepo, + uploader: uploader, + uploadDir: uploadDir, + } +} + +func (s *FileService) Upload(ctx context.Context, fileName string, fileType string, uploaderType string, uploaderID int32, data []byte) (*model.File, error) { + if !s.uploader.ValidateFileType(fileName) { + return nil, fmt.Errorf("file type not allowed") + } + + // Save file + filePath := s.uploader.GenerateFilePath(fileName) + fullPath := s.uploader.GetFilePath(filePath) + + if err := os.WriteFile(fullPath, data, 0644); err != nil { + return nil, fmt.Errorf("failed to write file: %w", err) + } + + // Create file record + file := &model.File{ + FileName: fileName, + FilePath: filePath, + FileType: strings.ToLower(fileType), + FileSize: int64(len(data)), + UploaderType: uploaderType, + UploaderID: uploaderID, + } + + if err := s.fileRepo.Create(ctx, file); err != nil { + // Clean up file on error + os.Remove(fullPath) + return nil, fmt.Errorf("failed to create file record: %w", err) + } + + return file, nil +} + +func (s *FileService) GetFile(ctx context.Context, fileID int32) (*model.File, error) { + return s.fileRepo.GetByID(ctx, fileID) +} + +func (s *FileService) GetFileReader(ctx context.Context, file *model.File) (io.ReadCloser, error) { + fullPath := filepath.Join(s.uploadDir, file.FilePath) + return os.Open(fullPath) +} + +func (s *FileService) DeleteFile(ctx context.Context, fileID int32, uploaderType string, uploaderID int32) error { + file, err := s.fileRepo.GetByID(ctx, fileID) + if err != nil || file == nil { + return fmt.Errorf("file not found") + } + + // Verify ownership + if file.UploaderType != uploaderType || file.UploaderID != uploaderID { + return fmt.Errorf("unauthorized") + } + + // Delete physical file + fullPath := s.uploader.GetFilePath(file.FilePath) + os.Remove(fullPath) + + // Delete record + return s.fileRepo.Delete(ctx, fileID) +} + +func (s *FileService) GetFileList(ctx context.Context, uploaderType string, uploaderID int32, page, pageSize int) ([]*model.File, int64, error) { + return s.fileRepo.GetListByUploader(ctx, uploaderType, uploaderID, page, pageSize) +} + +func (s *FileService) AddWatermark(ctx context.Context, fileID int32, text string, opacity float32, position int, fontSize int) (*model.File, error) { + file, err := s.fileRepo.GetByID(ctx, fileID) + if err != nil || file == nil { + return nil, fmt.Errorf("file not found") + } + + // In production, use a PDF library to add watermark + // For now, just return the original file + // TODO: Implement actual watermark using pdf-lib or similar + + return file, nil +} diff --git a/cloudprint-backend/internal/service/order_service.go b/cloudprint-backend/internal/service/order_service.go new file mode 100644 index 0000000..4566008 --- /dev/null +++ b/cloudprint-backend/internal/service/order_service.go @@ -0,0 +1,218 @@ +package service + +import ( + "context" + "errors" + "fmt" + "time" + + "github.com/cloudprint/cloudprint-backend/internal/model" + "github.com/cloudprint/cloudprint-backend/internal/repository" + "github.com/google/uuid" +) + +type OrderService struct { + orderRepo *repository.OrderRepository + orderItemRepo *repository.OrderItemRepository + fileRepo *repository.FileRepository + priceRepo *repository.PriceRepository + userRepo *repository.UserRepository + printerRepo *repository.PrinterRepository + printJobRepo *repository.PrintJobRepository +} + +func NewOrderService( + orderRepo *repository.OrderRepository, + orderItemRepo *repository.OrderItemRepository, + fileRepo *repository.FileRepository, + priceRepo *repository.PriceRepository, + userRepo *repository.UserRepository, + printerRepo *repository.PrinterRepository, + printJobRepo *repository.PrintJobRepository, +) *OrderService { + return &OrderService{ + orderRepo: orderRepo, + orderItemRepo: orderItemRepo, + fileRepo: fileRepo, + priceRepo: priceRepo, + userRepo: userRepo, + printerRepo: printerRepo, + printJobRepo: printJobRepo, + } +} + +type CreateOrderItem struct { + FileID int32 + PrinterID int32 + Copies int + Color bool + Duplex bool + PageRange string +} + +func (s *OrderService) CreateOrder(ctx context.Context, userID int32, items []*CreateOrderItem, remark string) (*model.Order, error) { + if len(items) == 0 { + return nil, errors.New("order must have at least one item") + } + + // Generate order number + orderNo := generateOrderNo() + + // Calculate total amount + var totalAmount float64 + orderItems := make([]*model.OrderItem, 0, len(items)) + + for _, item := range items { + // Verify file exists + file, err := s.fileRepo.GetByID(ctx, item.FileID) + if err != nil || file == nil { + return nil, fmt.Errorf("file not found: %d", item.FileID) + } + + // Calculate price + price, err := s.calculatePrice(ctx, item) + if err != nil { + return nil, err + } + + orderItem := &model.OrderItem{ + FileID: item.FileID, + PrinterID: intPtr(item.PrinterID), + Copies: item.Copies, + Color: item.Color, + Duplex: item.Duplex, + PageRange: item.PageRange, + Price: price, + } + orderItems = append(orderItems, orderItem) + totalAmount += price + } + + // Create order + order := &model.Order{ + OrderNo: orderNo, + UserID: userID, + Status: model.OrderStatusPending, + TotalAmount: totalAmount, + Remark: remark, + Items: orderItems, + } + + // Save order with items + if err := s.orderRepo.CreateWithItems(ctx, order, orderItems); err != nil { + return nil, fmt.Errorf("failed to create order: %w", err) + } + + return order, nil +} + +func (s *OrderService) calculatePrice(ctx context.Context, item *CreateOrderItem) (float64, error) { + // Get price list + prices, err := s.priceRepo.GetAllActive(ctx) + if err != nil { + return 0, err + } + + // Default price calculation (A4 B&W per page) + defaultPrice := 0.10 + colorMultiplier := 3.0 + duplexDiscount := 0.8 + + // Calculate based on file type and settings + // For simplicity, using default values + // In production, look up from price list based on file type + + pageCount := 1 // Default, should get actual page count from file + if item.Copies <= 0 { + item.Copies = 1 + } + + price := float64(pageCount) * defaultPrice * float64(item.Copies) + + if item.Color { + price *= colorMultiplier + } + + if item.Duplex { + price *= duplexDiscount + } + + return price, nil +} + +func generateOrderNo() string { + now := time.Now() + return fmt.Sprintf("CP%d%s", now.UnixNano()/1000000, uuid.New().String()[:8]) +} + +func intPtr(i int32) *int32 { + return &i +} + +func (s *OrderService) GetOrder(ctx context.Context, orderNo string) (*model.Order, error) { + return s.orderRepo.GetByOrderNo(ctx, orderNo) +} + +func (s *OrderService) GetOrderList(ctx context.Context, userID int32, status int8, page, pageSize int) ([]*model.Order, int64, error) { + return s.orderRepo.GetListByUserID(ctx, userID, status, page, pageSize) +} + +func (s *OrderService) UpdateOrderStatus(ctx context.Context, orderNo string, status int8) error { + return s.orderRepo.UpdateStatus(ctx, orderNo, status) +} + +func (s *OrderService) CancelOrder(ctx context.Context, orderNo string) error { + order, err := s.orderRepo.GetByOrderNo(ctx, orderNo) + if err != nil || order == nil { + return errors.New("order not found") + } + + if order.Status != model.OrderStatusPending { + return errors.New("only pending orders can be cancelled") + } + + return s.orderRepo.UpdateStatus(ctx, orderNo, model.OrderStatusCancelled) +} + +// PayOrder handles payment for an order +func (s *OrderService) PayOrder(ctx context.Context, orderNo string, payType string) error { + order, err := s.orderRepo.GetByOrderNo(ctx, orderNo) + if err != nil || order == nil { + return errors.New("order not found") + } + + if order.Status != model.OrderStatusPending { + return errors.New("order is not pending") + } + + // Update order status to paid + if err := s.orderRepo.UpdateStatus(ctx, orderNo, model.OrderStatusPaid); err != nil { + return err + } + + // Create print jobs for each order item + for _, item := range order.Items { + if item.PrinterID != nil { + jobNo := generateJobNo() + job := &model.PrintJob{ + JobNo: jobNo, + PrinterID: *item.PrinterID, + OrderItemID: item.ID, + Status: model.PrintJobStatusPending, + Progress: 0, + } + if err := s.printJobRepo.Create(ctx, job); err != nil { + // Log error but don't fail + continue + } + } + } + + // Update order status to printing + return s.orderRepo.UpdateStatus(ctx, orderNo, model.OrderStatusPrinting) +} + +func generateJobNo() string { + now := time.Now() + return fmt.Sprintf("PJ%d%s", now.UnixNano()/1000000, uuid.New().String()[:8]) +} diff --git a/cloudprint-backend/internal/service/print_service.go b/cloudprint-backend/internal/service/print_service.go new file mode 100644 index 0000000..29d7e14 --- /dev/null +++ b/cloudprint-backend/internal/service/print_service.go @@ -0,0 +1,194 @@ +package service + +import ( + "context" + "sync" + "time" + + "github.com/cloudprint/cloudprint-backend/internal/model" + "github.com/cloudprint/cloudprint-backend/internal/repository" + "github.com/google/uuid" +) + +type PrintService struct { + printerRepo *repository.PrinterRepository + printJobRepo *repository.PrintJobRepository + orderRepo *repository.OrderRepository + subscribers map[int32]chan *model.PrintJob + mu sync.RWMutex +} + +func NewPrintService( + printerRepo *repository.PrinterRepository, + printJobRepo *repository.PrintJobRepository, + orderRepo *repository.OrderRepository, +) *PrintService { + s := &PrintService{ + printerRepo: printerRepo, + printJobRepo: printJobRepo, + orderRepo: orderRepo, + subscribers: make(map[int32]chan *model.PrintJob), + } + // Start heartbeat checker + go s.checkPrinterHeartbeat() + return s +} + +func (s *PrintService) GetPrinters(ctx context.Context) ([]*model.Printer, error) { + return s.printerRepo.GetAllActive(ctx) +} + +func (s *PrintService) GetPrinterStatus(ctx context.Context, printerID int32) (*model.Printer, int64, error) { + printer, err := s.printerRepo.GetByID(ctx, printerID) + if err != nil || printer == nil { + return nil, 0, err + } + + queueCount, err := s.printJobRepo.GetQueueCount(ctx, printerID) + if err != nil { + return nil, 0, err + } + + return printer, queueCount, nil +} + +func (s *PrintService) RegisterPrinter(ctx context.Context, name, displayName, apiKey string) (*model.Printer, string, error) { + // Check if printer already exists + existing, err := s.printerRepo.GetByName(ctx, name) + if err != nil { + return nil, "", err + } + if existing != nil { + return nil, "", nil + } + + // Generate token for this printer + token := uuid.New().String() + + printer := &model.Printer{ + Name: name, + DisplayName: displayName, + APIKey: apiKey, + IsActive: true, + Status: model.PrinterStatusIdle, + } + + if err := s.printerRepo.Create(ctx, printer); err != nil { + return nil, "", err + } + + return printer, token, nil +} + +func (s *PrintService) PrinterHeartbeat(ctx context.Context, printerID int32, status int8, token string) error { + // Verify token (in production, validate against stored token) + // For now, just update heartbeat and status + if err := s.printerRepo.UpdateHeartbeat(ctx, printerID); err != nil { + return err + } + return s.printerRepo.UpdateStatus(ctx, printerID, status) +} + +func (s *PrintService) SubmitPrintJob(ctx context.Context, orderItemID int32, printerID int32, filePath string, copies int, color, duplex bool, pageRange string) (*model.PrintJob, error) { + jobNo := generateJobNo() + + job := &model.PrintJob{ + JobNo: jobNo, + PrinterID: printerID, + OrderItemID: orderItemID, + Status: model.PrintJobStatusPending, + Progress: 0, + } + + if err := s.printJobRepo.Create(ctx, job); err != nil { + return nil, err + } + + // Notify subscriber + s.mu.RLock() + ch, ok := s.subscribers[printerID] + s.mu.RUnlock() + + if ok { + select { + case ch <- job: + default: + } + } + + return job, nil +} + +func (s *PrintService) CancelPrintJob(ctx context.Context, jobNo string) error { + return s.printJobRepo.UpdateStatus(ctx, jobNo, model.PrintJobStatusCancelled, 0, "cancelled by user") +} + +func (s *PrintService) SubscribeJobs(ctx context.Context, printerID int32, token string) (<-chan *model.PrintJob, error) { + ch := make(chan *model.PrintJob, 100) + + s.mu.Lock() + s.subscribers[printerID] = ch + s.mu.Unlock() + + // Send pending jobs immediately + go func() { + jobs, err := s.printJobRepo.GetPendingJobs(ctx, printerID) + if err != nil { + return + } + for _, job := range jobs { + select { + case ch <- job: + default: + } + } + }() + + return ch, nil +} + +func (s *PrintService) UnsubscribeJobs(printerID int32) { + s.mu.Lock() + defer s.mu.Unlock() + + if ch, ok := s.subscribers[printerID]; ok { + close(ch) + delete(s.subscribers, printerID) + } +} + +func (s *PrintService) ReportJobStatus(ctx context.Context, jobNo string, status string, progress int, errorMsg string) error { + // Update job status + if err := s.printJobRepo.UpdateStatus(ctx, jobNo, status, progress, errorMsg); err != nil { + return err + } + + // If completed, check if all jobs for the order are done + if status == model.PrintJobStatusCompleted { + job, _ := s.printJobRepo.GetByJobNo(ctx, jobNo) + if job != nil { + // Check if all jobs for the order are completed + s.checkOrderCompletion(ctx, job.OrderItemID) + } + } + + return nil +} + +func (s *PrintService) checkOrderCompletion(ctx context.Context, orderItemID int32) { + // In production, check if all print jobs for the order are completed + // and update order status accordingly +} + +func (s *PrintService) checkPrinterHeartbeat() { + ticker := time.NewTicker(30 * time.Second) + for range ticker.C { + // In production, check LastHeartbeat and mark printers as offline if no heartbeat + // This is a placeholder for the heartbeat checker + } +} + +// ValidatePrinterToken validates the API key and returns the printer +func (s *PrintService) ValidatePrinterToken(ctx context.Context, apiKey string) (*model.Printer, error) { + return s.printerRepo.GetByAPIKey(ctx, apiKey) +} diff --git a/cloudprint-backend/pkg/jwt/jwt.go b/cloudprint-backend/pkg/jwt/jwt.go new file mode 100644 index 0000000..f89db72 --- /dev/null +++ b/cloudprint-backend/pkg/jwt/jwt.go @@ -0,0 +1,105 @@ +package jwt + +import ( + "errors" + "time" + + "github.com/golang-jwt/jwt/v5" +) + +var ( + ErrInvalidToken = errors.New("invalid token") + ErrExpiredToken = errors.New("token has expired") +) + +type Claims struct { + UserID int32 `json:"user_id"` + UserType string `json:"user_type"` // "user" or "admin" + Username string `json:"username,omitempty"` + jwt.RegisteredClaims +} + +type JWTManager struct { + secretKey []byte + accessTokenTTL time.Duration + refreshTokenTTL time.Duration +} + +func NewJWTManager(secret string, accessTokenTTL, refreshTokenTTL time.Duration) *JWTManager { + return &JWTManager{ + secretKey: []byte(secret), + accessTokenTTL: accessTokenTTL, + refreshTokenTTL: refreshTokenTTL, + } +} + +func (m *JWTManager) GenerateAccessToken(userID int32, userType string, username string) (string, error) { + now := time.Now() + claims := &Claims{ + UserID: userID, + UserType: userType, + Username: username, + RegisteredClaims: jwt.RegisteredClaims{ + ExpiresAt: jwt.NewNumericDate(now.Add(m.accessTokenTTL)), + IssuedAt: jwt.NewNumericDate(now), + NotBefore: jwt.NewNumericDate(now), + }, + } + + token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) + return token.SignedString(m.secretKey) +} + +func (m *JWTManager) GenerateRefreshToken(userID int32, userType string) (string, error) { + now := time.Now() + claims := &Claims{ + UserID: userID, + UserType: userType, + RegisteredClaims: jwt.RegisteredClaims{ + ExpiresAt: jwt.NewNumericDate(now.Add(m.refreshTokenTTL)), + IssuedAt: jwt.NewNumericDate(now), + NotBefore: jwt.NewNumericDate(now), + Subject: "refresh", + }, + } + + token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) + return token.SignedString(m.secretKey) +} + +func (m *JWTManager) ValidateToken(tokenString string) (*Claims, error) { + token, err := jwt.ParseWithClaims(tokenString, &Claims{}, func(token *jwt.Token) (interface{}, error) { + if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok { + return nil, ErrInvalidToken + } + return m.secretKey, nil + }) + + if err != nil { + if errors.Is(err, jwt.ErrTokenExpired) { + return nil, ErrExpiredToken + } + return nil, ErrInvalidToken + } + + claims, ok := token.Claims.(*Claims) + if !ok || !token.Valid { + return nil, ErrInvalidToken + } + + return claims, nil +} + +func (m *JWTManager) RefreshAccessToken(refreshToken string) (string, error) { + claims, err := m.ValidateToken(refreshToken) + if err != nil { + return "", err + } + + // Only refresh tokens with subject "refresh" can be used + if claims.Subject != "refresh" { + return "", ErrInvalidToken + } + + return m.GenerateAccessToken(claims.UserID, claims.UserType, claims.Username) +} diff --git a/cloudprint-backend/pkg/pay/wechat.go b/cloudprint-backend/pkg/pay/wechat.go new file mode 100644 index 0000000..c98c824 --- /dev/null +++ b/cloudprint-backend/pkg/pay/wechat.go @@ -0,0 +1,200 @@ +package pay + +import ( + "context" + "crypto/md5" + "encoding/hex" + "encoding/xml" + "fmt" + "math/rand" + "sort" + "strings" + "time" + + "github.com/cloudprint/cloudprint-backend/config" + "github.com/iGoogle-ink/gopay" +) + +// RandomString generates a random string with given length +func RandomString(length int) string { + const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" + b := make([]byte, length) + for i := range b { + b[i] = charset[rand.Intn(len(charset))] + } + return string(b) +} + +type WeChatPay struct { + client *gopay.WxPayClient + config *config.WeChatConfig +} + +type UnifiedOrderResponse struct { + ReturnCode string `xml:"return_code"` + ReturnMsg string `xml:"return_msg"` + ResultCode string `xml:"result_code"` + PrepayID string `xml:"prepay_id,omitempty"` + CodeURL string `xml:"code_url,omitempty"` + MWebURL string `xml:"mweb_url,omitempty"` + ErrCode string `xml:"err_code,omitempty"` + ErrMsg string `xml:"err_msg,omitempty"` + TransactionID string `xml:"transaction_id,omitempty"` + TradeState string `xml:"trade_state,omitempty"` + TotalFee int `xml:"total_fee,omitempty"` +} + +type PayCallback struct { + ReturnCode string `xml:"return_code"` + ReturnMsg string `xml:"return_msg"` + AppID string `xml:"appid"` + MchID string `xml:"mch_id"` + NonceStr string `xml:"nonce_str"` + Sign string `xml:"sign"` + ResultCode string `xml:"result_code"` + TransactionID string `xml:"transaction_id"` + OutTradeNo string `xml:"out_trade_no"` + TotalFee int `xml:"total_fee"` + TimeEnd string `xml:"time_end"` +} + +func NewWeChatPay(cfg *config.WeChatConfig) *WeChatPay { + client := gopay.NewWxPayClient(cfg.AppID, cfg.MchID, cfg.ApiKey, cfg.NotifyURL) + if cfg.CertPath != "" { + client.SetCertFilePath(cfg.CertPath) + } + return &WeChatPay{ + client: client, + config: cfg, + } +} + +func (p *WeChatPay) createSign(params map[string]string) string { + keys := make([]string, 0, len(params)) + for k := range params { + keys = append(keys, k) + } + sort.Strings(keys) + + var signParts []string + for _, k := range keys { + if params[k] != "" && k != "sign" { + signParts = append(signParts, fmt.Sprintf("%s=%s", k, params[k])) + } + } + signStr := strings.Join(signParts, "&") + signStr += "&key=" + p.config.ApiKey + + md5Hash := md5.New() + md5Hash.Write([]byte(signStr)) + return strings.ToUpper(hex.EncodeToString(md5Hash.Sum(nil))) +} + +func (p *WeChatPay) UnifiedOrder(ctx context.Context, orderNo string, amount float64, description, openID, clientIP string) (*UnifiedOrderResponse, error) { + nonceStr := RandomString(32) + totalFee := int(amount * 100) // Convert to fen + + // Build request body + body := gopay.UnifiedOrder{ + AppID: p.config.AppID, + MchID: p.config.MchID, + NonceStr: nonceStr, + Body: description, + OutTradeNo: orderNo, + TotalFee: totalFee, + SpbillCreateIP: clientIP, + NotifyURL: p.config.NotifyURL, + TradeType: "JSAPI", + OpenID: openID, + } + + // Use go-pay client to call unified order + resp, err := p.client.UnifiedOrder(ctx, body) + if err != nil { + return nil, fmt.Errorf("unified order failed: %w", err) + } + + result := &UnifiedOrderResponse{ + ReturnCode: resp.GetString("return_code"), + ReturnMsg: resp.GetString("return_msg"), + ResultCode: resp.GetString("result_code"), + PrepayID: resp.GetString("prepay_id"), + CodeURL: resp.GetString("code_url"), + MWebURL: resp.GetString("mweb_url"), + ErrCode: resp.GetString("err_code"), + ErrMsg: resp.GetString("err_msg"), + } + + return result, nil +} + +func (p *WeChatPay) QueryOrder(ctx context.Context, orderNo string) (string, int, error) { + nonceStr := RandomString(32) + + body := gopay.QueryOrder{ + AppID: p.config.AppID, + MchID: p.config.MchID, + NonceStr: nonceStr, + OutTradeNo: orderNo, + } + + resp, err := p.client.QueryOrder(ctx, body) + if err != nil { + return "", 0, err + } + + tradeState := resp.GetString("trade_state") + totalFee := resp.GetInt("total_fee") + + return tradeState, totalFee, nil +} + +func (p *WeChatPay) ParseCallback(body []byte) (*PayCallback, error) { + var callback PayCallback + if err := xml.Unmarshal(body, &callback); err != nil { + return nil, fmt.Errorf("failed to parse callback: %w", err) + } + return &callback, nil +} + +func (p *WeChatPay) ValidateCallback(callback *PayCallback) bool { + params := map[string]string{ + "return_code": callback.ReturnCode, + "return_msg": callback.ReturnMsg, + "appid": callback.AppID, + "mch_id": callback.MchID, + "nonce_str": callback.NonceStr, + "result_code": callback.ResultCode, + "transaction_id": callback.TransactionID, + "out_trade_no": callback.OutTradeNo, + "total_fee": fmt.Sprintf("%d", callback.TotalFee), + "time_end": callback.TimeEnd, + } + + expectedSign := p.createSign(params) + return callback.Sign == expectedSign +} + +func (p *WeChatPay) GenerateJSAPIPayParams(prepayID string) (map[string]string, error) { + nonceStr := RandomString(32) + timestamp := fmt.Sprintf("%d", time.Now().Unix()) + + params := map[string]string{ + "appId": p.config.AppID, + "timeStamp": timestamp, + "nonceStr": nonceStr, + "package": "prepay_id=" + prepayID, + "signType": "MD5", + } + + paySign := p.createSign(map[string]string{ + "appId": p.config.AppID, + "timeStamp": timestamp, + "nonceStr": nonceStr, + "package": "prepay_id=" + prepayID, + "signType": "MD5", + }) + + params["paySign"] = paySign + return params, nil +} diff --git a/cloudprint-backend/pkg/upload/upload.go b/cloudprint-backend/pkg/upload/upload.go new file mode 100644 index 0000000..9f1118e --- /dev/null +++ b/cloudprint-backend/pkg/upload/upload.go @@ -0,0 +1,196 @@ +package upload + +import ( + "context" + "fmt" + "io" + "mime/multipart" + "os" + "path/filepath" + "strings" + "sync" + + "github.com/google/uuid" +) + +var ( + // AllowedFileTypes 文件类型白名单 + AllowedFileTypes = map[string]bool{ + "pdf": true, + "doc": true, + "docx": true, + "xls": true, + "xlsx": true, + "ppt": true, + "pptx": true, + "txt": true, + "jpg": true, + "jpeg": true, + "png": true, + "bmp": true, + "gif": true, + "zip": true, + "rar": true, + } +) + +type FileUploader struct { + basePath string + chunkPath string + maxSize int64 + mu sync.RWMutex + chunks map[string]*ChunkInfo +} + +type ChunkInfo struct { + FileName string + TotalParts int + Parts map[int][]byte + CreatedAt int64 +} + +func NewFileUploader(basePath string, chunkPath string, maxSize int64) *FileUploader { + uploader := &FileUploader{ + basePath: basePath, + chunkPath: chunkPath, + maxSize: maxSize, + chunks: make(map[string]*ChunkInfo), + } + // Ensure directories exist + os.MkdirAll(basePath, 0755) + os.MkdirAll(chunkPath, 0755) + return uploader +} + +func (u *FileUploader) getExt(filename string) string { + ext := strings.ToLower(filepath.Ext(filename)) + return strings.TrimPrefix(ext, ".") +} + +func (u *FileUploader) ValidateFileType(filename string) bool { + ext := u.getExt(filename) + return AllowedFileTypes[ext] +} + +func (u *FileUploader) GenerateFilePath(filename string) string { + ext := u.getExt(filename) + newName := fmt.Sprintf("%s.%s", uuid.New().String(), ext) + // 按日期分目录 + // dateDir := time.Now().Format("2006/01/02") + // return filepath.Join(dateDir, newName) + return newName +} + +func (u *FileUploader) Upload(ctx context.Context, file *multipart.FileHeader) (string, error) { + if u.maxSize > 0 && file.Size > u.maxSize { + return "", fmt.Errorf("file size exceeds limit: %d > %d", file.Size, u.maxSize) + } + + if !u.ValidateFileType(file.Filename) { + return "", fmt.Errorf("file type not allowed: %s", file.Filename) + } + + src, err := file.Open() + if err != nil { + return "", fmt.Errorf("failed to open file: %w", err) + } + defer src.Close() + + filePath := u.GenerateFilePath(file.Filename) + fullPath := filepath.Join(u.basePath, filePath) + + // Ensure parent directory exists + if err := os.MkdirAll(filepath.Dir(fullPath), 0755); err != nil { + return "", fmt.Errorf("failed to create directory: %w", err) + } + + dst, err := os.Create(fullPath) + if err != nil { + return "", fmt.Errorf("failed to create file: %w", err) + } + defer dst.Close() + + if _, err := io.Copy(dst, src); err != nil { + return "", fmt.Errorf("failed to write file: %w", err) + } + + return filePath, nil +} + +// Chunk upload support +func (u *FileUploader) InitChunkUpload(chunkID, fileName string, totalParts int) error { + u.mu.Lock() + defer u.mu.Unlock() + + u.chunks[chunkID] = &ChunkInfo{ + FileName: fileName, + TotalParts: totalParts, + Parts: make(map[int][]byte), + } + return nil +} + +func (u *FileUploader) SaveChunk(chunkID string, partIndex int, data []byte) error { + u.mu.Lock() + defer u.mu.Unlock() + + chunk, ok := u.chunks[chunkID] + if !ok { + return fmt.Errorf("chunk upload not initialized: %s", chunkID) + } + + if partIndex < 0 || partIndex >= chunk.TotalParts { + return fmt.Errorf("invalid part index: %d", partIndex) + } + + chunk.Parts[partIndex] = data + return nil +} + +func (u *FileUploader) CompleteChunkUpload(ctx context.Context, chunkID string) (string, error) { + u.mu.Lock() + chunk, ok := u.chunks[chunkID] + if !ok { + u.mu.Unlock() + return "", fmt.Errorf("chunk upload not found: %s", chunkID) + } + + if len(chunk.Parts) != chunk.TotalParts { + u.mu.Unlock() + return "", fmt.Errorf("incomplete chunks: %d/%d", len(chunk.Parts), chunk.TotalParts) + } + + // Delete chunk info early to allow other operations + delete(u.chunks, chunkID) + u.mu.Unlock() + + filePath := u.GenerateFilePath(chunk.FileName) + fullPath := filepath.Join(u.basePath, filePath) + + if err := os.MkdirAll(filepath.Dir(fullPath), 0755); err != nil { + return "", fmt.Errorf("failed to create directory: %w", err) + } + + f, err := os.Create(fullPath) + if err != nil { + return "", fmt.Errorf("failed to create file: %w", err) + } + defer f.Close() + + for i := 0; i < chunk.TotalParts; i++ { + if _, err := f.Write(chunk.Parts[i]); err != nil { + return "", fmt.Errorf("failed to write chunk %d: %w", i, err) + } + } + + return filePath, nil +} + +func (u *FileUploader) DeleteFile(filePath string) error { + fullPath := filepath.Join(u.basePath, filePath) + return os.Remove(fullPath) +} + +func (u *FileUploader) GetFilePath(filePath string) string { + return filepath.Join(u.basePath, filePath) +} diff --git a/cloudprint-backend/proto/cloudprint.proto b/cloudprint-backend/proto/cloudprint.proto new file mode 100644 index 0000000..78d60a6 --- /dev/null +++ b/cloudprint-backend/proto/cloudprint.proto @@ -0,0 +1,502 @@ +syntax = "proto3"; + +package cloudprint; + +option go_package = "github.com/cloudprint/cloudprint-backend/proto/generated"; + +import "google/protobuf/empty.proto"; +import "google/protobuf/timestamp.proto"; + +// ============ 通用消息 ============ + +message Empty {} + +message StatusResponse { + int32 code = 1; + string message = 2; +} + +// ============ 用户相关 ============ + +message User { + int32 id = 1; + string openid = 2; + string nickname = 3; + string avatar = 4; + double balance = 5; + google.protobuf.Timestamp created_at = 6; +} + +message LoginRequest { + string code = 1; // 微信授权码 +} + +message LoginResponse { + string access_token = 1; + string refresh_token = 2; + User user = 3; +} + +message RefreshRequest { + string refresh_token = 1; +} + +message RefreshResponse { + string access_token = 1; +} + +message GetUserInfoRequest {} + +message UpdateUserRequest { + string nickname = 1; + string avatar = 2; +} + +// ============ 文件相关 ============ + +message FileInfo { + int32 id = 1; + string file_name = 2; + string file_path = 3; + string file_type = 4; + int64 file_size = 5; + string uploader_type = 6; + int32 uploader_id = 7; + google.protobuf.Timestamp created_at = 8; +} + +message UploadRequest { + string file_name = 1; + string file_type = 2; + int64 file_size = 3; + bytes data = 4; + bool is_last_chunk = 5; + string chunk_id = 6; + int32 chunk_index = 7; + int32 total_chunks = 8; +} + +message UploadResponse { + int32 file_id = 1; + string file_path = 2; + string file_url = 3; +} + +message GetFileRequest { + int32 file_id = 1; +} + +message FileData { + bytes data = 1; + bool is_last = 2; +} + +message DeleteFileRequest { + int32 file_id = 1; +} + +message WatermarkRequest { + int32 file_id = 1; + string text = 2; + float opacity = 3; + int32 position = 4; // 1: 左上 2: 右上 3: 左下 4: 右下 5: 居中 + int32 font_size = 5; +} + +message WatermarkResponse { + int32 file_id = 1; + string file_path = 2; +} + +message GetFileListRequest { + string uploader_type = 1; + int32 uploader_id = 2; + int32 page = 3; + int32 page_size = 4; +} + +message FileListResponse { + repeated FileInfo files = 1; + int32 total = 2; +} + +// ============ 订单相关 ============ + +message Order { + int32 id = 1; + string order_no = 2; + int32 user_id = 3; + int32 status = 4; + double total_amount = 5; + string remark = 6; + google.protobuf.Timestamp created_at = 7; + google.protobuf.Timestamp paid_at = 8; + repeated OrderItem items = 9; +} + +message OrderItem { + int32 id = 1; + int32 order_id = 2; + int32 file_id = 3; + FileInfo file = 4; + int32 printer_id = 5; + int32 copies = 6; + bool color = 7; + bool duplex = 8; + string page_range = 9; + double price = 10; +} + +message CreateOrderRequest { + repeated CreateOrderItem items = 1; + string remark = 2; +} + +message CreateOrderItem { + int32 file_id = 1; + int32 printer_id = 2; + int32 copies = 3; + bool color = 4; + bool duplex = 5; + string page_range = 6; +} + +message CreateOrderResponse { + string order_no = 1; + double total_amount = 2; +} + +message GetOrderRequest { + string order_no = 1; +} + +message GetOrderListRequest { + int32 user_id = 1; + int32 status = 2; + int32 page = 3; + int32 page_size = 4; +} + +message OrderListResponse { + repeated Order orders = 1; + int32 total = 2; +} + +message UpdateOrderStatusRequest { + string order_no = 1; + int32 status = 2; +} + +message CancelOrderRequest { + string order_no = 1; +} + +// ============ 打印机相关 ============ + +message Printer { + int32 id = 1; + string name = 2; + string display_name = 3; + bool is_active = 4; + int32 status = 5; // 0: 空闲 1: 打印中 2: 离线 + google.protobuf.Timestamp last_heartbeat = 6; +} + +message GetPrintersRequest {} + +message PrinterListResponse { + repeated Printer printers = 1; +} + +message GetPrinterStatusRequest { + int32 printer_id = 1; +} + +message PrinterStatusResponse { + Printer printer = 1; + int32 queue_count = 2; +} + +message RegisterPrinterRequest { + string name = 1; + string display_name = 2; + string api_key = 3; +} + +message RegisterPrinterResponse { + int32 printer_id = 1; + string token = 2; +} + +message PrinterHeartbeatRequest { + int32 printer_id = 1; + int32 status = 2; + string token = 3; +} + +// ============ 打印任务相关 ============ + +message PrintJob { + int32 id = 1; + string job_no = 2; + int32 printer_id = 3; + int32 order_item_id = 4; + string status = 5; // pending/printing/completed/failed/cancelled + int32 progress = 6; + string error_msg = 7; + google.protobuf.Timestamp started_at = 8; + google.protobuf.Timestamp completed_at = 9; + OrderItem order_item = 10; +} + +message SubmitPrintJobRequest { + int32 order_item_id = 1; + int32 printer_id = 2; + string file_path = 3; + int32 copies = 4; + bool color = 5; + bool duplex = 6; + string page_range = 7; +} + +message SubmitPrintJobResponse { + string job_no = 1; +} + +message CancelPrintJobRequest { + string job_no = 1; +} + +message SubscribeJobsRequest { + int32 printer_id = 1; + string token = 2; +} + +message ReportJobStatusRequest { + string job_no = 1; + string status = 2; + int32 progress = 3; + string error_msg = 4; +} + +// ============ 文库相关 ============ + +message LibraryCategory { + int32 id = 1; + string name = 2; + string icon = 3; + int32 sort_order = 4; +} + +message LibraryFile { + int32 id = 1; + int32 category_id = 2; + int32 file_id = 3; + string title = 4; + string description = 5; + int32 page_count = 6; + int32 download_count = 7; + FileInfo file = 8; + google.protobuf.Timestamp created_at = 9; +} + +message GetCategoriesRequest {} + +message CategoryListResponse { + repeated LibraryCategory categories = 1; +} + +message GetLibraryFilesRequest { + int32 category_id = 1; + int32 page = 2; + int32 page_size = 3; +} + +message LibraryFileListResponse { + repeated LibraryFile files = 1; + int32 total = 2; +} + +message UploadLibraryFileRequest { + int32 category_id = 1; + string title = 2; + string description = 3; + bytes data = 4; + string file_name = 5; + string file_type = 6; +} + +message UploadLibraryFileResponse { + int32 library_file_id = 1; +} + +message DeleteLibraryFileRequest { + int32 library_file_id = 1; +} + +// ============ 价目表相关 ============ + +message PriceItem { + int32 id = 1; + string name = 2; + string type = 3; + double price = 4; + string unit = 5; + bool color_enabled = 6; + bool is_active = 7; +} + +message GetPriceListRequest {} + +message PriceListResponse { + repeated PriceItem items = 1; +} + +message CreatePriceItemRequest { + string name = 1; + string type = 2; + double price = 3; + string unit = 4; + bool color_enabled = 5; +} + +message UpdatePriceItemRequest { + int32 id = 1; + string name = 2; + string type = 3; + double price = 4; + string unit = 5; + bool color_enabled = 6; + bool is_active = 7; +} + +// ============ 支付相关 ============ + +message WxPayRequest { + string order_no = 1; + double amount = 2; + string description = 3; + string openid = 4; + string client_ip = 5; +} + +message WxPayResponse { + string prepay_id = 1; + string code_url = 2; + string mweb_url = 3; +} + +message QueryPayStatusRequest { + string order_no = 1; +} + +message PayStatusResponse { + int32 status = 1; // 0: 待支付 1: 支付中 2: 成功 3: 失败 + string transaction_id = 2; +} + +message PayCallbackRequest { + string body = 1; +} + +message PayCallbackResponse { + string return_code = 1; + string return_msg = 2; +} + +message PayByBalanceRequest { + string order_no = 1; + int32 user_id = 2; +} + +// ============ 管理后台相关 ============ + +message Admin { + int32 id = 1; + string username = 2; + string nickname = 3; + int32 role = 4; + google.protobuf.Timestamp created_at = 5; +} + +message AdminLoginRequest { + string username = 1; + string password = 2; +} + +message AdminLoginResponse { + string access_token = 1; + Admin admin = 2; +} + +message GetStatisticsRequest {} + +message Statistics { + int32 total_users = 1; + int32 total_orders = 2; + int32 today_orders = 3; + double today_revenue = 4; + int32 pending_orders = 5; + int32 active_printers = 6; +} + +// ============ 服务定义 ============ + +service AuthService { + rpc Login(LoginRequest) returns (LoginResponse); + rpc RefreshToken(RefreshRequest) returns (RefreshResponse); + rpc GetUserInfo(GetUserInfoRequest) returns (User); + rpc UpdateUser(UpdateUserRequest) returns (User); +} + +service FileService { + rpc Upload(stream UploadRequest) returns (UploadResponse); + rpc GetFile(GetFileRequest) returns (stream FileData); + rpc DeleteFile(DeleteFileRequest) returns (Empty); + rpc AddWatermark(WatermarkRequest) returns (WatermarkResponse); + rpc GetFileList(GetFileListRequest) returns (FileListResponse); +} + +service OrderService { + rpc CreateOrder(CreateOrderRequest) returns (CreateOrderResponse); + rpc GetOrder(GetOrderRequest) returns (Order); + rpc GetOrderList(GetOrderListRequest) returns (OrderListResponse); + rpc UpdateOrderStatus(UpdateOrderStatusRequest) returns (Empty); + rpc CancelOrder(CancelOrderRequest) returns (Empty); +} + +service PrintService { + rpc GetPrinters(GetPrintersRequest) returns (PrinterListResponse); + rpc GetPrinterStatus(GetPrinterStatusRequest) returns (PrinterStatusResponse); + rpc RegisterPrinter(RegisterPrinterRequest) returns (RegisterPrinterResponse); + rpc PrinterHeartbeat(PrinterHeartbeatRequest) returns (Empty); + rpc SubmitPrintJob(SubmitPrintJobRequest) returns (SubmitPrintJobResponse); + rpc CancelPrintJob(CancelPrintJobRequest) returns (Empty); + rpc SubscribeJobs(SubscribeJobsRequest) returns (stream PrintJob); + rpc ReportJobStatus(ReportJobStatusRequest) returns (Empty); +} + +service LibraryService { + rpc GetCategories(GetCategoriesRequest) returns (CategoryListResponse); + rpc GetFiles(GetLibraryFilesRequest) returns (LibraryFileListResponse); + rpc UploadFile(stream UploadLibraryFileRequest) returns (UploadLibraryFileResponse); + rpc DeleteFile(DeleteLibraryFileRequest) returns (Empty); +} + +service PriceService { + rpc GetPriceList(GetPriceListRequest) returns (PriceListResponse); + rpc CreatePriceItem(CreatePriceItemRequest) returns (PriceItem); + rpc UpdatePriceItem(UpdatePriceItemRequest) returns (PriceItem); +} + +service PayService { + rpc CreateWxPayOrder(WxPayRequest) returns (WxPayResponse); + rpc QueryPayStatus(QueryPayStatusRequest) returns (PayStatusResponse); + rpc HandlePayCallback(PayCallbackRequest) returns (PayCallbackResponse); + rpc PayByBalance(PayByBalanceRequest) returns (StatusResponse); +} + +service AdminService { + rpc Login(AdminLoginRequest) returns (AdminLoginResponse); + rpc GetStatistics(GetStatisticsRequest) returns (Statistics); +} diff --git a/cloudprint-backend/proto/generated/cloudprint.pb.go b/cloudprint-backend/proto/generated/cloudprint.pb.go new file mode 100644 index 0000000..1f707e6 --- /dev/null +++ b/cloudprint-backend/proto/generated/cloudprint.pb.go @@ -0,0 +1,4785 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.36.11 +// protoc v6.32.0 +// source: cloudprint.proto + +package generated + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + _ "google.golang.org/protobuf/types/known/emptypb" + timestamppb "google.golang.org/protobuf/types/known/timestamppb" + reflect "reflect" + sync "sync" + unsafe "unsafe" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type Empty struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *Empty) Reset() { + *x = Empty{} + mi := &file_cloudprint_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *Empty) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Empty) ProtoMessage() {} + +func (x *Empty) ProtoReflect() protoreflect.Message { + mi := &file_cloudprint_proto_msgTypes[0] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Empty.ProtoReflect.Descriptor instead. +func (*Empty) Descriptor() ([]byte, []int) { + return file_cloudprint_proto_rawDescGZIP(), []int{0} +} + +type StatusResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Code int32 `protobuf:"varint,1,opt,name=code,proto3" json:"code,omitempty"` + Message string `protobuf:"bytes,2,opt,name=message,proto3" json:"message,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *StatusResponse) Reset() { + *x = StatusResponse{} + mi := &file_cloudprint_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *StatusResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*StatusResponse) ProtoMessage() {} + +func (x *StatusResponse) ProtoReflect() protoreflect.Message { + mi := &file_cloudprint_proto_msgTypes[1] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use StatusResponse.ProtoReflect.Descriptor instead. +func (*StatusResponse) Descriptor() ([]byte, []int) { + return file_cloudprint_proto_rawDescGZIP(), []int{1} +} + +func (x *StatusResponse) GetCode() int32 { + if x != nil { + return x.Code + } + return 0 +} + +func (x *StatusResponse) GetMessage() string { + if x != nil { + return x.Message + } + return "" +} + +type User struct { + state protoimpl.MessageState `protogen:"open.v1"` + Id int32 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"` + Openid string `protobuf:"bytes,2,opt,name=openid,proto3" json:"openid,omitempty"` + Nickname string `protobuf:"bytes,3,opt,name=nickname,proto3" json:"nickname,omitempty"` + Avatar string `protobuf:"bytes,4,opt,name=avatar,proto3" json:"avatar,omitempty"` + Balance float64 `protobuf:"fixed64,5,opt,name=balance,proto3" json:"balance,omitempty"` + CreatedAt *timestamppb.Timestamp `protobuf:"bytes,6,opt,name=created_at,json=createdAt,proto3" json:"created_at,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *User) Reset() { + *x = User{} + mi := &file_cloudprint_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *User) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*User) ProtoMessage() {} + +func (x *User) ProtoReflect() protoreflect.Message { + mi := &file_cloudprint_proto_msgTypes[2] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use User.ProtoReflect.Descriptor instead. +func (*User) Descriptor() ([]byte, []int) { + return file_cloudprint_proto_rawDescGZIP(), []int{2} +} + +func (x *User) GetId() int32 { + if x != nil { + return x.Id + } + return 0 +} + +func (x *User) GetOpenid() string { + if x != nil { + return x.Openid + } + return "" +} + +func (x *User) GetNickname() string { + if x != nil { + return x.Nickname + } + return "" +} + +func (x *User) GetAvatar() string { + if x != nil { + return x.Avatar + } + return "" +} + +func (x *User) GetBalance() float64 { + if x != nil { + return x.Balance + } + return 0 +} + +func (x *User) GetCreatedAt() *timestamppb.Timestamp { + if x != nil { + return x.CreatedAt + } + return nil +} + +type LoginRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + Code string `protobuf:"bytes,1,opt,name=code,proto3" json:"code,omitempty"` // 微信授权码 + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *LoginRequest) Reset() { + *x = LoginRequest{} + mi := &file_cloudprint_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *LoginRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LoginRequest) ProtoMessage() {} + +func (x *LoginRequest) ProtoReflect() protoreflect.Message { + mi := &file_cloudprint_proto_msgTypes[3] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use LoginRequest.ProtoReflect.Descriptor instead. +func (*LoginRequest) Descriptor() ([]byte, []int) { + return file_cloudprint_proto_rawDescGZIP(), []int{3} +} + +func (x *LoginRequest) GetCode() string { + if x != nil { + return x.Code + } + return "" +} + +type LoginResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + AccessToken string `protobuf:"bytes,1,opt,name=access_token,json=accessToken,proto3" json:"access_token,omitempty"` + RefreshToken string `protobuf:"bytes,2,opt,name=refresh_token,json=refreshToken,proto3" json:"refresh_token,omitempty"` + User *User `protobuf:"bytes,3,opt,name=user,proto3" json:"user,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *LoginResponse) Reset() { + *x = LoginResponse{} + mi := &file_cloudprint_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *LoginResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LoginResponse) ProtoMessage() {} + +func (x *LoginResponse) ProtoReflect() protoreflect.Message { + mi := &file_cloudprint_proto_msgTypes[4] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use LoginResponse.ProtoReflect.Descriptor instead. +func (*LoginResponse) Descriptor() ([]byte, []int) { + return file_cloudprint_proto_rawDescGZIP(), []int{4} +} + +func (x *LoginResponse) GetAccessToken() string { + if x != nil { + return x.AccessToken + } + return "" +} + +func (x *LoginResponse) GetRefreshToken() string { + if x != nil { + return x.RefreshToken + } + return "" +} + +func (x *LoginResponse) GetUser() *User { + if x != nil { + return x.User + } + return nil +} + +type RefreshRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + RefreshToken string `protobuf:"bytes,1,opt,name=refresh_token,json=refreshToken,proto3" json:"refresh_token,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *RefreshRequest) Reset() { + *x = RefreshRequest{} + mi := &file_cloudprint_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *RefreshRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RefreshRequest) ProtoMessage() {} + +func (x *RefreshRequest) ProtoReflect() protoreflect.Message { + mi := &file_cloudprint_proto_msgTypes[5] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RefreshRequest.ProtoReflect.Descriptor instead. +func (*RefreshRequest) Descriptor() ([]byte, []int) { + return file_cloudprint_proto_rawDescGZIP(), []int{5} +} + +func (x *RefreshRequest) GetRefreshToken() string { + if x != nil { + return x.RefreshToken + } + return "" +} + +type RefreshResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + AccessToken string `protobuf:"bytes,1,opt,name=access_token,json=accessToken,proto3" json:"access_token,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *RefreshResponse) Reset() { + *x = RefreshResponse{} + mi := &file_cloudprint_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *RefreshResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RefreshResponse) ProtoMessage() {} + +func (x *RefreshResponse) ProtoReflect() protoreflect.Message { + mi := &file_cloudprint_proto_msgTypes[6] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RefreshResponse.ProtoReflect.Descriptor instead. +func (*RefreshResponse) Descriptor() ([]byte, []int) { + return file_cloudprint_proto_rawDescGZIP(), []int{6} +} + +func (x *RefreshResponse) GetAccessToken() string { + if x != nil { + return x.AccessToken + } + return "" +} + +type GetUserInfoRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetUserInfoRequest) Reset() { + *x = GetUserInfoRequest{} + mi := &file_cloudprint_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetUserInfoRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetUserInfoRequest) ProtoMessage() {} + +func (x *GetUserInfoRequest) ProtoReflect() protoreflect.Message { + mi := &file_cloudprint_proto_msgTypes[7] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetUserInfoRequest.ProtoReflect.Descriptor instead. +func (*GetUserInfoRequest) Descriptor() ([]byte, []int) { + return file_cloudprint_proto_rawDescGZIP(), []int{7} +} + +type UpdateUserRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + Nickname string `protobuf:"bytes,1,opt,name=nickname,proto3" json:"nickname,omitempty"` + Avatar string `protobuf:"bytes,2,opt,name=avatar,proto3" json:"avatar,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *UpdateUserRequest) Reset() { + *x = UpdateUserRequest{} + mi := &file_cloudprint_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *UpdateUserRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UpdateUserRequest) ProtoMessage() {} + +func (x *UpdateUserRequest) ProtoReflect() protoreflect.Message { + mi := &file_cloudprint_proto_msgTypes[8] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use UpdateUserRequest.ProtoReflect.Descriptor instead. +func (*UpdateUserRequest) Descriptor() ([]byte, []int) { + return file_cloudprint_proto_rawDescGZIP(), []int{8} +} + +func (x *UpdateUserRequest) GetNickname() string { + if x != nil { + return x.Nickname + } + return "" +} + +func (x *UpdateUserRequest) GetAvatar() string { + if x != nil { + return x.Avatar + } + return "" +} + +type FileInfo struct { + state protoimpl.MessageState `protogen:"open.v1"` + Id int32 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"` + FileName string `protobuf:"bytes,2,opt,name=file_name,json=fileName,proto3" json:"file_name,omitempty"` + FilePath string `protobuf:"bytes,3,opt,name=file_path,json=filePath,proto3" json:"file_path,omitempty"` + FileType string `protobuf:"bytes,4,opt,name=file_type,json=fileType,proto3" json:"file_type,omitempty"` + FileSize int64 `protobuf:"varint,5,opt,name=file_size,json=fileSize,proto3" json:"file_size,omitempty"` + UploaderType string `protobuf:"bytes,6,opt,name=uploader_type,json=uploaderType,proto3" json:"uploader_type,omitempty"` + UploaderId int32 `protobuf:"varint,7,opt,name=uploader_id,json=uploaderId,proto3" json:"uploader_id,omitempty"` + CreatedAt *timestamppb.Timestamp `protobuf:"bytes,8,opt,name=created_at,json=createdAt,proto3" json:"created_at,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *FileInfo) Reset() { + *x = FileInfo{} + mi := &file_cloudprint_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *FileInfo) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*FileInfo) ProtoMessage() {} + +func (x *FileInfo) ProtoReflect() protoreflect.Message { + mi := &file_cloudprint_proto_msgTypes[9] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use FileInfo.ProtoReflect.Descriptor instead. +func (*FileInfo) Descriptor() ([]byte, []int) { + return file_cloudprint_proto_rawDescGZIP(), []int{9} +} + +func (x *FileInfo) GetId() int32 { + if x != nil { + return x.Id + } + return 0 +} + +func (x *FileInfo) GetFileName() string { + if x != nil { + return x.FileName + } + return "" +} + +func (x *FileInfo) GetFilePath() string { + if x != nil { + return x.FilePath + } + return "" +} + +func (x *FileInfo) GetFileType() string { + if x != nil { + return x.FileType + } + return "" +} + +func (x *FileInfo) GetFileSize() int64 { + if x != nil { + return x.FileSize + } + return 0 +} + +func (x *FileInfo) GetUploaderType() string { + if x != nil { + return x.UploaderType + } + return "" +} + +func (x *FileInfo) GetUploaderId() int32 { + if x != nil { + return x.UploaderId + } + return 0 +} + +func (x *FileInfo) GetCreatedAt() *timestamppb.Timestamp { + if x != nil { + return x.CreatedAt + } + return nil +} + +type UploadRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + FileName string `protobuf:"bytes,1,opt,name=file_name,json=fileName,proto3" json:"file_name,omitempty"` + FileType string `protobuf:"bytes,2,opt,name=file_type,json=fileType,proto3" json:"file_type,omitempty"` + FileSize int64 `protobuf:"varint,3,opt,name=file_size,json=fileSize,proto3" json:"file_size,omitempty"` + Data []byte `protobuf:"bytes,4,opt,name=data,proto3" json:"data,omitempty"` + IsLastChunk bool `protobuf:"varint,5,opt,name=is_last_chunk,json=isLastChunk,proto3" json:"is_last_chunk,omitempty"` + ChunkId string `protobuf:"bytes,6,opt,name=chunk_id,json=chunkId,proto3" json:"chunk_id,omitempty"` + ChunkIndex int32 `protobuf:"varint,7,opt,name=chunk_index,json=chunkIndex,proto3" json:"chunk_index,omitempty"` + TotalChunks int32 `protobuf:"varint,8,opt,name=total_chunks,json=totalChunks,proto3" json:"total_chunks,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *UploadRequest) Reset() { + *x = UploadRequest{} + mi := &file_cloudprint_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *UploadRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UploadRequest) ProtoMessage() {} + +func (x *UploadRequest) ProtoReflect() protoreflect.Message { + mi := &file_cloudprint_proto_msgTypes[10] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use UploadRequest.ProtoReflect.Descriptor instead. +func (*UploadRequest) Descriptor() ([]byte, []int) { + return file_cloudprint_proto_rawDescGZIP(), []int{10} +} + +func (x *UploadRequest) GetFileName() string { + if x != nil { + return x.FileName + } + return "" +} + +func (x *UploadRequest) GetFileType() string { + if x != nil { + return x.FileType + } + return "" +} + +func (x *UploadRequest) GetFileSize() int64 { + if x != nil { + return x.FileSize + } + return 0 +} + +func (x *UploadRequest) GetData() []byte { + if x != nil { + return x.Data + } + return nil +} + +func (x *UploadRequest) GetIsLastChunk() bool { + if x != nil { + return x.IsLastChunk + } + return false +} + +func (x *UploadRequest) GetChunkId() string { + if x != nil { + return x.ChunkId + } + return "" +} + +func (x *UploadRequest) GetChunkIndex() int32 { + if x != nil { + return x.ChunkIndex + } + return 0 +} + +func (x *UploadRequest) GetTotalChunks() int32 { + if x != nil { + return x.TotalChunks + } + return 0 +} + +type UploadResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + FileId int32 `protobuf:"varint,1,opt,name=file_id,json=fileId,proto3" json:"file_id,omitempty"` + FilePath string `protobuf:"bytes,2,opt,name=file_path,json=filePath,proto3" json:"file_path,omitempty"` + FileUrl string `protobuf:"bytes,3,opt,name=file_url,json=fileUrl,proto3" json:"file_url,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *UploadResponse) Reset() { + *x = UploadResponse{} + mi := &file_cloudprint_proto_msgTypes[11] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *UploadResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UploadResponse) ProtoMessage() {} + +func (x *UploadResponse) ProtoReflect() protoreflect.Message { + mi := &file_cloudprint_proto_msgTypes[11] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use UploadResponse.ProtoReflect.Descriptor instead. +func (*UploadResponse) Descriptor() ([]byte, []int) { + return file_cloudprint_proto_rawDescGZIP(), []int{11} +} + +func (x *UploadResponse) GetFileId() int32 { + if x != nil { + return x.FileId + } + return 0 +} + +func (x *UploadResponse) GetFilePath() string { + if x != nil { + return x.FilePath + } + return "" +} + +func (x *UploadResponse) GetFileUrl() string { + if x != nil { + return x.FileUrl + } + return "" +} + +type GetFileRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + FileId int32 `protobuf:"varint,1,opt,name=file_id,json=fileId,proto3" json:"file_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetFileRequest) Reset() { + *x = GetFileRequest{} + mi := &file_cloudprint_proto_msgTypes[12] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetFileRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetFileRequest) ProtoMessage() {} + +func (x *GetFileRequest) ProtoReflect() protoreflect.Message { + mi := &file_cloudprint_proto_msgTypes[12] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetFileRequest.ProtoReflect.Descriptor instead. +func (*GetFileRequest) Descriptor() ([]byte, []int) { + return file_cloudprint_proto_rawDescGZIP(), []int{12} +} + +func (x *GetFileRequest) GetFileId() int32 { + if x != nil { + return x.FileId + } + return 0 +} + +type FileData struct { + state protoimpl.MessageState `protogen:"open.v1"` + Data []byte `protobuf:"bytes,1,opt,name=data,proto3" json:"data,omitempty"` + IsLast bool `protobuf:"varint,2,opt,name=is_last,json=isLast,proto3" json:"is_last,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *FileData) Reset() { + *x = FileData{} + mi := &file_cloudprint_proto_msgTypes[13] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *FileData) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*FileData) ProtoMessage() {} + +func (x *FileData) ProtoReflect() protoreflect.Message { + mi := &file_cloudprint_proto_msgTypes[13] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use FileData.ProtoReflect.Descriptor instead. +func (*FileData) Descriptor() ([]byte, []int) { + return file_cloudprint_proto_rawDescGZIP(), []int{13} +} + +func (x *FileData) GetData() []byte { + if x != nil { + return x.Data + } + return nil +} + +func (x *FileData) GetIsLast() bool { + if x != nil { + return x.IsLast + } + return false +} + +type DeleteFileRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + FileId int32 `protobuf:"varint,1,opt,name=file_id,json=fileId,proto3" json:"file_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *DeleteFileRequest) Reset() { + *x = DeleteFileRequest{} + mi := &file_cloudprint_proto_msgTypes[14] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *DeleteFileRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DeleteFileRequest) ProtoMessage() {} + +func (x *DeleteFileRequest) ProtoReflect() protoreflect.Message { + mi := &file_cloudprint_proto_msgTypes[14] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DeleteFileRequest.ProtoReflect.Descriptor instead. +func (*DeleteFileRequest) Descriptor() ([]byte, []int) { + return file_cloudprint_proto_rawDescGZIP(), []int{14} +} + +func (x *DeleteFileRequest) GetFileId() int32 { + if x != nil { + return x.FileId + } + return 0 +} + +type WatermarkRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + FileId int32 `protobuf:"varint,1,opt,name=file_id,json=fileId,proto3" json:"file_id,omitempty"` + Text string `protobuf:"bytes,2,opt,name=text,proto3" json:"text,omitempty"` + Opacity float32 `protobuf:"fixed32,3,opt,name=opacity,proto3" json:"opacity,omitempty"` + Position int32 `protobuf:"varint,4,opt,name=position,proto3" json:"position,omitempty"` // 1: 左上 2: 右上 3: 左下 4: 右下 5: 居中 + FontSize int32 `protobuf:"varint,5,opt,name=font_size,json=fontSize,proto3" json:"font_size,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *WatermarkRequest) Reset() { + *x = WatermarkRequest{} + mi := &file_cloudprint_proto_msgTypes[15] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *WatermarkRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*WatermarkRequest) ProtoMessage() {} + +func (x *WatermarkRequest) ProtoReflect() protoreflect.Message { + mi := &file_cloudprint_proto_msgTypes[15] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use WatermarkRequest.ProtoReflect.Descriptor instead. +func (*WatermarkRequest) Descriptor() ([]byte, []int) { + return file_cloudprint_proto_rawDescGZIP(), []int{15} +} + +func (x *WatermarkRequest) GetFileId() int32 { + if x != nil { + return x.FileId + } + return 0 +} + +func (x *WatermarkRequest) GetText() string { + if x != nil { + return x.Text + } + return "" +} + +func (x *WatermarkRequest) GetOpacity() float32 { + if x != nil { + return x.Opacity + } + return 0 +} + +func (x *WatermarkRequest) GetPosition() int32 { + if x != nil { + return x.Position + } + return 0 +} + +func (x *WatermarkRequest) GetFontSize() int32 { + if x != nil { + return x.FontSize + } + return 0 +} + +type WatermarkResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + FileId int32 `protobuf:"varint,1,opt,name=file_id,json=fileId,proto3" json:"file_id,omitempty"` + FilePath string `protobuf:"bytes,2,opt,name=file_path,json=filePath,proto3" json:"file_path,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *WatermarkResponse) Reset() { + *x = WatermarkResponse{} + mi := &file_cloudprint_proto_msgTypes[16] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *WatermarkResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*WatermarkResponse) ProtoMessage() {} + +func (x *WatermarkResponse) ProtoReflect() protoreflect.Message { + mi := &file_cloudprint_proto_msgTypes[16] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use WatermarkResponse.ProtoReflect.Descriptor instead. +func (*WatermarkResponse) Descriptor() ([]byte, []int) { + return file_cloudprint_proto_rawDescGZIP(), []int{16} +} + +func (x *WatermarkResponse) GetFileId() int32 { + if x != nil { + return x.FileId + } + return 0 +} + +func (x *WatermarkResponse) GetFilePath() string { + if x != nil { + return x.FilePath + } + return "" +} + +type GetFileListRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + UploaderType string `protobuf:"bytes,1,opt,name=uploader_type,json=uploaderType,proto3" json:"uploader_type,omitempty"` + UploaderId int32 `protobuf:"varint,2,opt,name=uploader_id,json=uploaderId,proto3" json:"uploader_id,omitempty"` + Page int32 `protobuf:"varint,3,opt,name=page,proto3" json:"page,omitempty"` + PageSize int32 `protobuf:"varint,4,opt,name=page_size,json=pageSize,proto3" json:"page_size,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetFileListRequest) Reset() { + *x = GetFileListRequest{} + mi := &file_cloudprint_proto_msgTypes[17] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetFileListRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetFileListRequest) ProtoMessage() {} + +func (x *GetFileListRequest) ProtoReflect() protoreflect.Message { + mi := &file_cloudprint_proto_msgTypes[17] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetFileListRequest.ProtoReflect.Descriptor instead. +func (*GetFileListRequest) Descriptor() ([]byte, []int) { + return file_cloudprint_proto_rawDescGZIP(), []int{17} +} + +func (x *GetFileListRequest) GetUploaderType() string { + if x != nil { + return x.UploaderType + } + return "" +} + +func (x *GetFileListRequest) GetUploaderId() int32 { + if x != nil { + return x.UploaderId + } + return 0 +} + +func (x *GetFileListRequest) GetPage() int32 { + if x != nil { + return x.Page + } + return 0 +} + +func (x *GetFileListRequest) GetPageSize() int32 { + if x != nil { + return x.PageSize + } + return 0 +} + +type FileListResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Files []*FileInfo `protobuf:"bytes,1,rep,name=files,proto3" json:"files,omitempty"` + Total int32 `protobuf:"varint,2,opt,name=total,proto3" json:"total,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *FileListResponse) Reset() { + *x = FileListResponse{} + mi := &file_cloudprint_proto_msgTypes[18] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *FileListResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*FileListResponse) ProtoMessage() {} + +func (x *FileListResponse) ProtoReflect() protoreflect.Message { + mi := &file_cloudprint_proto_msgTypes[18] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use FileListResponse.ProtoReflect.Descriptor instead. +func (*FileListResponse) Descriptor() ([]byte, []int) { + return file_cloudprint_proto_rawDescGZIP(), []int{18} +} + +func (x *FileListResponse) GetFiles() []*FileInfo { + if x != nil { + return x.Files + } + return nil +} + +func (x *FileListResponse) GetTotal() int32 { + if x != nil { + return x.Total + } + return 0 +} + +type Order struct { + state protoimpl.MessageState `protogen:"open.v1"` + Id int32 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"` + OrderNo string `protobuf:"bytes,2,opt,name=order_no,json=orderNo,proto3" json:"order_no,omitempty"` + UserId int32 `protobuf:"varint,3,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` + Status int32 `protobuf:"varint,4,opt,name=status,proto3" json:"status,omitempty"` + TotalAmount float64 `protobuf:"fixed64,5,opt,name=total_amount,json=totalAmount,proto3" json:"total_amount,omitempty"` + Remark string `protobuf:"bytes,6,opt,name=remark,proto3" json:"remark,omitempty"` + CreatedAt *timestamppb.Timestamp `protobuf:"bytes,7,opt,name=created_at,json=createdAt,proto3" json:"created_at,omitempty"` + PaidAt *timestamppb.Timestamp `protobuf:"bytes,8,opt,name=paid_at,json=paidAt,proto3" json:"paid_at,omitempty"` + Items []*OrderItem `protobuf:"bytes,9,rep,name=items,proto3" json:"items,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *Order) Reset() { + *x = Order{} + mi := &file_cloudprint_proto_msgTypes[19] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *Order) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Order) ProtoMessage() {} + +func (x *Order) ProtoReflect() protoreflect.Message { + mi := &file_cloudprint_proto_msgTypes[19] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Order.ProtoReflect.Descriptor instead. +func (*Order) Descriptor() ([]byte, []int) { + return file_cloudprint_proto_rawDescGZIP(), []int{19} +} + +func (x *Order) GetId() int32 { + if x != nil { + return x.Id + } + return 0 +} + +func (x *Order) GetOrderNo() string { + if x != nil { + return x.OrderNo + } + return "" +} + +func (x *Order) GetUserId() int32 { + if x != nil { + return x.UserId + } + return 0 +} + +func (x *Order) GetStatus() int32 { + if x != nil { + return x.Status + } + return 0 +} + +func (x *Order) GetTotalAmount() float64 { + if x != nil { + return x.TotalAmount + } + return 0 +} + +func (x *Order) GetRemark() string { + if x != nil { + return x.Remark + } + return "" +} + +func (x *Order) GetCreatedAt() *timestamppb.Timestamp { + if x != nil { + return x.CreatedAt + } + return nil +} + +func (x *Order) GetPaidAt() *timestamppb.Timestamp { + if x != nil { + return x.PaidAt + } + return nil +} + +func (x *Order) GetItems() []*OrderItem { + if x != nil { + return x.Items + } + return nil +} + +type OrderItem struct { + state protoimpl.MessageState `protogen:"open.v1"` + Id int32 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"` + OrderId int32 `protobuf:"varint,2,opt,name=order_id,json=orderId,proto3" json:"order_id,omitempty"` + FileId int32 `protobuf:"varint,3,opt,name=file_id,json=fileId,proto3" json:"file_id,omitempty"` + File *FileInfo `protobuf:"bytes,4,opt,name=file,proto3" json:"file,omitempty"` + PrinterId int32 `protobuf:"varint,5,opt,name=printer_id,json=printerId,proto3" json:"printer_id,omitempty"` + Copies int32 `protobuf:"varint,6,opt,name=copies,proto3" json:"copies,omitempty"` + Color bool `protobuf:"varint,7,opt,name=color,proto3" json:"color,omitempty"` + Duplex bool `protobuf:"varint,8,opt,name=duplex,proto3" json:"duplex,omitempty"` + PageRange string `protobuf:"bytes,9,opt,name=page_range,json=pageRange,proto3" json:"page_range,omitempty"` + Price float64 `protobuf:"fixed64,10,opt,name=price,proto3" json:"price,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *OrderItem) Reset() { + *x = OrderItem{} + mi := &file_cloudprint_proto_msgTypes[20] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *OrderItem) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*OrderItem) ProtoMessage() {} + +func (x *OrderItem) ProtoReflect() protoreflect.Message { + mi := &file_cloudprint_proto_msgTypes[20] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use OrderItem.ProtoReflect.Descriptor instead. +func (*OrderItem) Descriptor() ([]byte, []int) { + return file_cloudprint_proto_rawDescGZIP(), []int{20} +} + +func (x *OrderItem) GetId() int32 { + if x != nil { + return x.Id + } + return 0 +} + +func (x *OrderItem) GetOrderId() int32 { + if x != nil { + return x.OrderId + } + return 0 +} + +func (x *OrderItem) GetFileId() int32 { + if x != nil { + return x.FileId + } + return 0 +} + +func (x *OrderItem) GetFile() *FileInfo { + if x != nil { + return x.File + } + return nil +} + +func (x *OrderItem) GetPrinterId() int32 { + if x != nil { + return x.PrinterId + } + return 0 +} + +func (x *OrderItem) GetCopies() int32 { + if x != nil { + return x.Copies + } + return 0 +} + +func (x *OrderItem) GetColor() bool { + if x != nil { + return x.Color + } + return false +} + +func (x *OrderItem) GetDuplex() bool { + if x != nil { + return x.Duplex + } + return false +} + +func (x *OrderItem) GetPageRange() string { + if x != nil { + return x.PageRange + } + return "" +} + +func (x *OrderItem) GetPrice() float64 { + if x != nil { + return x.Price + } + return 0 +} + +type CreateOrderRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + Items []*CreateOrderItem `protobuf:"bytes,1,rep,name=items,proto3" json:"items,omitempty"` + Remark string `protobuf:"bytes,2,opt,name=remark,proto3" json:"remark,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *CreateOrderRequest) Reset() { + *x = CreateOrderRequest{} + mi := &file_cloudprint_proto_msgTypes[21] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *CreateOrderRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CreateOrderRequest) ProtoMessage() {} + +func (x *CreateOrderRequest) ProtoReflect() protoreflect.Message { + mi := &file_cloudprint_proto_msgTypes[21] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CreateOrderRequest.ProtoReflect.Descriptor instead. +func (*CreateOrderRequest) Descriptor() ([]byte, []int) { + return file_cloudprint_proto_rawDescGZIP(), []int{21} +} + +func (x *CreateOrderRequest) GetItems() []*CreateOrderItem { + if x != nil { + return x.Items + } + return nil +} + +func (x *CreateOrderRequest) GetRemark() string { + if x != nil { + return x.Remark + } + return "" +} + +type CreateOrderItem struct { + state protoimpl.MessageState `protogen:"open.v1"` + FileId int32 `protobuf:"varint,1,opt,name=file_id,json=fileId,proto3" json:"file_id,omitempty"` + PrinterId int32 `protobuf:"varint,2,opt,name=printer_id,json=printerId,proto3" json:"printer_id,omitempty"` + Copies int32 `protobuf:"varint,3,opt,name=copies,proto3" json:"copies,omitempty"` + Color bool `protobuf:"varint,4,opt,name=color,proto3" json:"color,omitempty"` + Duplex bool `protobuf:"varint,5,opt,name=duplex,proto3" json:"duplex,omitempty"` + PageRange string `protobuf:"bytes,6,opt,name=page_range,json=pageRange,proto3" json:"page_range,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *CreateOrderItem) Reset() { + *x = CreateOrderItem{} + mi := &file_cloudprint_proto_msgTypes[22] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *CreateOrderItem) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CreateOrderItem) ProtoMessage() {} + +func (x *CreateOrderItem) ProtoReflect() protoreflect.Message { + mi := &file_cloudprint_proto_msgTypes[22] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CreateOrderItem.ProtoReflect.Descriptor instead. +func (*CreateOrderItem) Descriptor() ([]byte, []int) { + return file_cloudprint_proto_rawDescGZIP(), []int{22} +} + +func (x *CreateOrderItem) GetFileId() int32 { + if x != nil { + return x.FileId + } + return 0 +} + +func (x *CreateOrderItem) GetPrinterId() int32 { + if x != nil { + return x.PrinterId + } + return 0 +} + +func (x *CreateOrderItem) GetCopies() int32 { + if x != nil { + return x.Copies + } + return 0 +} + +func (x *CreateOrderItem) GetColor() bool { + if x != nil { + return x.Color + } + return false +} + +func (x *CreateOrderItem) GetDuplex() bool { + if x != nil { + return x.Duplex + } + return false +} + +func (x *CreateOrderItem) GetPageRange() string { + if x != nil { + return x.PageRange + } + return "" +} + +type CreateOrderResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + OrderNo string `protobuf:"bytes,1,opt,name=order_no,json=orderNo,proto3" json:"order_no,omitempty"` + TotalAmount float64 `protobuf:"fixed64,2,opt,name=total_amount,json=totalAmount,proto3" json:"total_amount,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *CreateOrderResponse) Reset() { + *x = CreateOrderResponse{} + mi := &file_cloudprint_proto_msgTypes[23] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *CreateOrderResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CreateOrderResponse) ProtoMessage() {} + +func (x *CreateOrderResponse) ProtoReflect() protoreflect.Message { + mi := &file_cloudprint_proto_msgTypes[23] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CreateOrderResponse.ProtoReflect.Descriptor instead. +func (*CreateOrderResponse) Descriptor() ([]byte, []int) { + return file_cloudprint_proto_rawDescGZIP(), []int{23} +} + +func (x *CreateOrderResponse) GetOrderNo() string { + if x != nil { + return x.OrderNo + } + return "" +} + +func (x *CreateOrderResponse) GetTotalAmount() float64 { + if x != nil { + return x.TotalAmount + } + return 0 +} + +type GetOrderRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + OrderNo string `protobuf:"bytes,1,opt,name=order_no,json=orderNo,proto3" json:"order_no,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetOrderRequest) Reset() { + *x = GetOrderRequest{} + mi := &file_cloudprint_proto_msgTypes[24] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetOrderRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetOrderRequest) ProtoMessage() {} + +func (x *GetOrderRequest) ProtoReflect() protoreflect.Message { + mi := &file_cloudprint_proto_msgTypes[24] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetOrderRequest.ProtoReflect.Descriptor instead. +func (*GetOrderRequest) Descriptor() ([]byte, []int) { + return file_cloudprint_proto_rawDescGZIP(), []int{24} +} + +func (x *GetOrderRequest) GetOrderNo() string { + if x != nil { + return x.OrderNo + } + return "" +} + +type GetOrderListRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + UserId int32 `protobuf:"varint,1,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` + Status int32 `protobuf:"varint,2,opt,name=status,proto3" json:"status,omitempty"` + Page int32 `protobuf:"varint,3,opt,name=page,proto3" json:"page,omitempty"` + PageSize int32 `protobuf:"varint,4,opt,name=page_size,json=pageSize,proto3" json:"page_size,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetOrderListRequest) Reset() { + *x = GetOrderListRequest{} + mi := &file_cloudprint_proto_msgTypes[25] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetOrderListRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetOrderListRequest) ProtoMessage() {} + +func (x *GetOrderListRequest) ProtoReflect() protoreflect.Message { + mi := &file_cloudprint_proto_msgTypes[25] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetOrderListRequest.ProtoReflect.Descriptor instead. +func (*GetOrderListRequest) Descriptor() ([]byte, []int) { + return file_cloudprint_proto_rawDescGZIP(), []int{25} +} + +func (x *GetOrderListRequest) GetUserId() int32 { + if x != nil { + return x.UserId + } + return 0 +} + +func (x *GetOrderListRequest) GetStatus() int32 { + if x != nil { + return x.Status + } + return 0 +} + +func (x *GetOrderListRequest) GetPage() int32 { + if x != nil { + return x.Page + } + return 0 +} + +func (x *GetOrderListRequest) GetPageSize() int32 { + if x != nil { + return x.PageSize + } + return 0 +} + +type OrderListResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Orders []*Order `protobuf:"bytes,1,rep,name=orders,proto3" json:"orders,omitempty"` + Total int32 `protobuf:"varint,2,opt,name=total,proto3" json:"total,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *OrderListResponse) Reset() { + *x = OrderListResponse{} + mi := &file_cloudprint_proto_msgTypes[26] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *OrderListResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*OrderListResponse) ProtoMessage() {} + +func (x *OrderListResponse) ProtoReflect() protoreflect.Message { + mi := &file_cloudprint_proto_msgTypes[26] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use OrderListResponse.ProtoReflect.Descriptor instead. +func (*OrderListResponse) Descriptor() ([]byte, []int) { + return file_cloudprint_proto_rawDescGZIP(), []int{26} +} + +func (x *OrderListResponse) GetOrders() []*Order { + if x != nil { + return x.Orders + } + return nil +} + +func (x *OrderListResponse) GetTotal() int32 { + if x != nil { + return x.Total + } + return 0 +} + +type UpdateOrderStatusRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + OrderNo string `protobuf:"bytes,1,opt,name=order_no,json=orderNo,proto3" json:"order_no,omitempty"` + Status int32 `protobuf:"varint,2,opt,name=status,proto3" json:"status,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *UpdateOrderStatusRequest) Reset() { + *x = UpdateOrderStatusRequest{} + mi := &file_cloudprint_proto_msgTypes[27] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *UpdateOrderStatusRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UpdateOrderStatusRequest) ProtoMessage() {} + +func (x *UpdateOrderStatusRequest) ProtoReflect() protoreflect.Message { + mi := &file_cloudprint_proto_msgTypes[27] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use UpdateOrderStatusRequest.ProtoReflect.Descriptor instead. +func (*UpdateOrderStatusRequest) Descriptor() ([]byte, []int) { + return file_cloudprint_proto_rawDescGZIP(), []int{27} +} + +func (x *UpdateOrderStatusRequest) GetOrderNo() string { + if x != nil { + return x.OrderNo + } + return "" +} + +func (x *UpdateOrderStatusRequest) GetStatus() int32 { + if x != nil { + return x.Status + } + return 0 +} + +type CancelOrderRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + OrderNo string `protobuf:"bytes,1,opt,name=order_no,json=orderNo,proto3" json:"order_no,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *CancelOrderRequest) Reset() { + *x = CancelOrderRequest{} + mi := &file_cloudprint_proto_msgTypes[28] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *CancelOrderRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CancelOrderRequest) ProtoMessage() {} + +func (x *CancelOrderRequest) ProtoReflect() protoreflect.Message { + mi := &file_cloudprint_proto_msgTypes[28] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CancelOrderRequest.ProtoReflect.Descriptor instead. +func (*CancelOrderRequest) Descriptor() ([]byte, []int) { + return file_cloudprint_proto_rawDescGZIP(), []int{28} +} + +func (x *CancelOrderRequest) GetOrderNo() string { + if x != nil { + return x.OrderNo + } + return "" +} + +type Printer struct { + state protoimpl.MessageState `protogen:"open.v1"` + Id int32 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"` + Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` + DisplayName string `protobuf:"bytes,3,opt,name=display_name,json=displayName,proto3" json:"display_name,omitempty"` + IsActive bool `protobuf:"varint,4,opt,name=is_active,json=isActive,proto3" json:"is_active,omitempty"` + Status int32 `protobuf:"varint,5,opt,name=status,proto3" json:"status,omitempty"` // 0: 空闲 1: 打印中 2: 离线 + LastHeartbeat *timestamppb.Timestamp `protobuf:"bytes,6,opt,name=last_heartbeat,json=lastHeartbeat,proto3" json:"last_heartbeat,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *Printer) Reset() { + *x = Printer{} + mi := &file_cloudprint_proto_msgTypes[29] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *Printer) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Printer) ProtoMessage() {} + +func (x *Printer) ProtoReflect() protoreflect.Message { + mi := &file_cloudprint_proto_msgTypes[29] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Printer.ProtoReflect.Descriptor instead. +func (*Printer) Descriptor() ([]byte, []int) { + return file_cloudprint_proto_rawDescGZIP(), []int{29} +} + +func (x *Printer) GetId() int32 { + if x != nil { + return x.Id + } + return 0 +} + +func (x *Printer) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *Printer) GetDisplayName() string { + if x != nil { + return x.DisplayName + } + return "" +} + +func (x *Printer) GetIsActive() bool { + if x != nil { + return x.IsActive + } + return false +} + +func (x *Printer) GetStatus() int32 { + if x != nil { + return x.Status + } + return 0 +} + +func (x *Printer) GetLastHeartbeat() *timestamppb.Timestamp { + if x != nil { + return x.LastHeartbeat + } + return nil +} + +type GetPrintersRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetPrintersRequest) Reset() { + *x = GetPrintersRequest{} + mi := &file_cloudprint_proto_msgTypes[30] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetPrintersRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetPrintersRequest) ProtoMessage() {} + +func (x *GetPrintersRequest) ProtoReflect() protoreflect.Message { + mi := &file_cloudprint_proto_msgTypes[30] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetPrintersRequest.ProtoReflect.Descriptor instead. +func (*GetPrintersRequest) Descriptor() ([]byte, []int) { + return file_cloudprint_proto_rawDescGZIP(), []int{30} +} + +type PrinterListResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Printers []*Printer `protobuf:"bytes,1,rep,name=printers,proto3" json:"printers,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *PrinterListResponse) Reset() { + *x = PrinterListResponse{} + mi := &file_cloudprint_proto_msgTypes[31] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *PrinterListResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PrinterListResponse) ProtoMessage() {} + +func (x *PrinterListResponse) ProtoReflect() protoreflect.Message { + mi := &file_cloudprint_proto_msgTypes[31] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PrinterListResponse.ProtoReflect.Descriptor instead. +func (*PrinterListResponse) Descriptor() ([]byte, []int) { + return file_cloudprint_proto_rawDescGZIP(), []int{31} +} + +func (x *PrinterListResponse) GetPrinters() []*Printer { + if x != nil { + return x.Printers + } + return nil +} + +type GetPrinterStatusRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + PrinterId int32 `protobuf:"varint,1,opt,name=printer_id,json=printerId,proto3" json:"printer_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetPrinterStatusRequest) Reset() { + *x = GetPrinterStatusRequest{} + mi := &file_cloudprint_proto_msgTypes[32] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetPrinterStatusRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetPrinterStatusRequest) ProtoMessage() {} + +func (x *GetPrinterStatusRequest) ProtoReflect() protoreflect.Message { + mi := &file_cloudprint_proto_msgTypes[32] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetPrinterStatusRequest.ProtoReflect.Descriptor instead. +func (*GetPrinterStatusRequest) Descriptor() ([]byte, []int) { + return file_cloudprint_proto_rawDescGZIP(), []int{32} +} + +func (x *GetPrinterStatusRequest) GetPrinterId() int32 { + if x != nil { + return x.PrinterId + } + return 0 +} + +type PrinterStatusResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Printer *Printer `protobuf:"bytes,1,opt,name=printer,proto3" json:"printer,omitempty"` + QueueCount int32 `protobuf:"varint,2,opt,name=queue_count,json=queueCount,proto3" json:"queue_count,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *PrinterStatusResponse) Reset() { + *x = PrinterStatusResponse{} + mi := &file_cloudprint_proto_msgTypes[33] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *PrinterStatusResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PrinterStatusResponse) ProtoMessage() {} + +func (x *PrinterStatusResponse) ProtoReflect() protoreflect.Message { + mi := &file_cloudprint_proto_msgTypes[33] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PrinterStatusResponse.ProtoReflect.Descriptor instead. +func (*PrinterStatusResponse) Descriptor() ([]byte, []int) { + return file_cloudprint_proto_rawDescGZIP(), []int{33} +} + +func (x *PrinterStatusResponse) GetPrinter() *Printer { + if x != nil { + return x.Printer + } + return nil +} + +func (x *PrinterStatusResponse) GetQueueCount() int32 { + if x != nil { + return x.QueueCount + } + return 0 +} + +type RegisterPrinterRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + DisplayName string `protobuf:"bytes,2,opt,name=display_name,json=displayName,proto3" json:"display_name,omitempty"` + ApiKey string `protobuf:"bytes,3,opt,name=api_key,json=apiKey,proto3" json:"api_key,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *RegisterPrinterRequest) Reset() { + *x = RegisterPrinterRequest{} + mi := &file_cloudprint_proto_msgTypes[34] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *RegisterPrinterRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RegisterPrinterRequest) ProtoMessage() {} + +func (x *RegisterPrinterRequest) ProtoReflect() protoreflect.Message { + mi := &file_cloudprint_proto_msgTypes[34] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RegisterPrinterRequest.ProtoReflect.Descriptor instead. +func (*RegisterPrinterRequest) Descriptor() ([]byte, []int) { + return file_cloudprint_proto_rawDescGZIP(), []int{34} +} + +func (x *RegisterPrinterRequest) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *RegisterPrinterRequest) GetDisplayName() string { + if x != nil { + return x.DisplayName + } + return "" +} + +func (x *RegisterPrinterRequest) GetApiKey() string { + if x != nil { + return x.ApiKey + } + return "" +} + +type RegisterPrinterResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + PrinterId int32 `protobuf:"varint,1,opt,name=printer_id,json=printerId,proto3" json:"printer_id,omitempty"` + Token string `protobuf:"bytes,2,opt,name=token,proto3" json:"token,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *RegisterPrinterResponse) Reset() { + *x = RegisterPrinterResponse{} + mi := &file_cloudprint_proto_msgTypes[35] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *RegisterPrinterResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RegisterPrinterResponse) ProtoMessage() {} + +func (x *RegisterPrinterResponse) ProtoReflect() protoreflect.Message { + mi := &file_cloudprint_proto_msgTypes[35] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RegisterPrinterResponse.ProtoReflect.Descriptor instead. +func (*RegisterPrinterResponse) Descriptor() ([]byte, []int) { + return file_cloudprint_proto_rawDescGZIP(), []int{35} +} + +func (x *RegisterPrinterResponse) GetPrinterId() int32 { + if x != nil { + return x.PrinterId + } + return 0 +} + +func (x *RegisterPrinterResponse) GetToken() string { + if x != nil { + return x.Token + } + return "" +} + +type PrinterHeartbeatRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + PrinterId int32 `protobuf:"varint,1,opt,name=printer_id,json=printerId,proto3" json:"printer_id,omitempty"` + Status int32 `protobuf:"varint,2,opt,name=status,proto3" json:"status,omitempty"` + Token string `protobuf:"bytes,3,opt,name=token,proto3" json:"token,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *PrinterHeartbeatRequest) Reset() { + *x = PrinterHeartbeatRequest{} + mi := &file_cloudprint_proto_msgTypes[36] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *PrinterHeartbeatRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PrinterHeartbeatRequest) ProtoMessage() {} + +func (x *PrinterHeartbeatRequest) ProtoReflect() protoreflect.Message { + mi := &file_cloudprint_proto_msgTypes[36] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PrinterHeartbeatRequest.ProtoReflect.Descriptor instead. +func (*PrinterHeartbeatRequest) Descriptor() ([]byte, []int) { + return file_cloudprint_proto_rawDescGZIP(), []int{36} +} + +func (x *PrinterHeartbeatRequest) GetPrinterId() int32 { + if x != nil { + return x.PrinterId + } + return 0 +} + +func (x *PrinterHeartbeatRequest) GetStatus() int32 { + if x != nil { + return x.Status + } + return 0 +} + +func (x *PrinterHeartbeatRequest) GetToken() string { + if x != nil { + return x.Token + } + return "" +} + +type PrintJob struct { + state protoimpl.MessageState `protogen:"open.v1"` + Id int32 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"` + JobNo string `protobuf:"bytes,2,opt,name=job_no,json=jobNo,proto3" json:"job_no,omitempty"` + PrinterId int32 `protobuf:"varint,3,opt,name=printer_id,json=printerId,proto3" json:"printer_id,omitempty"` + OrderItemId int32 `protobuf:"varint,4,opt,name=order_item_id,json=orderItemId,proto3" json:"order_item_id,omitempty"` + Status string `protobuf:"bytes,5,opt,name=status,proto3" json:"status,omitempty"` // pending/printing/completed/failed/cancelled + Progress int32 `protobuf:"varint,6,opt,name=progress,proto3" json:"progress,omitempty"` + ErrorMsg string `protobuf:"bytes,7,opt,name=error_msg,json=errorMsg,proto3" json:"error_msg,omitempty"` + StartedAt *timestamppb.Timestamp `protobuf:"bytes,8,opt,name=started_at,json=startedAt,proto3" json:"started_at,omitempty"` + CompletedAt *timestamppb.Timestamp `protobuf:"bytes,9,opt,name=completed_at,json=completedAt,proto3" json:"completed_at,omitempty"` + OrderItem *OrderItem `protobuf:"bytes,10,opt,name=order_item,json=orderItem,proto3" json:"order_item,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *PrintJob) Reset() { + *x = PrintJob{} + mi := &file_cloudprint_proto_msgTypes[37] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *PrintJob) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PrintJob) ProtoMessage() {} + +func (x *PrintJob) ProtoReflect() protoreflect.Message { + mi := &file_cloudprint_proto_msgTypes[37] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PrintJob.ProtoReflect.Descriptor instead. +func (*PrintJob) Descriptor() ([]byte, []int) { + return file_cloudprint_proto_rawDescGZIP(), []int{37} +} + +func (x *PrintJob) GetId() int32 { + if x != nil { + return x.Id + } + return 0 +} + +func (x *PrintJob) GetJobNo() string { + if x != nil { + return x.JobNo + } + return "" +} + +func (x *PrintJob) GetPrinterId() int32 { + if x != nil { + return x.PrinterId + } + return 0 +} + +func (x *PrintJob) GetOrderItemId() int32 { + if x != nil { + return x.OrderItemId + } + return 0 +} + +func (x *PrintJob) GetStatus() string { + if x != nil { + return x.Status + } + return "" +} + +func (x *PrintJob) GetProgress() int32 { + if x != nil { + return x.Progress + } + return 0 +} + +func (x *PrintJob) GetErrorMsg() string { + if x != nil { + return x.ErrorMsg + } + return "" +} + +func (x *PrintJob) GetStartedAt() *timestamppb.Timestamp { + if x != nil { + return x.StartedAt + } + return nil +} + +func (x *PrintJob) GetCompletedAt() *timestamppb.Timestamp { + if x != nil { + return x.CompletedAt + } + return nil +} + +func (x *PrintJob) GetOrderItem() *OrderItem { + if x != nil { + return x.OrderItem + } + return nil +} + +type SubmitPrintJobRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + OrderItemId int32 `protobuf:"varint,1,opt,name=order_item_id,json=orderItemId,proto3" json:"order_item_id,omitempty"` + PrinterId int32 `protobuf:"varint,2,opt,name=printer_id,json=printerId,proto3" json:"printer_id,omitempty"` + FilePath string `protobuf:"bytes,3,opt,name=file_path,json=filePath,proto3" json:"file_path,omitempty"` + Copies int32 `protobuf:"varint,4,opt,name=copies,proto3" json:"copies,omitempty"` + Color bool `protobuf:"varint,5,opt,name=color,proto3" json:"color,omitempty"` + Duplex bool `protobuf:"varint,6,opt,name=duplex,proto3" json:"duplex,omitempty"` + PageRange string `protobuf:"bytes,7,opt,name=page_range,json=pageRange,proto3" json:"page_range,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *SubmitPrintJobRequest) Reset() { + *x = SubmitPrintJobRequest{} + mi := &file_cloudprint_proto_msgTypes[38] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *SubmitPrintJobRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SubmitPrintJobRequest) ProtoMessage() {} + +func (x *SubmitPrintJobRequest) ProtoReflect() protoreflect.Message { + mi := &file_cloudprint_proto_msgTypes[38] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SubmitPrintJobRequest.ProtoReflect.Descriptor instead. +func (*SubmitPrintJobRequest) Descriptor() ([]byte, []int) { + return file_cloudprint_proto_rawDescGZIP(), []int{38} +} + +func (x *SubmitPrintJobRequest) GetOrderItemId() int32 { + if x != nil { + return x.OrderItemId + } + return 0 +} + +func (x *SubmitPrintJobRequest) GetPrinterId() int32 { + if x != nil { + return x.PrinterId + } + return 0 +} + +func (x *SubmitPrintJobRequest) GetFilePath() string { + if x != nil { + return x.FilePath + } + return "" +} + +func (x *SubmitPrintJobRequest) GetCopies() int32 { + if x != nil { + return x.Copies + } + return 0 +} + +func (x *SubmitPrintJobRequest) GetColor() bool { + if x != nil { + return x.Color + } + return false +} + +func (x *SubmitPrintJobRequest) GetDuplex() bool { + if x != nil { + return x.Duplex + } + return false +} + +func (x *SubmitPrintJobRequest) GetPageRange() string { + if x != nil { + return x.PageRange + } + return "" +} + +type SubmitPrintJobResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + JobNo string `protobuf:"bytes,1,opt,name=job_no,json=jobNo,proto3" json:"job_no,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *SubmitPrintJobResponse) Reset() { + *x = SubmitPrintJobResponse{} + mi := &file_cloudprint_proto_msgTypes[39] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *SubmitPrintJobResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SubmitPrintJobResponse) ProtoMessage() {} + +func (x *SubmitPrintJobResponse) ProtoReflect() protoreflect.Message { + mi := &file_cloudprint_proto_msgTypes[39] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SubmitPrintJobResponse.ProtoReflect.Descriptor instead. +func (*SubmitPrintJobResponse) Descriptor() ([]byte, []int) { + return file_cloudprint_proto_rawDescGZIP(), []int{39} +} + +func (x *SubmitPrintJobResponse) GetJobNo() string { + if x != nil { + return x.JobNo + } + return "" +} + +type CancelPrintJobRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + JobNo string `protobuf:"bytes,1,opt,name=job_no,json=jobNo,proto3" json:"job_no,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *CancelPrintJobRequest) Reset() { + *x = CancelPrintJobRequest{} + mi := &file_cloudprint_proto_msgTypes[40] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *CancelPrintJobRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CancelPrintJobRequest) ProtoMessage() {} + +func (x *CancelPrintJobRequest) ProtoReflect() protoreflect.Message { + mi := &file_cloudprint_proto_msgTypes[40] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CancelPrintJobRequest.ProtoReflect.Descriptor instead. +func (*CancelPrintJobRequest) Descriptor() ([]byte, []int) { + return file_cloudprint_proto_rawDescGZIP(), []int{40} +} + +func (x *CancelPrintJobRequest) GetJobNo() string { + if x != nil { + return x.JobNo + } + return "" +} + +type SubscribeJobsRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + PrinterId int32 `protobuf:"varint,1,opt,name=printer_id,json=printerId,proto3" json:"printer_id,omitempty"` + Token string `protobuf:"bytes,2,opt,name=token,proto3" json:"token,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *SubscribeJobsRequest) Reset() { + *x = SubscribeJobsRequest{} + mi := &file_cloudprint_proto_msgTypes[41] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *SubscribeJobsRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SubscribeJobsRequest) ProtoMessage() {} + +func (x *SubscribeJobsRequest) ProtoReflect() protoreflect.Message { + mi := &file_cloudprint_proto_msgTypes[41] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SubscribeJobsRequest.ProtoReflect.Descriptor instead. +func (*SubscribeJobsRequest) Descriptor() ([]byte, []int) { + return file_cloudprint_proto_rawDescGZIP(), []int{41} +} + +func (x *SubscribeJobsRequest) GetPrinterId() int32 { + if x != nil { + return x.PrinterId + } + return 0 +} + +func (x *SubscribeJobsRequest) GetToken() string { + if x != nil { + return x.Token + } + return "" +} + +type ReportJobStatusRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + JobNo string `protobuf:"bytes,1,opt,name=job_no,json=jobNo,proto3" json:"job_no,omitempty"` + Status string `protobuf:"bytes,2,opt,name=status,proto3" json:"status,omitempty"` + Progress int32 `protobuf:"varint,3,opt,name=progress,proto3" json:"progress,omitempty"` + ErrorMsg string `protobuf:"bytes,4,opt,name=error_msg,json=errorMsg,proto3" json:"error_msg,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ReportJobStatusRequest) Reset() { + *x = ReportJobStatusRequest{} + mi := &file_cloudprint_proto_msgTypes[42] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ReportJobStatusRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ReportJobStatusRequest) ProtoMessage() {} + +func (x *ReportJobStatusRequest) ProtoReflect() protoreflect.Message { + mi := &file_cloudprint_proto_msgTypes[42] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ReportJobStatusRequest.ProtoReflect.Descriptor instead. +func (*ReportJobStatusRequest) Descriptor() ([]byte, []int) { + return file_cloudprint_proto_rawDescGZIP(), []int{42} +} + +func (x *ReportJobStatusRequest) GetJobNo() string { + if x != nil { + return x.JobNo + } + return "" +} + +func (x *ReportJobStatusRequest) GetStatus() string { + if x != nil { + return x.Status + } + return "" +} + +func (x *ReportJobStatusRequest) GetProgress() int32 { + if x != nil { + return x.Progress + } + return 0 +} + +func (x *ReportJobStatusRequest) GetErrorMsg() string { + if x != nil { + return x.ErrorMsg + } + return "" +} + +type LibraryCategory struct { + state protoimpl.MessageState `protogen:"open.v1"` + Id int32 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"` + Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` + Icon string `protobuf:"bytes,3,opt,name=icon,proto3" json:"icon,omitempty"` + SortOrder int32 `protobuf:"varint,4,opt,name=sort_order,json=sortOrder,proto3" json:"sort_order,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *LibraryCategory) Reset() { + *x = LibraryCategory{} + mi := &file_cloudprint_proto_msgTypes[43] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *LibraryCategory) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LibraryCategory) ProtoMessage() {} + +func (x *LibraryCategory) ProtoReflect() protoreflect.Message { + mi := &file_cloudprint_proto_msgTypes[43] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use LibraryCategory.ProtoReflect.Descriptor instead. +func (*LibraryCategory) Descriptor() ([]byte, []int) { + return file_cloudprint_proto_rawDescGZIP(), []int{43} +} + +func (x *LibraryCategory) GetId() int32 { + if x != nil { + return x.Id + } + return 0 +} + +func (x *LibraryCategory) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *LibraryCategory) GetIcon() string { + if x != nil { + return x.Icon + } + return "" +} + +func (x *LibraryCategory) GetSortOrder() int32 { + if x != nil { + return x.SortOrder + } + return 0 +} + +type LibraryFile struct { + state protoimpl.MessageState `protogen:"open.v1"` + Id int32 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"` + CategoryId int32 `protobuf:"varint,2,opt,name=category_id,json=categoryId,proto3" json:"category_id,omitempty"` + FileId int32 `protobuf:"varint,3,opt,name=file_id,json=fileId,proto3" json:"file_id,omitempty"` + Title string `protobuf:"bytes,4,opt,name=title,proto3" json:"title,omitempty"` + Description string `protobuf:"bytes,5,opt,name=description,proto3" json:"description,omitempty"` + PageCount int32 `protobuf:"varint,6,opt,name=page_count,json=pageCount,proto3" json:"page_count,omitempty"` + DownloadCount int32 `protobuf:"varint,7,opt,name=download_count,json=downloadCount,proto3" json:"download_count,omitempty"` + File *FileInfo `protobuf:"bytes,8,opt,name=file,proto3" json:"file,omitempty"` + CreatedAt *timestamppb.Timestamp `protobuf:"bytes,9,opt,name=created_at,json=createdAt,proto3" json:"created_at,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *LibraryFile) Reset() { + *x = LibraryFile{} + mi := &file_cloudprint_proto_msgTypes[44] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *LibraryFile) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LibraryFile) ProtoMessage() {} + +func (x *LibraryFile) ProtoReflect() protoreflect.Message { + mi := &file_cloudprint_proto_msgTypes[44] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use LibraryFile.ProtoReflect.Descriptor instead. +func (*LibraryFile) Descriptor() ([]byte, []int) { + return file_cloudprint_proto_rawDescGZIP(), []int{44} +} + +func (x *LibraryFile) GetId() int32 { + if x != nil { + return x.Id + } + return 0 +} + +func (x *LibraryFile) GetCategoryId() int32 { + if x != nil { + return x.CategoryId + } + return 0 +} + +func (x *LibraryFile) GetFileId() int32 { + if x != nil { + return x.FileId + } + return 0 +} + +func (x *LibraryFile) GetTitle() string { + if x != nil { + return x.Title + } + return "" +} + +func (x *LibraryFile) GetDescription() string { + if x != nil { + return x.Description + } + return "" +} + +func (x *LibraryFile) GetPageCount() int32 { + if x != nil { + return x.PageCount + } + return 0 +} + +func (x *LibraryFile) GetDownloadCount() int32 { + if x != nil { + return x.DownloadCount + } + return 0 +} + +func (x *LibraryFile) GetFile() *FileInfo { + if x != nil { + return x.File + } + return nil +} + +func (x *LibraryFile) GetCreatedAt() *timestamppb.Timestamp { + if x != nil { + return x.CreatedAt + } + return nil +} + +type GetCategoriesRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetCategoriesRequest) Reset() { + *x = GetCategoriesRequest{} + mi := &file_cloudprint_proto_msgTypes[45] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetCategoriesRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetCategoriesRequest) ProtoMessage() {} + +func (x *GetCategoriesRequest) ProtoReflect() protoreflect.Message { + mi := &file_cloudprint_proto_msgTypes[45] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetCategoriesRequest.ProtoReflect.Descriptor instead. +func (*GetCategoriesRequest) Descriptor() ([]byte, []int) { + return file_cloudprint_proto_rawDescGZIP(), []int{45} +} + +type CategoryListResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Categories []*LibraryCategory `protobuf:"bytes,1,rep,name=categories,proto3" json:"categories,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *CategoryListResponse) Reset() { + *x = CategoryListResponse{} + mi := &file_cloudprint_proto_msgTypes[46] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *CategoryListResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CategoryListResponse) ProtoMessage() {} + +func (x *CategoryListResponse) ProtoReflect() protoreflect.Message { + mi := &file_cloudprint_proto_msgTypes[46] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CategoryListResponse.ProtoReflect.Descriptor instead. +func (*CategoryListResponse) Descriptor() ([]byte, []int) { + return file_cloudprint_proto_rawDescGZIP(), []int{46} +} + +func (x *CategoryListResponse) GetCategories() []*LibraryCategory { + if x != nil { + return x.Categories + } + return nil +} + +type GetLibraryFilesRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + CategoryId int32 `protobuf:"varint,1,opt,name=category_id,json=categoryId,proto3" json:"category_id,omitempty"` + Page int32 `protobuf:"varint,2,opt,name=page,proto3" json:"page,omitempty"` + PageSize int32 `protobuf:"varint,3,opt,name=page_size,json=pageSize,proto3" json:"page_size,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetLibraryFilesRequest) Reset() { + *x = GetLibraryFilesRequest{} + mi := &file_cloudprint_proto_msgTypes[47] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetLibraryFilesRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetLibraryFilesRequest) ProtoMessage() {} + +func (x *GetLibraryFilesRequest) ProtoReflect() protoreflect.Message { + mi := &file_cloudprint_proto_msgTypes[47] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetLibraryFilesRequest.ProtoReflect.Descriptor instead. +func (*GetLibraryFilesRequest) Descriptor() ([]byte, []int) { + return file_cloudprint_proto_rawDescGZIP(), []int{47} +} + +func (x *GetLibraryFilesRequest) GetCategoryId() int32 { + if x != nil { + return x.CategoryId + } + return 0 +} + +func (x *GetLibraryFilesRequest) GetPage() int32 { + if x != nil { + return x.Page + } + return 0 +} + +func (x *GetLibraryFilesRequest) GetPageSize() int32 { + if x != nil { + return x.PageSize + } + return 0 +} + +type LibraryFileListResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Files []*LibraryFile `protobuf:"bytes,1,rep,name=files,proto3" json:"files,omitempty"` + Total int32 `protobuf:"varint,2,opt,name=total,proto3" json:"total,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *LibraryFileListResponse) Reset() { + *x = LibraryFileListResponse{} + mi := &file_cloudprint_proto_msgTypes[48] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *LibraryFileListResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LibraryFileListResponse) ProtoMessage() {} + +func (x *LibraryFileListResponse) ProtoReflect() protoreflect.Message { + mi := &file_cloudprint_proto_msgTypes[48] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use LibraryFileListResponse.ProtoReflect.Descriptor instead. +func (*LibraryFileListResponse) Descriptor() ([]byte, []int) { + return file_cloudprint_proto_rawDescGZIP(), []int{48} +} + +func (x *LibraryFileListResponse) GetFiles() []*LibraryFile { + if x != nil { + return x.Files + } + return nil +} + +func (x *LibraryFileListResponse) GetTotal() int32 { + if x != nil { + return x.Total + } + return 0 +} + +type UploadLibraryFileRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + CategoryId int32 `protobuf:"varint,1,opt,name=category_id,json=categoryId,proto3" json:"category_id,omitempty"` + Title string `protobuf:"bytes,2,opt,name=title,proto3" json:"title,omitempty"` + Description string `protobuf:"bytes,3,opt,name=description,proto3" json:"description,omitempty"` + Data []byte `protobuf:"bytes,4,opt,name=data,proto3" json:"data,omitempty"` + FileName string `protobuf:"bytes,5,opt,name=file_name,json=fileName,proto3" json:"file_name,omitempty"` + FileType string `protobuf:"bytes,6,opt,name=file_type,json=fileType,proto3" json:"file_type,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *UploadLibraryFileRequest) Reset() { + *x = UploadLibraryFileRequest{} + mi := &file_cloudprint_proto_msgTypes[49] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *UploadLibraryFileRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UploadLibraryFileRequest) ProtoMessage() {} + +func (x *UploadLibraryFileRequest) ProtoReflect() protoreflect.Message { + mi := &file_cloudprint_proto_msgTypes[49] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use UploadLibraryFileRequest.ProtoReflect.Descriptor instead. +func (*UploadLibraryFileRequest) Descriptor() ([]byte, []int) { + return file_cloudprint_proto_rawDescGZIP(), []int{49} +} + +func (x *UploadLibraryFileRequest) GetCategoryId() int32 { + if x != nil { + return x.CategoryId + } + return 0 +} + +func (x *UploadLibraryFileRequest) GetTitle() string { + if x != nil { + return x.Title + } + return "" +} + +func (x *UploadLibraryFileRequest) GetDescription() string { + if x != nil { + return x.Description + } + return "" +} + +func (x *UploadLibraryFileRequest) GetData() []byte { + if x != nil { + return x.Data + } + return nil +} + +func (x *UploadLibraryFileRequest) GetFileName() string { + if x != nil { + return x.FileName + } + return "" +} + +func (x *UploadLibraryFileRequest) GetFileType() string { + if x != nil { + return x.FileType + } + return "" +} + +type UploadLibraryFileResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + LibraryFileId int32 `protobuf:"varint,1,opt,name=library_file_id,json=libraryFileId,proto3" json:"library_file_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *UploadLibraryFileResponse) Reset() { + *x = UploadLibraryFileResponse{} + mi := &file_cloudprint_proto_msgTypes[50] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *UploadLibraryFileResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UploadLibraryFileResponse) ProtoMessage() {} + +func (x *UploadLibraryFileResponse) ProtoReflect() protoreflect.Message { + mi := &file_cloudprint_proto_msgTypes[50] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use UploadLibraryFileResponse.ProtoReflect.Descriptor instead. +func (*UploadLibraryFileResponse) Descriptor() ([]byte, []int) { + return file_cloudprint_proto_rawDescGZIP(), []int{50} +} + +func (x *UploadLibraryFileResponse) GetLibraryFileId() int32 { + if x != nil { + return x.LibraryFileId + } + return 0 +} + +type DeleteLibraryFileRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + LibraryFileId int32 `protobuf:"varint,1,opt,name=library_file_id,json=libraryFileId,proto3" json:"library_file_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *DeleteLibraryFileRequest) Reset() { + *x = DeleteLibraryFileRequest{} + mi := &file_cloudprint_proto_msgTypes[51] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *DeleteLibraryFileRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DeleteLibraryFileRequest) ProtoMessage() {} + +func (x *DeleteLibraryFileRequest) ProtoReflect() protoreflect.Message { + mi := &file_cloudprint_proto_msgTypes[51] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DeleteLibraryFileRequest.ProtoReflect.Descriptor instead. +func (*DeleteLibraryFileRequest) Descriptor() ([]byte, []int) { + return file_cloudprint_proto_rawDescGZIP(), []int{51} +} + +func (x *DeleteLibraryFileRequest) GetLibraryFileId() int32 { + if x != nil { + return x.LibraryFileId + } + return 0 +} + +type PriceItem struct { + state protoimpl.MessageState `protogen:"open.v1"` + Id int32 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"` + Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` + Type string `protobuf:"bytes,3,opt,name=type,proto3" json:"type,omitempty"` + Price float64 `protobuf:"fixed64,4,opt,name=price,proto3" json:"price,omitempty"` + Unit string `protobuf:"bytes,5,opt,name=unit,proto3" json:"unit,omitempty"` + ColorEnabled bool `protobuf:"varint,6,opt,name=color_enabled,json=colorEnabled,proto3" json:"color_enabled,omitempty"` + IsActive bool `protobuf:"varint,7,opt,name=is_active,json=isActive,proto3" json:"is_active,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *PriceItem) Reset() { + *x = PriceItem{} + mi := &file_cloudprint_proto_msgTypes[52] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *PriceItem) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PriceItem) ProtoMessage() {} + +func (x *PriceItem) ProtoReflect() protoreflect.Message { + mi := &file_cloudprint_proto_msgTypes[52] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PriceItem.ProtoReflect.Descriptor instead. +func (*PriceItem) Descriptor() ([]byte, []int) { + return file_cloudprint_proto_rawDescGZIP(), []int{52} +} + +func (x *PriceItem) GetId() int32 { + if x != nil { + return x.Id + } + return 0 +} + +func (x *PriceItem) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *PriceItem) GetType() string { + if x != nil { + return x.Type + } + return "" +} + +func (x *PriceItem) GetPrice() float64 { + if x != nil { + return x.Price + } + return 0 +} + +func (x *PriceItem) GetUnit() string { + if x != nil { + return x.Unit + } + return "" +} + +func (x *PriceItem) GetColorEnabled() bool { + if x != nil { + return x.ColorEnabled + } + return false +} + +func (x *PriceItem) GetIsActive() bool { + if x != nil { + return x.IsActive + } + return false +} + +type GetPriceListRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetPriceListRequest) Reset() { + *x = GetPriceListRequest{} + mi := &file_cloudprint_proto_msgTypes[53] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetPriceListRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetPriceListRequest) ProtoMessage() {} + +func (x *GetPriceListRequest) ProtoReflect() protoreflect.Message { + mi := &file_cloudprint_proto_msgTypes[53] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetPriceListRequest.ProtoReflect.Descriptor instead. +func (*GetPriceListRequest) Descriptor() ([]byte, []int) { + return file_cloudprint_proto_rawDescGZIP(), []int{53} +} + +type PriceListResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Items []*PriceItem `protobuf:"bytes,1,rep,name=items,proto3" json:"items,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *PriceListResponse) Reset() { + *x = PriceListResponse{} + mi := &file_cloudprint_proto_msgTypes[54] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *PriceListResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PriceListResponse) ProtoMessage() {} + +func (x *PriceListResponse) ProtoReflect() protoreflect.Message { + mi := &file_cloudprint_proto_msgTypes[54] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PriceListResponse.ProtoReflect.Descriptor instead. +func (*PriceListResponse) Descriptor() ([]byte, []int) { + return file_cloudprint_proto_rawDescGZIP(), []int{54} +} + +func (x *PriceListResponse) GetItems() []*PriceItem { + if x != nil { + return x.Items + } + return nil +} + +type CreatePriceItemRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + Type string `protobuf:"bytes,2,opt,name=type,proto3" json:"type,omitempty"` + Price float64 `protobuf:"fixed64,3,opt,name=price,proto3" json:"price,omitempty"` + Unit string `protobuf:"bytes,4,opt,name=unit,proto3" json:"unit,omitempty"` + ColorEnabled bool `protobuf:"varint,5,opt,name=color_enabled,json=colorEnabled,proto3" json:"color_enabled,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *CreatePriceItemRequest) Reset() { + *x = CreatePriceItemRequest{} + mi := &file_cloudprint_proto_msgTypes[55] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *CreatePriceItemRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CreatePriceItemRequest) ProtoMessage() {} + +func (x *CreatePriceItemRequest) ProtoReflect() protoreflect.Message { + mi := &file_cloudprint_proto_msgTypes[55] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CreatePriceItemRequest.ProtoReflect.Descriptor instead. +func (*CreatePriceItemRequest) Descriptor() ([]byte, []int) { + return file_cloudprint_proto_rawDescGZIP(), []int{55} +} + +func (x *CreatePriceItemRequest) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *CreatePriceItemRequest) GetType() string { + if x != nil { + return x.Type + } + return "" +} + +func (x *CreatePriceItemRequest) GetPrice() float64 { + if x != nil { + return x.Price + } + return 0 +} + +func (x *CreatePriceItemRequest) GetUnit() string { + if x != nil { + return x.Unit + } + return "" +} + +func (x *CreatePriceItemRequest) GetColorEnabled() bool { + if x != nil { + return x.ColorEnabled + } + return false +} + +type UpdatePriceItemRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + Id int32 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"` + Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` + Type string `protobuf:"bytes,3,opt,name=type,proto3" json:"type,omitempty"` + Price float64 `protobuf:"fixed64,4,opt,name=price,proto3" json:"price,omitempty"` + Unit string `protobuf:"bytes,5,opt,name=unit,proto3" json:"unit,omitempty"` + ColorEnabled bool `protobuf:"varint,6,opt,name=color_enabled,json=colorEnabled,proto3" json:"color_enabled,omitempty"` + IsActive bool `protobuf:"varint,7,opt,name=is_active,json=isActive,proto3" json:"is_active,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *UpdatePriceItemRequest) Reset() { + *x = UpdatePriceItemRequest{} + mi := &file_cloudprint_proto_msgTypes[56] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *UpdatePriceItemRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UpdatePriceItemRequest) ProtoMessage() {} + +func (x *UpdatePriceItemRequest) ProtoReflect() protoreflect.Message { + mi := &file_cloudprint_proto_msgTypes[56] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use UpdatePriceItemRequest.ProtoReflect.Descriptor instead. +func (*UpdatePriceItemRequest) Descriptor() ([]byte, []int) { + return file_cloudprint_proto_rawDescGZIP(), []int{56} +} + +func (x *UpdatePriceItemRequest) GetId() int32 { + if x != nil { + return x.Id + } + return 0 +} + +func (x *UpdatePriceItemRequest) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *UpdatePriceItemRequest) GetType() string { + if x != nil { + return x.Type + } + return "" +} + +func (x *UpdatePriceItemRequest) GetPrice() float64 { + if x != nil { + return x.Price + } + return 0 +} + +func (x *UpdatePriceItemRequest) GetUnit() string { + if x != nil { + return x.Unit + } + return "" +} + +func (x *UpdatePriceItemRequest) GetColorEnabled() bool { + if x != nil { + return x.ColorEnabled + } + return false +} + +func (x *UpdatePriceItemRequest) GetIsActive() bool { + if x != nil { + return x.IsActive + } + return false +} + +type WxPayRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + OrderNo string `protobuf:"bytes,1,opt,name=order_no,json=orderNo,proto3" json:"order_no,omitempty"` + Amount float64 `protobuf:"fixed64,2,opt,name=amount,proto3" json:"amount,omitempty"` + Description string `protobuf:"bytes,3,opt,name=description,proto3" json:"description,omitempty"` + Openid string `protobuf:"bytes,4,opt,name=openid,proto3" json:"openid,omitempty"` + ClientIp string `protobuf:"bytes,5,opt,name=client_ip,json=clientIp,proto3" json:"client_ip,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *WxPayRequest) Reset() { + *x = WxPayRequest{} + mi := &file_cloudprint_proto_msgTypes[57] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *WxPayRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*WxPayRequest) ProtoMessage() {} + +func (x *WxPayRequest) ProtoReflect() protoreflect.Message { + mi := &file_cloudprint_proto_msgTypes[57] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use WxPayRequest.ProtoReflect.Descriptor instead. +func (*WxPayRequest) Descriptor() ([]byte, []int) { + return file_cloudprint_proto_rawDescGZIP(), []int{57} +} + +func (x *WxPayRequest) GetOrderNo() string { + if x != nil { + return x.OrderNo + } + return "" +} + +func (x *WxPayRequest) GetAmount() float64 { + if x != nil { + return x.Amount + } + return 0 +} + +func (x *WxPayRequest) GetDescription() string { + if x != nil { + return x.Description + } + return "" +} + +func (x *WxPayRequest) GetOpenid() string { + if x != nil { + return x.Openid + } + return "" +} + +func (x *WxPayRequest) GetClientIp() string { + if x != nil { + return x.ClientIp + } + return "" +} + +type WxPayResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + PrepayId string `protobuf:"bytes,1,opt,name=prepay_id,json=prepayId,proto3" json:"prepay_id,omitempty"` + CodeUrl string `protobuf:"bytes,2,opt,name=code_url,json=codeUrl,proto3" json:"code_url,omitempty"` + MwebUrl string `protobuf:"bytes,3,opt,name=mweb_url,json=mwebUrl,proto3" json:"mweb_url,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *WxPayResponse) Reset() { + *x = WxPayResponse{} + mi := &file_cloudprint_proto_msgTypes[58] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *WxPayResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*WxPayResponse) ProtoMessage() {} + +func (x *WxPayResponse) ProtoReflect() protoreflect.Message { + mi := &file_cloudprint_proto_msgTypes[58] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use WxPayResponse.ProtoReflect.Descriptor instead. +func (*WxPayResponse) Descriptor() ([]byte, []int) { + return file_cloudprint_proto_rawDescGZIP(), []int{58} +} + +func (x *WxPayResponse) GetPrepayId() string { + if x != nil { + return x.PrepayId + } + return "" +} + +func (x *WxPayResponse) GetCodeUrl() string { + if x != nil { + return x.CodeUrl + } + return "" +} + +func (x *WxPayResponse) GetMwebUrl() string { + if x != nil { + return x.MwebUrl + } + return "" +} + +type QueryPayStatusRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + OrderNo string `protobuf:"bytes,1,opt,name=order_no,json=orderNo,proto3" json:"order_no,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *QueryPayStatusRequest) Reset() { + *x = QueryPayStatusRequest{} + mi := &file_cloudprint_proto_msgTypes[59] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *QueryPayStatusRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*QueryPayStatusRequest) ProtoMessage() {} + +func (x *QueryPayStatusRequest) ProtoReflect() protoreflect.Message { + mi := &file_cloudprint_proto_msgTypes[59] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use QueryPayStatusRequest.ProtoReflect.Descriptor instead. +func (*QueryPayStatusRequest) Descriptor() ([]byte, []int) { + return file_cloudprint_proto_rawDescGZIP(), []int{59} +} + +func (x *QueryPayStatusRequest) GetOrderNo() string { + if x != nil { + return x.OrderNo + } + return "" +} + +type PayStatusResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Status int32 `protobuf:"varint,1,opt,name=status,proto3" json:"status,omitempty"` // 0: 待支付 1: 支付中 2: 成功 3: 失败 + TransactionId string `protobuf:"bytes,2,opt,name=transaction_id,json=transactionId,proto3" json:"transaction_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *PayStatusResponse) Reset() { + *x = PayStatusResponse{} + mi := &file_cloudprint_proto_msgTypes[60] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *PayStatusResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PayStatusResponse) ProtoMessage() {} + +func (x *PayStatusResponse) ProtoReflect() protoreflect.Message { + mi := &file_cloudprint_proto_msgTypes[60] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PayStatusResponse.ProtoReflect.Descriptor instead. +func (*PayStatusResponse) Descriptor() ([]byte, []int) { + return file_cloudprint_proto_rawDescGZIP(), []int{60} +} + +func (x *PayStatusResponse) GetStatus() int32 { + if x != nil { + return x.Status + } + return 0 +} + +func (x *PayStatusResponse) GetTransactionId() string { + if x != nil { + return x.TransactionId + } + return "" +} + +type PayCallbackRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + Body string `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *PayCallbackRequest) Reset() { + *x = PayCallbackRequest{} + mi := &file_cloudprint_proto_msgTypes[61] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *PayCallbackRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PayCallbackRequest) ProtoMessage() {} + +func (x *PayCallbackRequest) ProtoReflect() protoreflect.Message { + mi := &file_cloudprint_proto_msgTypes[61] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PayCallbackRequest.ProtoReflect.Descriptor instead. +func (*PayCallbackRequest) Descriptor() ([]byte, []int) { + return file_cloudprint_proto_rawDescGZIP(), []int{61} +} + +func (x *PayCallbackRequest) GetBody() string { + if x != nil { + return x.Body + } + return "" +} + +type PayCallbackResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + ReturnCode string `protobuf:"bytes,1,opt,name=return_code,json=returnCode,proto3" json:"return_code,omitempty"` + ReturnMsg string `protobuf:"bytes,2,opt,name=return_msg,json=returnMsg,proto3" json:"return_msg,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *PayCallbackResponse) Reset() { + *x = PayCallbackResponse{} + mi := &file_cloudprint_proto_msgTypes[62] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *PayCallbackResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PayCallbackResponse) ProtoMessage() {} + +func (x *PayCallbackResponse) ProtoReflect() protoreflect.Message { + mi := &file_cloudprint_proto_msgTypes[62] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PayCallbackResponse.ProtoReflect.Descriptor instead. +func (*PayCallbackResponse) Descriptor() ([]byte, []int) { + return file_cloudprint_proto_rawDescGZIP(), []int{62} +} + +func (x *PayCallbackResponse) GetReturnCode() string { + if x != nil { + return x.ReturnCode + } + return "" +} + +func (x *PayCallbackResponse) GetReturnMsg() string { + if x != nil { + return x.ReturnMsg + } + return "" +} + +type PayByBalanceRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + OrderNo string `protobuf:"bytes,1,opt,name=order_no,json=orderNo,proto3" json:"order_no,omitempty"` + UserId int32 `protobuf:"varint,2,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *PayByBalanceRequest) Reset() { + *x = PayByBalanceRequest{} + mi := &file_cloudprint_proto_msgTypes[63] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *PayByBalanceRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PayByBalanceRequest) ProtoMessage() {} + +func (x *PayByBalanceRequest) ProtoReflect() protoreflect.Message { + mi := &file_cloudprint_proto_msgTypes[63] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PayByBalanceRequest.ProtoReflect.Descriptor instead. +func (*PayByBalanceRequest) Descriptor() ([]byte, []int) { + return file_cloudprint_proto_rawDescGZIP(), []int{63} +} + +func (x *PayByBalanceRequest) GetOrderNo() string { + if x != nil { + return x.OrderNo + } + return "" +} + +func (x *PayByBalanceRequest) GetUserId() int32 { + if x != nil { + return x.UserId + } + return 0 +} + +type Admin struct { + state protoimpl.MessageState `protogen:"open.v1"` + Id int32 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"` + Username string `protobuf:"bytes,2,opt,name=username,proto3" json:"username,omitempty"` + Nickname string `protobuf:"bytes,3,opt,name=nickname,proto3" json:"nickname,omitempty"` + Role int32 `protobuf:"varint,4,opt,name=role,proto3" json:"role,omitempty"` + CreatedAt *timestamppb.Timestamp `protobuf:"bytes,5,opt,name=created_at,json=createdAt,proto3" json:"created_at,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *Admin) Reset() { + *x = Admin{} + mi := &file_cloudprint_proto_msgTypes[64] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *Admin) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Admin) ProtoMessage() {} + +func (x *Admin) ProtoReflect() protoreflect.Message { + mi := &file_cloudprint_proto_msgTypes[64] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Admin.ProtoReflect.Descriptor instead. +func (*Admin) Descriptor() ([]byte, []int) { + return file_cloudprint_proto_rawDescGZIP(), []int{64} +} + +func (x *Admin) GetId() int32 { + if x != nil { + return x.Id + } + return 0 +} + +func (x *Admin) GetUsername() string { + if x != nil { + return x.Username + } + return "" +} + +func (x *Admin) GetNickname() string { + if x != nil { + return x.Nickname + } + return "" +} + +func (x *Admin) GetRole() int32 { + if x != nil { + return x.Role + } + return 0 +} + +func (x *Admin) GetCreatedAt() *timestamppb.Timestamp { + if x != nil { + return x.CreatedAt + } + return nil +} + +type AdminLoginRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + Username string `protobuf:"bytes,1,opt,name=username,proto3" json:"username,omitempty"` + Password string `protobuf:"bytes,2,opt,name=password,proto3" json:"password,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *AdminLoginRequest) Reset() { + *x = AdminLoginRequest{} + mi := &file_cloudprint_proto_msgTypes[65] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *AdminLoginRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AdminLoginRequest) ProtoMessage() {} + +func (x *AdminLoginRequest) ProtoReflect() protoreflect.Message { + mi := &file_cloudprint_proto_msgTypes[65] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use AdminLoginRequest.ProtoReflect.Descriptor instead. +func (*AdminLoginRequest) Descriptor() ([]byte, []int) { + return file_cloudprint_proto_rawDescGZIP(), []int{65} +} + +func (x *AdminLoginRequest) GetUsername() string { + if x != nil { + return x.Username + } + return "" +} + +func (x *AdminLoginRequest) GetPassword() string { + if x != nil { + return x.Password + } + return "" +} + +type AdminLoginResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + AccessToken string `protobuf:"bytes,1,opt,name=access_token,json=accessToken,proto3" json:"access_token,omitempty"` + Admin *Admin `protobuf:"bytes,2,opt,name=admin,proto3" json:"admin,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *AdminLoginResponse) Reset() { + *x = AdminLoginResponse{} + mi := &file_cloudprint_proto_msgTypes[66] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *AdminLoginResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AdminLoginResponse) ProtoMessage() {} + +func (x *AdminLoginResponse) ProtoReflect() protoreflect.Message { + mi := &file_cloudprint_proto_msgTypes[66] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use AdminLoginResponse.ProtoReflect.Descriptor instead. +func (*AdminLoginResponse) Descriptor() ([]byte, []int) { + return file_cloudprint_proto_rawDescGZIP(), []int{66} +} + +func (x *AdminLoginResponse) GetAccessToken() string { + if x != nil { + return x.AccessToken + } + return "" +} + +func (x *AdminLoginResponse) GetAdmin() *Admin { + if x != nil { + return x.Admin + } + return nil +} + +type GetStatisticsRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetStatisticsRequest) Reset() { + *x = GetStatisticsRequest{} + mi := &file_cloudprint_proto_msgTypes[67] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetStatisticsRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetStatisticsRequest) ProtoMessage() {} + +func (x *GetStatisticsRequest) ProtoReflect() protoreflect.Message { + mi := &file_cloudprint_proto_msgTypes[67] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetStatisticsRequest.ProtoReflect.Descriptor instead. +func (*GetStatisticsRequest) Descriptor() ([]byte, []int) { + return file_cloudprint_proto_rawDescGZIP(), []int{67} +} + +type Statistics struct { + state protoimpl.MessageState `protogen:"open.v1"` + TotalUsers int32 `protobuf:"varint,1,opt,name=total_users,json=totalUsers,proto3" json:"total_users,omitempty"` + TotalOrders int32 `protobuf:"varint,2,opt,name=total_orders,json=totalOrders,proto3" json:"total_orders,omitempty"` + TodayOrders int32 `protobuf:"varint,3,opt,name=today_orders,json=todayOrders,proto3" json:"today_orders,omitempty"` + TodayRevenue float64 `protobuf:"fixed64,4,opt,name=today_revenue,json=todayRevenue,proto3" json:"today_revenue,omitempty"` + PendingOrders int32 `protobuf:"varint,5,opt,name=pending_orders,json=pendingOrders,proto3" json:"pending_orders,omitempty"` + ActivePrinters int32 `protobuf:"varint,6,opt,name=active_printers,json=activePrinters,proto3" json:"active_printers,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *Statistics) Reset() { + *x = Statistics{} + mi := &file_cloudprint_proto_msgTypes[68] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *Statistics) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Statistics) ProtoMessage() {} + +func (x *Statistics) ProtoReflect() protoreflect.Message { + mi := &file_cloudprint_proto_msgTypes[68] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Statistics.ProtoReflect.Descriptor instead. +func (*Statistics) Descriptor() ([]byte, []int) { + return file_cloudprint_proto_rawDescGZIP(), []int{68} +} + +func (x *Statistics) GetTotalUsers() int32 { + if x != nil { + return x.TotalUsers + } + return 0 +} + +func (x *Statistics) GetTotalOrders() int32 { + if x != nil { + return x.TotalOrders + } + return 0 +} + +func (x *Statistics) GetTodayOrders() int32 { + if x != nil { + return x.TodayOrders + } + return 0 +} + +func (x *Statistics) GetTodayRevenue() float64 { + if x != nil { + return x.TodayRevenue + } + return 0 +} + +func (x *Statistics) GetPendingOrders() int32 { + if x != nil { + return x.PendingOrders + } + return 0 +} + +func (x *Statistics) GetActivePrinters() int32 { + if x != nil { + return x.ActivePrinters + } + return 0 +} + +var File_cloudprint_proto protoreflect.FileDescriptor + +const file_cloudprint_proto_rawDesc = "" + + "\n" + + "\x10cloudprint.proto\x12\n" + + "cloudprint\x1a\x1bgoogle/protobuf/empty.proto\x1a\x1fgoogle/protobuf/timestamp.proto\"\a\n" + + "\x05Empty\">\n" + + "\x0eStatusResponse\x12\x12\n" + + "\x04code\x18\x01 \x01(\x05R\x04code\x12\x18\n" + + "\amessage\x18\x02 \x01(\tR\amessage\"\xb7\x01\n" + + "\x04User\x12\x0e\n" + + "\x02id\x18\x01 \x01(\x05R\x02id\x12\x16\n" + + "\x06openid\x18\x02 \x01(\tR\x06openid\x12\x1a\n" + + "\bnickname\x18\x03 \x01(\tR\bnickname\x12\x16\n" + + "\x06avatar\x18\x04 \x01(\tR\x06avatar\x12\x18\n" + + "\abalance\x18\x05 \x01(\x01R\abalance\x129\n" + + "\n" + + "created_at\x18\x06 \x01(\v2\x1a.google.protobuf.TimestampR\tcreatedAt\"\"\n" + + "\fLoginRequest\x12\x12\n" + + "\x04code\x18\x01 \x01(\tR\x04code\"}\n" + + "\rLoginResponse\x12!\n" + + "\faccess_token\x18\x01 \x01(\tR\vaccessToken\x12#\n" + + "\rrefresh_token\x18\x02 \x01(\tR\frefreshToken\x12$\n" + + "\x04user\x18\x03 \x01(\v2\x10.cloudprint.UserR\x04user\"5\n" + + "\x0eRefreshRequest\x12#\n" + + "\rrefresh_token\x18\x01 \x01(\tR\frefreshToken\"4\n" + + "\x0fRefreshResponse\x12!\n" + + "\faccess_token\x18\x01 \x01(\tR\vaccessToken\"\x14\n" + + "\x12GetUserInfoRequest\"G\n" + + "\x11UpdateUserRequest\x12\x1a\n" + + "\bnickname\x18\x01 \x01(\tR\bnickname\x12\x16\n" + + "\x06avatar\x18\x02 \x01(\tR\x06avatar\"\x8f\x02\n" + + "\bFileInfo\x12\x0e\n" + + "\x02id\x18\x01 \x01(\x05R\x02id\x12\x1b\n" + + "\tfile_name\x18\x02 \x01(\tR\bfileName\x12\x1b\n" + + "\tfile_path\x18\x03 \x01(\tR\bfilePath\x12\x1b\n" + + "\tfile_type\x18\x04 \x01(\tR\bfileType\x12\x1b\n" + + "\tfile_size\x18\x05 \x01(\x03R\bfileSize\x12#\n" + + "\ruploader_type\x18\x06 \x01(\tR\fuploaderType\x12\x1f\n" + + "\vuploader_id\x18\a \x01(\x05R\n" + + "uploaderId\x129\n" + + "\n" + + "created_at\x18\b \x01(\v2\x1a.google.protobuf.TimestampR\tcreatedAt\"\xfd\x01\n" + + "\rUploadRequest\x12\x1b\n" + + "\tfile_name\x18\x01 \x01(\tR\bfileName\x12\x1b\n" + + "\tfile_type\x18\x02 \x01(\tR\bfileType\x12\x1b\n" + + "\tfile_size\x18\x03 \x01(\x03R\bfileSize\x12\x12\n" + + "\x04data\x18\x04 \x01(\fR\x04data\x12\"\n" + + "\ris_last_chunk\x18\x05 \x01(\bR\visLastChunk\x12\x19\n" + + "\bchunk_id\x18\x06 \x01(\tR\achunkId\x12\x1f\n" + + "\vchunk_index\x18\a \x01(\x05R\n" + + "chunkIndex\x12!\n" + + "\ftotal_chunks\x18\b \x01(\x05R\vtotalChunks\"a\n" + + "\x0eUploadResponse\x12\x17\n" + + "\afile_id\x18\x01 \x01(\x05R\x06fileId\x12\x1b\n" + + "\tfile_path\x18\x02 \x01(\tR\bfilePath\x12\x19\n" + + "\bfile_url\x18\x03 \x01(\tR\afileUrl\")\n" + + "\x0eGetFileRequest\x12\x17\n" + + "\afile_id\x18\x01 \x01(\x05R\x06fileId\"7\n" + + "\bFileData\x12\x12\n" + + "\x04data\x18\x01 \x01(\fR\x04data\x12\x17\n" + + "\ais_last\x18\x02 \x01(\bR\x06isLast\",\n" + + "\x11DeleteFileRequest\x12\x17\n" + + "\afile_id\x18\x01 \x01(\x05R\x06fileId\"\x92\x01\n" + + "\x10WatermarkRequest\x12\x17\n" + + "\afile_id\x18\x01 \x01(\x05R\x06fileId\x12\x12\n" + + "\x04text\x18\x02 \x01(\tR\x04text\x12\x18\n" + + "\aopacity\x18\x03 \x01(\x02R\aopacity\x12\x1a\n" + + "\bposition\x18\x04 \x01(\x05R\bposition\x12\x1b\n" + + "\tfont_size\x18\x05 \x01(\x05R\bfontSize\"I\n" + + "\x11WatermarkResponse\x12\x17\n" + + "\afile_id\x18\x01 \x01(\x05R\x06fileId\x12\x1b\n" + + "\tfile_path\x18\x02 \x01(\tR\bfilePath\"\x8b\x01\n" + + "\x12GetFileListRequest\x12#\n" + + "\ruploader_type\x18\x01 \x01(\tR\fuploaderType\x12\x1f\n" + + "\vuploader_id\x18\x02 \x01(\x05R\n" + + "uploaderId\x12\x12\n" + + "\x04page\x18\x03 \x01(\x05R\x04page\x12\x1b\n" + + "\tpage_size\x18\x04 \x01(\x05R\bpageSize\"T\n" + + "\x10FileListResponse\x12*\n" + + "\x05files\x18\x01 \x03(\v2\x14.cloudprint.FileInfoR\x05files\x12\x14\n" + + "\x05total\x18\x02 \x01(\x05R\x05total\"\xbb\x02\n" + + "\x05Order\x12\x0e\n" + + "\x02id\x18\x01 \x01(\x05R\x02id\x12\x19\n" + + "\border_no\x18\x02 \x01(\tR\aorderNo\x12\x17\n" + + "\auser_id\x18\x03 \x01(\x05R\x06userId\x12\x16\n" + + "\x06status\x18\x04 \x01(\x05R\x06status\x12!\n" + + "\ftotal_amount\x18\x05 \x01(\x01R\vtotalAmount\x12\x16\n" + + "\x06remark\x18\x06 \x01(\tR\x06remark\x129\n" + + "\n" + + "created_at\x18\a \x01(\v2\x1a.google.protobuf.TimestampR\tcreatedAt\x123\n" + + "\apaid_at\x18\b \x01(\v2\x1a.google.protobuf.TimestampR\x06paidAt\x12+\n" + + "\x05items\x18\t \x03(\v2\x15.cloudprint.OrderItemR\x05items\"\x93\x02\n" + + "\tOrderItem\x12\x0e\n" + + "\x02id\x18\x01 \x01(\x05R\x02id\x12\x19\n" + + "\border_id\x18\x02 \x01(\x05R\aorderId\x12\x17\n" + + "\afile_id\x18\x03 \x01(\x05R\x06fileId\x12(\n" + + "\x04file\x18\x04 \x01(\v2\x14.cloudprint.FileInfoR\x04file\x12\x1d\n" + + "\n" + + "printer_id\x18\x05 \x01(\x05R\tprinterId\x12\x16\n" + + "\x06copies\x18\x06 \x01(\x05R\x06copies\x12\x14\n" + + "\x05color\x18\a \x01(\bR\x05color\x12\x16\n" + + "\x06duplex\x18\b \x01(\bR\x06duplex\x12\x1d\n" + + "\n" + + "page_range\x18\t \x01(\tR\tpageRange\x12\x14\n" + + "\x05price\x18\n" + + " \x01(\x01R\x05price\"_\n" + + "\x12CreateOrderRequest\x121\n" + + "\x05items\x18\x01 \x03(\v2\x1b.cloudprint.CreateOrderItemR\x05items\x12\x16\n" + + "\x06remark\x18\x02 \x01(\tR\x06remark\"\xae\x01\n" + + "\x0fCreateOrderItem\x12\x17\n" + + "\afile_id\x18\x01 \x01(\x05R\x06fileId\x12\x1d\n" + + "\n" + + "printer_id\x18\x02 \x01(\x05R\tprinterId\x12\x16\n" + + "\x06copies\x18\x03 \x01(\x05R\x06copies\x12\x14\n" + + "\x05color\x18\x04 \x01(\bR\x05color\x12\x16\n" + + "\x06duplex\x18\x05 \x01(\bR\x06duplex\x12\x1d\n" + + "\n" + + "page_range\x18\x06 \x01(\tR\tpageRange\"S\n" + + "\x13CreateOrderResponse\x12\x19\n" + + "\border_no\x18\x01 \x01(\tR\aorderNo\x12!\n" + + "\ftotal_amount\x18\x02 \x01(\x01R\vtotalAmount\",\n" + + "\x0fGetOrderRequest\x12\x19\n" + + "\border_no\x18\x01 \x01(\tR\aorderNo\"w\n" + + "\x13GetOrderListRequest\x12\x17\n" + + "\auser_id\x18\x01 \x01(\x05R\x06userId\x12\x16\n" + + "\x06status\x18\x02 \x01(\x05R\x06status\x12\x12\n" + + "\x04page\x18\x03 \x01(\x05R\x04page\x12\x1b\n" + + "\tpage_size\x18\x04 \x01(\x05R\bpageSize\"T\n" + + "\x11OrderListResponse\x12)\n" + + "\x06orders\x18\x01 \x03(\v2\x11.cloudprint.OrderR\x06orders\x12\x14\n" + + "\x05total\x18\x02 \x01(\x05R\x05total\"M\n" + + "\x18UpdateOrderStatusRequest\x12\x19\n" + + "\border_no\x18\x01 \x01(\tR\aorderNo\x12\x16\n" + + "\x06status\x18\x02 \x01(\x05R\x06status\"/\n" + + "\x12CancelOrderRequest\x12\x19\n" + + "\border_no\x18\x01 \x01(\tR\aorderNo\"\xc8\x01\n" + + "\aPrinter\x12\x0e\n" + + "\x02id\x18\x01 \x01(\x05R\x02id\x12\x12\n" + + "\x04name\x18\x02 \x01(\tR\x04name\x12!\n" + + "\fdisplay_name\x18\x03 \x01(\tR\vdisplayName\x12\x1b\n" + + "\tis_active\x18\x04 \x01(\bR\bisActive\x12\x16\n" + + "\x06status\x18\x05 \x01(\x05R\x06status\x12A\n" + + "\x0elast_heartbeat\x18\x06 \x01(\v2\x1a.google.protobuf.TimestampR\rlastHeartbeat\"\x14\n" + + "\x12GetPrintersRequest\"F\n" + + "\x13PrinterListResponse\x12/\n" + + "\bprinters\x18\x01 \x03(\v2\x13.cloudprint.PrinterR\bprinters\"8\n" + + "\x17GetPrinterStatusRequest\x12\x1d\n" + + "\n" + + "printer_id\x18\x01 \x01(\x05R\tprinterId\"g\n" + + "\x15PrinterStatusResponse\x12-\n" + + "\aprinter\x18\x01 \x01(\v2\x13.cloudprint.PrinterR\aprinter\x12\x1f\n" + + "\vqueue_count\x18\x02 \x01(\x05R\n" + + "queueCount\"h\n" + + "\x16RegisterPrinterRequest\x12\x12\n" + + "\x04name\x18\x01 \x01(\tR\x04name\x12!\n" + + "\fdisplay_name\x18\x02 \x01(\tR\vdisplayName\x12\x17\n" + + "\aapi_key\x18\x03 \x01(\tR\x06apiKey\"N\n" + + "\x17RegisterPrinterResponse\x12\x1d\n" + + "\n" + + "printer_id\x18\x01 \x01(\x05R\tprinterId\x12\x14\n" + + "\x05token\x18\x02 \x01(\tR\x05token\"f\n" + + "\x17PrinterHeartbeatRequest\x12\x1d\n" + + "\n" + + "printer_id\x18\x01 \x01(\x05R\tprinterId\x12\x16\n" + + "\x06status\x18\x02 \x01(\x05R\x06status\x12\x14\n" + + "\x05token\x18\x03 \x01(\tR\x05token\"\xf5\x02\n" + + "\bPrintJob\x12\x0e\n" + + "\x02id\x18\x01 \x01(\x05R\x02id\x12\x15\n" + + "\x06job_no\x18\x02 \x01(\tR\x05jobNo\x12\x1d\n" + + "\n" + + "printer_id\x18\x03 \x01(\x05R\tprinterId\x12\"\n" + + "\rorder_item_id\x18\x04 \x01(\x05R\vorderItemId\x12\x16\n" + + "\x06status\x18\x05 \x01(\tR\x06status\x12\x1a\n" + + "\bprogress\x18\x06 \x01(\x05R\bprogress\x12\x1b\n" + + "\terror_msg\x18\a \x01(\tR\berrorMsg\x129\n" + + "\n" + + "started_at\x18\b \x01(\v2\x1a.google.protobuf.TimestampR\tstartedAt\x12=\n" + + "\fcompleted_at\x18\t \x01(\v2\x1a.google.protobuf.TimestampR\vcompletedAt\x124\n" + + "\n" + + "order_item\x18\n" + + " \x01(\v2\x15.cloudprint.OrderItemR\torderItem\"\xdc\x01\n" + + "\x15SubmitPrintJobRequest\x12\"\n" + + "\rorder_item_id\x18\x01 \x01(\x05R\vorderItemId\x12\x1d\n" + + "\n" + + "printer_id\x18\x02 \x01(\x05R\tprinterId\x12\x1b\n" + + "\tfile_path\x18\x03 \x01(\tR\bfilePath\x12\x16\n" + + "\x06copies\x18\x04 \x01(\x05R\x06copies\x12\x14\n" + + "\x05color\x18\x05 \x01(\bR\x05color\x12\x16\n" + + "\x06duplex\x18\x06 \x01(\bR\x06duplex\x12\x1d\n" + + "\n" + + "page_range\x18\a \x01(\tR\tpageRange\"/\n" + + "\x16SubmitPrintJobResponse\x12\x15\n" + + "\x06job_no\x18\x01 \x01(\tR\x05jobNo\".\n" + + "\x15CancelPrintJobRequest\x12\x15\n" + + "\x06job_no\x18\x01 \x01(\tR\x05jobNo\"K\n" + + "\x14SubscribeJobsRequest\x12\x1d\n" + + "\n" + + "printer_id\x18\x01 \x01(\x05R\tprinterId\x12\x14\n" + + "\x05token\x18\x02 \x01(\tR\x05token\"\x80\x01\n" + + "\x16ReportJobStatusRequest\x12\x15\n" + + "\x06job_no\x18\x01 \x01(\tR\x05jobNo\x12\x16\n" + + "\x06status\x18\x02 \x01(\tR\x06status\x12\x1a\n" + + "\bprogress\x18\x03 \x01(\x05R\bprogress\x12\x1b\n" + + "\terror_msg\x18\x04 \x01(\tR\berrorMsg\"h\n" + + "\x0fLibraryCategory\x12\x0e\n" + + "\x02id\x18\x01 \x01(\x05R\x02id\x12\x12\n" + + "\x04name\x18\x02 \x01(\tR\x04name\x12\x12\n" + + "\x04icon\x18\x03 \x01(\tR\x04icon\x12\x1d\n" + + "\n" + + "sort_order\x18\x04 \x01(\x05R\tsortOrder\"\xba\x02\n" + + "\vLibraryFile\x12\x0e\n" + + "\x02id\x18\x01 \x01(\x05R\x02id\x12\x1f\n" + + "\vcategory_id\x18\x02 \x01(\x05R\n" + + "categoryId\x12\x17\n" + + "\afile_id\x18\x03 \x01(\x05R\x06fileId\x12\x14\n" + + "\x05title\x18\x04 \x01(\tR\x05title\x12 \n" + + "\vdescription\x18\x05 \x01(\tR\vdescription\x12\x1d\n" + + "\n" + + "page_count\x18\x06 \x01(\x05R\tpageCount\x12%\n" + + "\x0edownload_count\x18\a \x01(\x05R\rdownloadCount\x12(\n" + + "\x04file\x18\b \x01(\v2\x14.cloudprint.FileInfoR\x04file\x129\n" + + "\n" + + "created_at\x18\t \x01(\v2\x1a.google.protobuf.TimestampR\tcreatedAt\"\x16\n" + + "\x14GetCategoriesRequest\"S\n" + + "\x14CategoryListResponse\x12;\n" + + "\n" + + "categories\x18\x01 \x03(\v2\x1b.cloudprint.LibraryCategoryR\n" + + "categories\"j\n" + + "\x16GetLibraryFilesRequest\x12\x1f\n" + + "\vcategory_id\x18\x01 \x01(\x05R\n" + + "categoryId\x12\x12\n" + + "\x04page\x18\x02 \x01(\x05R\x04page\x12\x1b\n" + + "\tpage_size\x18\x03 \x01(\x05R\bpageSize\"^\n" + + "\x17LibraryFileListResponse\x12-\n" + + "\x05files\x18\x01 \x03(\v2\x17.cloudprint.LibraryFileR\x05files\x12\x14\n" + + "\x05total\x18\x02 \x01(\x05R\x05total\"\xc1\x01\n" + + "\x18UploadLibraryFileRequest\x12\x1f\n" + + "\vcategory_id\x18\x01 \x01(\x05R\n" + + "categoryId\x12\x14\n" + + "\x05title\x18\x02 \x01(\tR\x05title\x12 \n" + + "\vdescription\x18\x03 \x01(\tR\vdescription\x12\x12\n" + + "\x04data\x18\x04 \x01(\fR\x04data\x12\x1b\n" + + "\tfile_name\x18\x05 \x01(\tR\bfileName\x12\x1b\n" + + "\tfile_type\x18\x06 \x01(\tR\bfileType\"C\n" + + "\x19UploadLibraryFileResponse\x12&\n" + + "\x0flibrary_file_id\x18\x01 \x01(\x05R\rlibraryFileId\"B\n" + + "\x18DeleteLibraryFileRequest\x12&\n" + + "\x0flibrary_file_id\x18\x01 \x01(\x05R\rlibraryFileId\"\xaf\x01\n" + + "\tPriceItem\x12\x0e\n" + + "\x02id\x18\x01 \x01(\x05R\x02id\x12\x12\n" + + "\x04name\x18\x02 \x01(\tR\x04name\x12\x12\n" + + "\x04type\x18\x03 \x01(\tR\x04type\x12\x14\n" + + "\x05price\x18\x04 \x01(\x01R\x05price\x12\x12\n" + + "\x04unit\x18\x05 \x01(\tR\x04unit\x12#\n" + + "\rcolor_enabled\x18\x06 \x01(\bR\fcolorEnabled\x12\x1b\n" + + "\tis_active\x18\a \x01(\bR\bisActive\"\x15\n" + + "\x13GetPriceListRequest\"@\n" + + "\x11PriceListResponse\x12+\n" + + "\x05items\x18\x01 \x03(\v2\x15.cloudprint.PriceItemR\x05items\"\x8f\x01\n" + + "\x16CreatePriceItemRequest\x12\x12\n" + + "\x04name\x18\x01 \x01(\tR\x04name\x12\x12\n" + + "\x04type\x18\x02 \x01(\tR\x04type\x12\x14\n" + + "\x05price\x18\x03 \x01(\x01R\x05price\x12\x12\n" + + "\x04unit\x18\x04 \x01(\tR\x04unit\x12#\n" + + "\rcolor_enabled\x18\x05 \x01(\bR\fcolorEnabled\"\xbc\x01\n" + + "\x16UpdatePriceItemRequest\x12\x0e\n" + + "\x02id\x18\x01 \x01(\x05R\x02id\x12\x12\n" + + "\x04name\x18\x02 \x01(\tR\x04name\x12\x12\n" + + "\x04type\x18\x03 \x01(\tR\x04type\x12\x14\n" + + "\x05price\x18\x04 \x01(\x01R\x05price\x12\x12\n" + + "\x04unit\x18\x05 \x01(\tR\x04unit\x12#\n" + + "\rcolor_enabled\x18\x06 \x01(\bR\fcolorEnabled\x12\x1b\n" + + "\tis_active\x18\a \x01(\bR\bisActive\"\x98\x01\n" + + "\fWxPayRequest\x12\x19\n" + + "\border_no\x18\x01 \x01(\tR\aorderNo\x12\x16\n" + + "\x06amount\x18\x02 \x01(\x01R\x06amount\x12 \n" + + "\vdescription\x18\x03 \x01(\tR\vdescription\x12\x16\n" + + "\x06openid\x18\x04 \x01(\tR\x06openid\x12\x1b\n" + + "\tclient_ip\x18\x05 \x01(\tR\bclientIp\"b\n" + + "\rWxPayResponse\x12\x1b\n" + + "\tprepay_id\x18\x01 \x01(\tR\bprepayId\x12\x19\n" + + "\bcode_url\x18\x02 \x01(\tR\acodeUrl\x12\x19\n" + + "\bmweb_url\x18\x03 \x01(\tR\amwebUrl\"2\n" + + "\x15QueryPayStatusRequest\x12\x19\n" + + "\border_no\x18\x01 \x01(\tR\aorderNo\"R\n" + + "\x11PayStatusResponse\x12\x16\n" + + "\x06status\x18\x01 \x01(\x05R\x06status\x12%\n" + + "\x0etransaction_id\x18\x02 \x01(\tR\rtransactionId\"(\n" + + "\x12PayCallbackRequest\x12\x12\n" + + "\x04body\x18\x01 \x01(\tR\x04body\"U\n" + + "\x13PayCallbackResponse\x12\x1f\n" + + "\vreturn_code\x18\x01 \x01(\tR\n" + + "returnCode\x12\x1d\n" + + "\n" + + "return_msg\x18\x02 \x01(\tR\treturnMsg\"I\n" + + "\x13PayByBalanceRequest\x12\x19\n" + + "\border_no\x18\x01 \x01(\tR\aorderNo\x12\x17\n" + + "\auser_id\x18\x02 \x01(\x05R\x06userId\"\x9e\x01\n" + + "\x05Admin\x12\x0e\n" + + "\x02id\x18\x01 \x01(\x05R\x02id\x12\x1a\n" + + "\busername\x18\x02 \x01(\tR\busername\x12\x1a\n" + + "\bnickname\x18\x03 \x01(\tR\bnickname\x12\x12\n" + + "\x04role\x18\x04 \x01(\x05R\x04role\x129\n" + + "\n" + + "created_at\x18\x05 \x01(\v2\x1a.google.protobuf.TimestampR\tcreatedAt\"K\n" + + "\x11AdminLoginRequest\x12\x1a\n" + + "\busername\x18\x01 \x01(\tR\busername\x12\x1a\n" + + "\bpassword\x18\x02 \x01(\tR\bpassword\"`\n" + + "\x12AdminLoginResponse\x12!\n" + + "\faccess_token\x18\x01 \x01(\tR\vaccessToken\x12'\n" + + "\x05admin\x18\x02 \x01(\v2\x11.cloudprint.AdminR\x05admin\"\x16\n" + + "\x14GetStatisticsRequest\"\xe8\x01\n" + + "\n" + + "Statistics\x12\x1f\n" + + "\vtotal_users\x18\x01 \x01(\x05R\n" + + "totalUsers\x12!\n" + + "\ftotal_orders\x18\x02 \x01(\x05R\vtotalOrders\x12!\n" + + "\ftoday_orders\x18\x03 \x01(\x05R\vtodayOrders\x12#\n" + + "\rtoday_revenue\x18\x04 \x01(\x01R\ftodayRevenue\x12%\n" + + "\x0epending_orders\x18\x05 \x01(\x05R\rpendingOrders\x12'\n" + + "\x0factive_printers\x18\x06 \x01(\x05R\x0eactivePrinters2\x94\x02\n" + + "\vAuthService\x12<\n" + + "\x05Login\x12\x18.cloudprint.LoginRequest\x1a\x19.cloudprint.LoginResponse\x12G\n" + + "\fRefreshToken\x12\x1a.cloudprint.RefreshRequest\x1a\x1b.cloudprint.RefreshResponse\x12?\n" + + "\vGetUserInfo\x12\x1e.cloudprint.GetUserInfoRequest\x1a\x10.cloudprint.User\x12=\n" + + "\n" + + "UpdateUser\x12\x1d.cloudprint.UpdateUserRequest\x1a\x10.cloudprint.User2\xe9\x02\n" + + "\vFileService\x12A\n" + + "\x06Upload\x12\x19.cloudprint.UploadRequest\x1a\x1a.cloudprint.UploadResponse(\x01\x12=\n" + + "\aGetFile\x12\x1a.cloudprint.GetFileRequest\x1a\x14.cloudprint.FileData0\x01\x12>\n" + + "\n" + + "DeleteFile\x12\x1d.cloudprint.DeleteFileRequest\x1a\x11.cloudprint.Empty\x12K\n" + + "\fAddWatermark\x12\x1c.cloudprint.WatermarkRequest\x1a\x1d.cloudprint.WatermarkResponse\x12K\n" + + "\vGetFileList\x12\x1e.cloudprint.GetFileListRequest\x1a\x1c.cloudprint.FileListResponse2\xfa\x02\n" + + "\fOrderService\x12N\n" + + "\vCreateOrder\x12\x1e.cloudprint.CreateOrderRequest\x1a\x1f.cloudprint.CreateOrderResponse\x12:\n" + + "\bGetOrder\x12\x1b.cloudprint.GetOrderRequest\x1a\x11.cloudprint.Order\x12N\n" + + "\fGetOrderList\x12\x1f.cloudprint.GetOrderListRequest\x1a\x1d.cloudprint.OrderListResponse\x12L\n" + + "\x11UpdateOrderStatus\x12$.cloudprint.UpdateOrderStatusRequest\x1a\x11.cloudprint.Empty\x12@\n" + + "\vCancelOrder\x12\x1e.cloudprint.CancelOrderRequest\x1a\x11.cloudprint.Empty2\x98\x05\n" + + "\fPrintService\x12N\n" + + "\vGetPrinters\x12\x1e.cloudprint.GetPrintersRequest\x1a\x1f.cloudprint.PrinterListResponse\x12Z\n" + + "\x10GetPrinterStatus\x12#.cloudprint.GetPrinterStatusRequest\x1a!.cloudprint.PrinterStatusResponse\x12Z\n" + + "\x0fRegisterPrinter\x12\".cloudprint.RegisterPrinterRequest\x1a#.cloudprint.RegisterPrinterResponse\x12J\n" + + "\x10PrinterHeartbeat\x12#.cloudprint.PrinterHeartbeatRequest\x1a\x11.cloudprint.Empty\x12W\n" + + "\x0eSubmitPrintJob\x12!.cloudprint.SubmitPrintJobRequest\x1a\".cloudprint.SubmitPrintJobResponse\x12F\n" + + "\x0eCancelPrintJob\x12!.cloudprint.CancelPrintJobRequest\x1a\x11.cloudprint.Empty\x12I\n" + + "\rSubscribeJobs\x12 .cloudprint.SubscribeJobsRequest\x1a\x14.cloudprint.PrintJob0\x01\x12H\n" + + "\x0fReportJobStatus\x12\".cloudprint.ReportJobStatusRequest\x1a\x11.cloudprint.Empty2\xde\x02\n" + + "\x0eLibraryService\x12S\n" + + "\rGetCategories\x12 .cloudprint.GetCategoriesRequest\x1a .cloudprint.CategoryListResponse\x12S\n" + + "\bGetFiles\x12\".cloudprint.GetLibraryFilesRequest\x1a#.cloudprint.LibraryFileListResponse\x12[\n" + + "\n" + + "UploadFile\x12$.cloudprint.UploadLibraryFileRequest\x1a%.cloudprint.UploadLibraryFileResponse(\x01\x12E\n" + + "\n" + + "DeleteFile\x12$.cloudprint.DeleteLibraryFileRequest\x1a\x11.cloudprint.Empty2\xfa\x01\n" + + "\fPriceService\x12N\n" + + "\fGetPriceList\x12\x1f.cloudprint.GetPriceListRequest\x1a\x1d.cloudprint.PriceListResponse\x12L\n" + + "\x0fCreatePriceItem\x12\".cloudprint.CreatePriceItemRequest\x1a\x15.cloudprint.PriceItem\x12L\n" + + "\x0fUpdatePriceItem\x12\".cloudprint.UpdatePriceItemRequest\x1a\x15.cloudprint.PriceItem2\xcc\x02\n" + + "\n" + + "PayService\x12G\n" + + "\x10CreateWxPayOrder\x12\x18.cloudprint.WxPayRequest\x1a\x19.cloudprint.WxPayResponse\x12R\n" + + "\x0eQueryPayStatus\x12!.cloudprint.QueryPayStatusRequest\x1a\x1d.cloudprint.PayStatusResponse\x12T\n" + + "\x11HandlePayCallback\x12\x1e.cloudprint.PayCallbackRequest\x1a\x1f.cloudprint.PayCallbackResponse\x12K\n" + + "\fPayByBalance\x12\x1f.cloudprint.PayByBalanceRequest\x1a\x1a.cloudprint.StatusResponse2\xa1\x01\n" + + "\fAdminService\x12F\n" + + "\x05Login\x12\x1d.cloudprint.AdminLoginRequest\x1a\x1e.cloudprint.AdminLoginResponse\x12I\n" + + "\rGetStatistics\x12 .cloudprint.GetStatisticsRequest\x1a\x16.cloudprint.StatisticsB:Z8github.com/cloudprint/cloudprint-backend/proto/generatedb\x06proto3" + +var ( + file_cloudprint_proto_rawDescOnce sync.Once + file_cloudprint_proto_rawDescData []byte +) + +func file_cloudprint_proto_rawDescGZIP() []byte { + file_cloudprint_proto_rawDescOnce.Do(func() { + file_cloudprint_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_cloudprint_proto_rawDesc), len(file_cloudprint_proto_rawDesc))) + }) + return file_cloudprint_proto_rawDescData +} + +var file_cloudprint_proto_msgTypes = make([]protoimpl.MessageInfo, 69) +var file_cloudprint_proto_goTypes = []any{ + (*Empty)(nil), // 0: cloudprint.Empty + (*StatusResponse)(nil), // 1: cloudprint.StatusResponse + (*User)(nil), // 2: cloudprint.User + (*LoginRequest)(nil), // 3: cloudprint.LoginRequest + (*LoginResponse)(nil), // 4: cloudprint.LoginResponse + (*RefreshRequest)(nil), // 5: cloudprint.RefreshRequest + (*RefreshResponse)(nil), // 6: cloudprint.RefreshResponse + (*GetUserInfoRequest)(nil), // 7: cloudprint.GetUserInfoRequest + (*UpdateUserRequest)(nil), // 8: cloudprint.UpdateUserRequest + (*FileInfo)(nil), // 9: cloudprint.FileInfo + (*UploadRequest)(nil), // 10: cloudprint.UploadRequest + (*UploadResponse)(nil), // 11: cloudprint.UploadResponse + (*GetFileRequest)(nil), // 12: cloudprint.GetFileRequest + (*FileData)(nil), // 13: cloudprint.FileData + (*DeleteFileRequest)(nil), // 14: cloudprint.DeleteFileRequest + (*WatermarkRequest)(nil), // 15: cloudprint.WatermarkRequest + (*WatermarkResponse)(nil), // 16: cloudprint.WatermarkResponse + (*GetFileListRequest)(nil), // 17: cloudprint.GetFileListRequest + (*FileListResponse)(nil), // 18: cloudprint.FileListResponse + (*Order)(nil), // 19: cloudprint.Order + (*OrderItem)(nil), // 20: cloudprint.OrderItem + (*CreateOrderRequest)(nil), // 21: cloudprint.CreateOrderRequest + (*CreateOrderItem)(nil), // 22: cloudprint.CreateOrderItem + (*CreateOrderResponse)(nil), // 23: cloudprint.CreateOrderResponse + (*GetOrderRequest)(nil), // 24: cloudprint.GetOrderRequest + (*GetOrderListRequest)(nil), // 25: cloudprint.GetOrderListRequest + (*OrderListResponse)(nil), // 26: cloudprint.OrderListResponse + (*UpdateOrderStatusRequest)(nil), // 27: cloudprint.UpdateOrderStatusRequest + (*CancelOrderRequest)(nil), // 28: cloudprint.CancelOrderRequest + (*Printer)(nil), // 29: cloudprint.Printer + (*GetPrintersRequest)(nil), // 30: cloudprint.GetPrintersRequest + (*PrinterListResponse)(nil), // 31: cloudprint.PrinterListResponse + (*GetPrinterStatusRequest)(nil), // 32: cloudprint.GetPrinterStatusRequest + (*PrinterStatusResponse)(nil), // 33: cloudprint.PrinterStatusResponse + (*RegisterPrinterRequest)(nil), // 34: cloudprint.RegisterPrinterRequest + (*RegisterPrinterResponse)(nil), // 35: cloudprint.RegisterPrinterResponse + (*PrinterHeartbeatRequest)(nil), // 36: cloudprint.PrinterHeartbeatRequest + (*PrintJob)(nil), // 37: cloudprint.PrintJob + (*SubmitPrintJobRequest)(nil), // 38: cloudprint.SubmitPrintJobRequest + (*SubmitPrintJobResponse)(nil), // 39: cloudprint.SubmitPrintJobResponse + (*CancelPrintJobRequest)(nil), // 40: cloudprint.CancelPrintJobRequest + (*SubscribeJobsRequest)(nil), // 41: cloudprint.SubscribeJobsRequest + (*ReportJobStatusRequest)(nil), // 42: cloudprint.ReportJobStatusRequest + (*LibraryCategory)(nil), // 43: cloudprint.LibraryCategory + (*LibraryFile)(nil), // 44: cloudprint.LibraryFile + (*GetCategoriesRequest)(nil), // 45: cloudprint.GetCategoriesRequest + (*CategoryListResponse)(nil), // 46: cloudprint.CategoryListResponse + (*GetLibraryFilesRequest)(nil), // 47: cloudprint.GetLibraryFilesRequest + (*LibraryFileListResponse)(nil), // 48: cloudprint.LibraryFileListResponse + (*UploadLibraryFileRequest)(nil), // 49: cloudprint.UploadLibraryFileRequest + (*UploadLibraryFileResponse)(nil), // 50: cloudprint.UploadLibraryFileResponse + (*DeleteLibraryFileRequest)(nil), // 51: cloudprint.DeleteLibraryFileRequest + (*PriceItem)(nil), // 52: cloudprint.PriceItem + (*GetPriceListRequest)(nil), // 53: cloudprint.GetPriceListRequest + (*PriceListResponse)(nil), // 54: cloudprint.PriceListResponse + (*CreatePriceItemRequest)(nil), // 55: cloudprint.CreatePriceItemRequest + (*UpdatePriceItemRequest)(nil), // 56: cloudprint.UpdatePriceItemRequest + (*WxPayRequest)(nil), // 57: cloudprint.WxPayRequest + (*WxPayResponse)(nil), // 58: cloudprint.WxPayResponse + (*QueryPayStatusRequest)(nil), // 59: cloudprint.QueryPayStatusRequest + (*PayStatusResponse)(nil), // 60: cloudprint.PayStatusResponse + (*PayCallbackRequest)(nil), // 61: cloudprint.PayCallbackRequest + (*PayCallbackResponse)(nil), // 62: cloudprint.PayCallbackResponse + (*PayByBalanceRequest)(nil), // 63: cloudprint.PayByBalanceRequest + (*Admin)(nil), // 64: cloudprint.Admin + (*AdminLoginRequest)(nil), // 65: cloudprint.AdminLoginRequest + (*AdminLoginResponse)(nil), // 66: cloudprint.AdminLoginResponse + (*GetStatisticsRequest)(nil), // 67: cloudprint.GetStatisticsRequest + (*Statistics)(nil), // 68: cloudprint.Statistics + (*timestamppb.Timestamp)(nil), // 69: google.protobuf.Timestamp +} +var file_cloudprint_proto_depIdxs = []int32{ + 69, // 0: cloudprint.User.created_at:type_name -> google.protobuf.Timestamp + 2, // 1: cloudprint.LoginResponse.user:type_name -> cloudprint.User + 69, // 2: cloudprint.FileInfo.created_at:type_name -> google.protobuf.Timestamp + 9, // 3: cloudprint.FileListResponse.files:type_name -> cloudprint.FileInfo + 69, // 4: cloudprint.Order.created_at:type_name -> google.protobuf.Timestamp + 69, // 5: cloudprint.Order.paid_at:type_name -> google.protobuf.Timestamp + 20, // 6: cloudprint.Order.items:type_name -> cloudprint.OrderItem + 9, // 7: cloudprint.OrderItem.file:type_name -> cloudprint.FileInfo + 22, // 8: cloudprint.CreateOrderRequest.items:type_name -> cloudprint.CreateOrderItem + 19, // 9: cloudprint.OrderListResponse.orders:type_name -> cloudprint.Order + 69, // 10: cloudprint.Printer.last_heartbeat:type_name -> google.protobuf.Timestamp + 29, // 11: cloudprint.PrinterListResponse.printers:type_name -> cloudprint.Printer + 29, // 12: cloudprint.PrinterStatusResponse.printer:type_name -> cloudprint.Printer + 69, // 13: cloudprint.PrintJob.started_at:type_name -> google.protobuf.Timestamp + 69, // 14: cloudprint.PrintJob.completed_at:type_name -> google.protobuf.Timestamp + 20, // 15: cloudprint.PrintJob.order_item:type_name -> cloudprint.OrderItem + 9, // 16: cloudprint.LibraryFile.file:type_name -> cloudprint.FileInfo + 69, // 17: cloudprint.LibraryFile.created_at:type_name -> google.protobuf.Timestamp + 43, // 18: cloudprint.CategoryListResponse.categories:type_name -> cloudprint.LibraryCategory + 44, // 19: cloudprint.LibraryFileListResponse.files:type_name -> cloudprint.LibraryFile + 52, // 20: cloudprint.PriceListResponse.items:type_name -> cloudprint.PriceItem + 69, // 21: cloudprint.Admin.created_at:type_name -> google.protobuf.Timestamp + 64, // 22: cloudprint.AdminLoginResponse.admin:type_name -> cloudprint.Admin + 3, // 23: cloudprint.AuthService.Login:input_type -> cloudprint.LoginRequest + 5, // 24: cloudprint.AuthService.RefreshToken:input_type -> cloudprint.RefreshRequest + 7, // 25: cloudprint.AuthService.GetUserInfo:input_type -> cloudprint.GetUserInfoRequest + 8, // 26: cloudprint.AuthService.UpdateUser:input_type -> cloudprint.UpdateUserRequest + 10, // 27: cloudprint.FileService.Upload:input_type -> cloudprint.UploadRequest + 12, // 28: cloudprint.FileService.GetFile:input_type -> cloudprint.GetFileRequest + 14, // 29: cloudprint.FileService.DeleteFile:input_type -> cloudprint.DeleteFileRequest + 15, // 30: cloudprint.FileService.AddWatermark:input_type -> cloudprint.WatermarkRequest + 17, // 31: cloudprint.FileService.GetFileList:input_type -> cloudprint.GetFileListRequest + 21, // 32: cloudprint.OrderService.CreateOrder:input_type -> cloudprint.CreateOrderRequest + 24, // 33: cloudprint.OrderService.GetOrder:input_type -> cloudprint.GetOrderRequest + 25, // 34: cloudprint.OrderService.GetOrderList:input_type -> cloudprint.GetOrderListRequest + 27, // 35: cloudprint.OrderService.UpdateOrderStatus:input_type -> cloudprint.UpdateOrderStatusRequest + 28, // 36: cloudprint.OrderService.CancelOrder:input_type -> cloudprint.CancelOrderRequest + 30, // 37: cloudprint.PrintService.GetPrinters:input_type -> cloudprint.GetPrintersRequest + 32, // 38: cloudprint.PrintService.GetPrinterStatus:input_type -> cloudprint.GetPrinterStatusRequest + 34, // 39: cloudprint.PrintService.RegisterPrinter:input_type -> cloudprint.RegisterPrinterRequest + 36, // 40: cloudprint.PrintService.PrinterHeartbeat:input_type -> cloudprint.PrinterHeartbeatRequest + 38, // 41: cloudprint.PrintService.SubmitPrintJob:input_type -> cloudprint.SubmitPrintJobRequest + 40, // 42: cloudprint.PrintService.CancelPrintJob:input_type -> cloudprint.CancelPrintJobRequest + 41, // 43: cloudprint.PrintService.SubscribeJobs:input_type -> cloudprint.SubscribeJobsRequest + 42, // 44: cloudprint.PrintService.ReportJobStatus:input_type -> cloudprint.ReportJobStatusRequest + 45, // 45: cloudprint.LibraryService.GetCategories:input_type -> cloudprint.GetCategoriesRequest + 47, // 46: cloudprint.LibraryService.GetFiles:input_type -> cloudprint.GetLibraryFilesRequest + 49, // 47: cloudprint.LibraryService.UploadFile:input_type -> cloudprint.UploadLibraryFileRequest + 51, // 48: cloudprint.LibraryService.DeleteFile:input_type -> cloudprint.DeleteLibraryFileRequest + 53, // 49: cloudprint.PriceService.GetPriceList:input_type -> cloudprint.GetPriceListRequest + 55, // 50: cloudprint.PriceService.CreatePriceItem:input_type -> cloudprint.CreatePriceItemRequest + 56, // 51: cloudprint.PriceService.UpdatePriceItem:input_type -> cloudprint.UpdatePriceItemRequest + 57, // 52: cloudprint.PayService.CreateWxPayOrder:input_type -> cloudprint.WxPayRequest + 59, // 53: cloudprint.PayService.QueryPayStatus:input_type -> cloudprint.QueryPayStatusRequest + 61, // 54: cloudprint.PayService.HandlePayCallback:input_type -> cloudprint.PayCallbackRequest + 63, // 55: cloudprint.PayService.PayByBalance:input_type -> cloudprint.PayByBalanceRequest + 65, // 56: cloudprint.AdminService.Login:input_type -> cloudprint.AdminLoginRequest + 67, // 57: cloudprint.AdminService.GetStatistics:input_type -> cloudprint.GetStatisticsRequest + 4, // 58: cloudprint.AuthService.Login:output_type -> cloudprint.LoginResponse + 6, // 59: cloudprint.AuthService.RefreshToken:output_type -> cloudprint.RefreshResponse + 2, // 60: cloudprint.AuthService.GetUserInfo:output_type -> cloudprint.User + 2, // 61: cloudprint.AuthService.UpdateUser:output_type -> cloudprint.User + 11, // 62: cloudprint.FileService.Upload:output_type -> cloudprint.UploadResponse + 13, // 63: cloudprint.FileService.GetFile:output_type -> cloudprint.FileData + 0, // 64: cloudprint.FileService.DeleteFile:output_type -> cloudprint.Empty + 16, // 65: cloudprint.FileService.AddWatermark:output_type -> cloudprint.WatermarkResponse + 18, // 66: cloudprint.FileService.GetFileList:output_type -> cloudprint.FileListResponse + 23, // 67: cloudprint.OrderService.CreateOrder:output_type -> cloudprint.CreateOrderResponse + 19, // 68: cloudprint.OrderService.GetOrder:output_type -> cloudprint.Order + 26, // 69: cloudprint.OrderService.GetOrderList:output_type -> cloudprint.OrderListResponse + 0, // 70: cloudprint.OrderService.UpdateOrderStatus:output_type -> cloudprint.Empty + 0, // 71: cloudprint.OrderService.CancelOrder:output_type -> cloudprint.Empty + 31, // 72: cloudprint.PrintService.GetPrinters:output_type -> cloudprint.PrinterListResponse + 33, // 73: cloudprint.PrintService.GetPrinterStatus:output_type -> cloudprint.PrinterStatusResponse + 35, // 74: cloudprint.PrintService.RegisterPrinter:output_type -> cloudprint.RegisterPrinterResponse + 0, // 75: cloudprint.PrintService.PrinterHeartbeat:output_type -> cloudprint.Empty + 39, // 76: cloudprint.PrintService.SubmitPrintJob:output_type -> cloudprint.SubmitPrintJobResponse + 0, // 77: cloudprint.PrintService.CancelPrintJob:output_type -> cloudprint.Empty + 37, // 78: cloudprint.PrintService.SubscribeJobs:output_type -> cloudprint.PrintJob + 0, // 79: cloudprint.PrintService.ReportJobStatus:output_type -> cloudprint.Empty + 46, // 80: cloudprint.LibraryService.GetCategories:output_type -> cloudprint.CategoryListResponse + 48, // 81: cloudprint.LibraryService.GetFiles:output_type -> cloudprint.LibraryFileListResponse + 50, // 82: cloudprint.LibraryService.UploadFile:output_type -> cloudprint.UploadLibraryFileResponse + 0, // 83: cloudprint.LibraryService.DeleteFile:output_type -> cloudprint.Empty + 54, // 84: cloudprint.PriceService.GetPriceList:output_type -> cloudprint.PriceListResponse + 52, // 85: cloudprint.PriceService.CreatePriceItem:output_type -> cloudprint.PriceItem + 52, // 86: cloudprint.PriceService.UpdatePriceItem:output_type -> cloudprint.PriceItem + 58, // 87: cloudprint.PayService.CreateWxPayOrder:output_type -> cloudprint.WxPayResponse + 60, // 88: cloudprint.PayService.QueryPayStatus:output_type -> cloudprint.PayStatusResponse + 62, // 89: cloudprint.PayService.HandlePayCallback:output_type -> cloudprint.PayCallbackResponse + 1, // 90: cloudprint.PayService.PayByBalance:output_type -> cloudprint.StatusResponse + 66, // 91: cloudprint.AdminService.Login:output_type -> cloudprint.AdminLoginResponse + 68, // 92: cloudprint.AdminService.GetStatistics:output_type -> cloudprint.Statistics + 58, // [58:93] is the sub-list for method output_type + 23, // [23:58] is the sub-list for method input_type + 23, // [23:23] is the sub-list for extension type_name + 23, // [23:23] is the sub-list for extension extendee + 0, // [0:23] is the sub-list for field type_name +} + +func init() { file_cloudprint_proto_init() } +func file_cloudprint_proto_init() { + if File_cloudprint_proto != nil { + return + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: unsafe.Slice(unsafe.StringData(file_cloudprint_proto_rawDesc), len(file_cloudprint_proto_rawDesc)), + NumEnums: 0, + NumMessages: 69, + NumExtensions: 0, + NumServices: 8, + }, + GoTypes: file_cloudprint_proto_goTypes, + DependencyIndexes: file_cloudprint_proto_depIdxs, + MessageInfos: file_cloudprint_proto_msgTypes, + }.Build() + File_cloudprint_proto = out.File + file_cloudprint_proto_goTypes = nil + file_cloudprint_proto_depIdxs = nil +} diff --git a/cloudprint-backend/proto/generated/cloudprint_grpc.pb.go b/cloudprint-backend/proto/generated/cloudprint_grpc.pb.go new file mode 100644 index 0000000..70d2fd2 --- /dev/null +++ b/cloudprint-backend/proto/generated/cloudprint_grpc.pb.go @@ -0,0 +1,1856 @@ +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. +// versions: +// - protoc-gen-go-grpc v1.6.1 +// - protoc v6.32.0 +// source: cloudprint.proto + +package generated + +import ( + context "context" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" +) + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +// Requires gRPC-Go v1.64.0 or later. +const _ = grpc.SupportPackageIsVersion9 + +const ( + AuthService_Login_FullMethodName = "/cloudprint.AuthService/Login" + AuthService_RefreshToken_FullMethodName = "/cloudprint.AuthService/RefreshToken" + AuthService_GetUserInfo_FullMethodName = "/cloudprint.AuthService/GetUserInfo" + AuthService_UpdateUser_FullMethodName = "/cloudprint.AuthService/UpdateUser" +) + +// AuthServiceClient is the client API for AuthService service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +type AuthServiceClient interface { + Login(ctx context.Context, in *LoginRequest, opts ...grpc.CallOption) (*LoginResponse, error) + RefreshToken(ctx context.Context, in *RefreshRequest, opts ...grpc.CallOption) (*RefreshResponse, error) + GetUserInfo(ctx context.Context, in *GetUserInfoRequest, opts ...grpc.CallOption) (*User, error) + UpdateUser(ctx context.Context, in *UpdateUserRequest, opts ...grpc.CallOption) (*User, error) +} + +type authServiceClient struct { + cc grpc.ClientConnInterface +} + +func NewAuthServiceClient(cc grpc.ClientConnInterface) AuthServiceClient { + return &authServiceClient{cc} +} + +func (c *authServiceClient) Login(ctx context.Context, in *LoginRequest, opts ...grpc.CallOption) (*LoginResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(LoginResponse) + err := c.cc.Invoke(ctx, AuthService_Login_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *authServiceClient) RefreshToken(ctx context.Context, in *RefreshRequest, opts ...grpc.CallOption) (*RefreshResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(RefreshResponse) + err := c.cc.Invoke(ctx, AuthService_RefreshToken_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *authServiceClient) GetUserInfo(ctx context.Context, in *GetUserInfoRequest, opts ...grpc.CallOption) (*User, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(User) + err := c.cc.Invoke(ctx, AuthService_GetUserInfo_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *authServiceClient) UpdateUser(ctx context.Context, in *UpdateUserRequest, opts ...grpc.CallOption) (*User, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(User) + err := c.cc.Invoke(ctx, AuthService_UpdateUser_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +// AuthServiceServer is the server API for AuthService service. +// All implementations must embed UnimplementedAuthServiceServer +// for forward compatibility. +type AuthServiceServer interface { + Login(context.Context, *LoginRequest) (*LoginResponse, error) + RefreshToken(context.Context, *RefreshRequest) (*RefreshResponse, error) + GetUserInfo(context.Context, *GetUserInfoRequest) (*User, error) + UpdateUser(context.Context, *UpdateUserRequest) (*User, error) + mustEmbedUnimplementedAuthServiceServer() +} + +// UnimplementedAuthServiceServer must be embedded to have +// forward compatible implementations. +// +// NOTE: this should be embedded by value instead of pointer to avoid a nil +// pointer dereference when methods are called. +type UnimplementedAuthServiceServer struct{} + +func (UnimplementedAuthServiceServer) Login(context.Context, *LoginRequest) (*LoginResponse, error) { + return nil, status.Error(codes.Unimplemented, "method Login not implemented") +} +func (UnimplementedAuthServiceServer) RefreshToken(context.Context, *RefreshRequest) (*RefreshResponse, error) { + return nil, status.Error(codes.Unimplemented, "method RefreshToken not implemented") +} +func (UnimplementedAuthServiceServer) GetUserInfo(context.Context, *GetUserInfoRequest) (*User, error) { + return nil, status.Error(codes.Unimplemented, "method GetUserInfo not implemented") +} +func (UnimplementedAuthServiceServer) UpdateUser(context.Context, *UpdateUserRequest) (*User, error) { + return nil, status.Error(codes.Unimplemented, "method UpdateUser not implemented") +} +func (UnimplementedAuthServiceServer) mustEmbedUnimplementedAuthServiceServer() {} +func (UnimplementedAuthServiceServer) testEmbeddedByValue() {} + +// UnsafeAuthServiceServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to AuthServiceServer will +// result in compilation errors. +type UnsafeAuthServiceServer interface { + mustEmbedUnimplementedAuthServiceServer() +} + +func RegisterAuthServiceServer(s grpc.ServiceRegistrar, srv AuthServiceServer) { + // If the following call panics, it indicates UnimplementedAuthServiceServer was + // embedded by pointer and is nil. This will cause panics if an + // unimplemented method is ever invoked, so we test this at initialization + // time to prevent it from happening at runtime later due to I/O. + if t, ok := srv.(interface{ testEmbeddedByValue() }); ok { + t.testEmbeddedByValue() + } + s.RegisterService(&AuthService_ServiceDesc, srv) +} + +func _AuthService_Login_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(LoginRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(AuthServiceServer).Login(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: AuthService_Login_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(AuthServiceServer).Login(ctx, req.(*LoginRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _AuthService_RefreshToken_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(RefreshRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(AuthServiceServer).RefreshToken(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: AuthService_RefreshToken_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(AuthServiceServer).RefreshToken(ctx, req.(*RefreshRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _AuthService_GetUserInfo_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetUserInfoRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(AuthServiceServer).GetUserInfo(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: AuthService_GetUserInfo_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(AuthServiceServer).GetUserInfo(ctx, req.(*GetUserInfoRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _AuthService_UpdateUser_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(UpdateUserRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(AuthServiceServer).UpdateUser(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: AuthService_UpdateUser_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(AuthServiceServer).UpdateUser(ctx, req.(*UpdateUserRequest)) + } + return interceptor(ctx, in, info, handler) +} + +// AuthService_ServiceDesc is the grpc.ServiceDesc for AuthService service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var AuthService_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "cloudprint.AuthService", + HandlerType: (*AuthServiceServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "Login", + Handler: _AuthService_Login_Handler, + }, + { + MethodName: "RefreshToken", + Handler: _AuthService_RefreshToken_Handler, + }, + { + MethodName: "GetUserInfo", + Handler: _AuthService_GetUserInfo_Handler, + }, + { + MethodName: "UpdateUser", + Handler: _AuthService_UpdateUser_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "cloudprint.proto", +} + +const ( + FileService_Upload_FullMethodName = "/cloudprint.FileService/Upload" + FileService_GetFile_FullMethodName = "/cloudprint.FileService/GetFile" + FileService_DeleteFile_FullMethodName = "/cloudprint.FileService/DeleteFile" + FileService_AddWatermark_FullMethodName = "/cloudprint.FileService/AddWatermark" + FileService_GetFileList_FullMethodName = "/cloudprint.FileService/GetFileList" +) + +// FileServiceClient is the client API for FileService service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +type FileServiceClient interface { + Upload(ctx context.Context, opts ...grpc.CallOption) (grpc.ClientStreamingClient[UploadRequest, UploadResponse], error) + GetFile(ctx context.Context, in *GetFileRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[FileData], error) + DeleteFile(ctx context.Context, in *DeleteFileRequest, opts ...grpc.CallOption) (*Empty, error) + AddWatermark(ctx context.Context, in *WatermarkRequest, opts ...grpc.CallOption) (*WatermarkResponse, error) + GetFileList(ctx context.Context, in *GetFileListRequest, opts ...grpc.CallOption) (*FileListResponse, error) +} + +type fileServiceClient struct { + cc grpc.ClientConnInterface +} + +func NewFileServiceClient(cc grpc.ClientConnInterface) FileServiceClient { + return &fileServiceClient{cc} +} + +func (c *fileServiceClient) Upload(ctx context.Context, opts ...grpc.CallOption) (grpc.ClientStreamingClient[UploadRequest, UploadResponse], error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + stream, err := c.cc.NewStream(ctx, &FileService_ServiceDesc.Streams[0], FileService_Upload_FullMethodName, cOpts...) + if err != nil { + return nil, err + } + x := &grpc.GenericClientStream[UploadRequest, UploadResponse]{ClientStream: stream} + return x, nil +} + +// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. +type FileService_UploadClient = grpc.ClientStreamingClient[UploadRequest, UploadResponse] + +func (c *fileServiceClient) GetFile(ctx context.Context, in *GetFileRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[FileData], error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + stream, err := c.cc.NewStream(ctx, &FileService_ServiceDesc.Streams[1], FileService_GetFile_FullMethodName, cOpts...) + if err != nil { + return nil, err + } + x := &grpc.GenericClientStream[GetFileRequest, FileData]{ClientStream: stream} + if err := x.ClientStream.SendMsg(in); err != nil { + return nil, err + } + if err := x.ClientStream.CloseSend(); err != nil { + return nil, err + } + return x, nil +} + +// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. +type FileService_GetFileClient = grpc.ServerStreamingClient[FileData] + +func (c *fileServiceClient) DeleteFile(ctx context.Context, in *DeleteFileRequest, opts ...grpc.CallOption) (*Empty, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(Empty) + err := c.cc.Invoke(ctx, FileService_DeleteFile_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *fileServiceClient) AddWatermark(ctx context.Context, in *WatermarkRequest, opts ...grpc.CallOption) (*WatermarkResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(WatermarkResponse) + err := c.cc.Invoke(ctx, FileService_AddWatermark_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *fileServiceClient) GetFileList(ctx context.Context, in *GetFileListRequest, opts ...grpc.CallOption) (*FileListResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(FileListResponse) + err := c.cc.Invoke(ctx, FileService_GetFileList_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +// FileServiceServer is the server API for FileService service. +// All implementations must embed UnimplementedFileServiceServer +// for forward compatibility. +type FileServiceServer interface { + Upload(grpc.ClientStreamingServer[UploadRequest, UploadResponse]) error + GetFile(*GetFileRequest, grpc.ServerStreamingServer[FileData]) error + DeleteFile(context.Context, *DeleteFileRequest) (*Empty, error) + AddWatermark(context.Context, *WatermarkRequest) (*WatermarkResponse, error) + GetFileList(context.Context, *GetFileListRequest) (*FileListResponse, error) + mustEmbedUnimplementedFileServiceServer() +} + +// UnimplementedFileServiceServer must be embedded to have +// forward compatible implementations. +// +// NOTE: this should be embedded by value instead of pointer to avoid a nil +// pointer dereference when methods are called. +type UnimplementedFileServiceServer struct{} + +func (UnimplementedFileServiceServer) Upload(grpc.ClientStreamingServer[UploadRequest, UploadResponse]) error { + return status.Error(codes.Unimplemented, "method Upload not implemented") +} +func (UnimplementedFileServiceServer) GetFile(*GetFileRequest, grpc.ServerStreamingServer[FileData]) error { + return status.Error(codes.Unimplemented, "method GetFile not implemented") +} +func (UnimplementedFileServiceServer) DeleteFile(context.Context, *DeleteFileRequest) (*Empty, error) { + return nil, status.Error(codes.Unimplemented, "method DeleteFile not implemented") +} +func (UnimplementedFileServiceServer) AddWatermark(context.Context, *WatermarkRequest) (*WatermarkResponse, error) { + return nil, status.Error(codes.Unimplemented, "method AddWatermark not implemented") +} +func (UnimplementedFileServiceServer) GetFileList(context.Context, *GetFileListRequest) (*FileListResponse, error) { + return nil, status.Error(codes.Unimplemented, "method GetFileList not implemented") +} +func (UnimplementedFileServiceServer) mustEmbedUnimplementedFileServiceServer() {} +func (UnimplementedFileServiceServer) testEmbeddedByValue() {} + +// UnsafeFileServiceServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to FileServiceServer will +// result in compilation errors. +type UnsafeFileServiceServer interface { + mustEmbedUnimplementedFileServiceServer() +} + +func RegisterFileServiceServer(s grpc.ServiceRegistrar, srv FileServiceServer) { + // If the following call panics, it indicates UnimplementedFileServiceServer was + // embedded by pointer and is nil. This will cause panics if an + // unimplemented method is ever invoked, so we test this at initialization + // time to prevent it from happening at runtime later due to I/O. + if t, ok := srv.(interface{ testEmbeddedByValue() }); ok { + t.testEmbeddedByValue() + } + s.RegisterService(&FileService_ServiceDesc, srv) +} + +func _FileService_Upload_Handler(srv interface{}, stream grpc.ServerStream) error { + return srv.(FileServiceServer).Upload(&grpc.GenericServerStream[UploadRequest, UploadResponse]{ServerStream: stream}) +} + +// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. +type FileService_UploadServer = grpc.ClientStreamingServer[UploadRequest, UploadResponse] + +func _FileService_GetFile_Handler(srv interface{}, stream grpc.ServerStream) error { + m := new(GetFileRequest) + if err := stream.RecvMsg(m); err != nil { + return err + } + return srv.(FileServiceServer).GetFile(m, &grpc.GenericServerStream[GetFileRequest, FileData]{ServerStream: stream}) +} + +// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. +type FileService_GetFileServer = grpc.ServerStreamingServer[FileData] + +func _FileService_DeleteFile_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(DeleteFileRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(FileServiceServer).DeleteFile(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: FileService_DeleteFile_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(FileServiceServer).DeleteFile(ctx, req.(*DeleteFileRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _FileService_AddWatermark_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(WatermarkRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(FileServiceServer).AddWatermark(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: FileService_AddWatermark_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(FileServiceServer).AddWatermark(ctx, req.(*WatermarkRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _FileService_GetFileList_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetFileListRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(FileServiceServer).GetFileList(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: FileService_GetFileList_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(FileServiceServer).GetFileList(ctx, req.(*GetFileListRequest)) + } + return interceptor(ctx, in, info, handler) +} + +// FileService_ServiceDesc is the grpc.ServiceDesc for FileService service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var FileService_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "cloudprint.FileService", + HandlerType: (*FileServiceServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "DeleteFile", + Handler: _FileService_DeleteFile_Handler, + }, + { + MethodName: "AddWatermark", + Handler: _FileService_AddWatermark_Handler, + }, + { + MethodName: "GetFileList", + Handler: _FileService_GetFileList_Handler, + }, + }, + Streams: []grpc.StreamDesc{ + { + StreamName: "Upload", + Handler: _FileService_Upload_Handler, + ClientStreams: true, + }, + { + StreamName: "GetFile", + Handler: _FileService_GetFile_Handler, + ServerStreams: true, + }, + }, + Metadata: "cloudprint.proto", +} + +const ( + OrderService_CreateOrder_FullMethodName = "/cloudprint.OrderService/CreateOrder" + OrderService_GetOrder_FullMethodName = "/cloudprint.OrderService/GetOrder" + OrderService_GetOrderList_FullMethodName = "/cloudprint.OrderService/GetOrderList" + OrderService_UpdateOrderStatus_FullMethodName = "/cloudprint.OrderService/UpdateOrderStatus" + OrderService_CancelOrder_FullMethodName = "/cloudprint.OrderService/CancelOrder" +) + +// OrderServiceClient is the client API for OrderService service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +type OrderServiceClient interface { + CreateOrder(ctx context.Context, in *CreateOrderRequest, opts ...grpc.CallOption) (*CreateOrderResponse, error) + GetOrder(ctx context.Context, in *GetOrderRequest, opts ...grpc.CallOption) (*Order, error) + GetOrderList(ctx context.Context, in *GetOrderListRequest, opts ...grpc.CallOption) (*OrderListResponse, error) + UpdateOrderStatus(ctx context.Context, in *UpdateOrderStatusRequest, opts ...grpc.CallOption) (*Empty, error) + CancelOrder(ctx context.Context, in *CancelOrderRequest, opts ...grpc.CallOption) (*Empty, error) +} + +type orderServiceClient struct { + cc grpc.ClientConnInterface +} + +func NewOrderServiceClient(cc grpc.ClientConnInterface) OrderServiceClient { + return &orderServiceClient{cc} +} + +func (c *orderServiceClient) CreateOrder(ctx context.Context, in *CreateOrderRequest, opts ...grpc.CallOption) (*CreateOrderResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(CreateOrderResponse) + err := c.cc.Invoke(ctx, OrderService_CreateOrder_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *orderServiceClient) GetOrder(ctx context.Context, in *GetOrderRequest, opts ...grpc.CallOption) (*Order, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(Order) + err := c.cc.Invoke(ctx, OrderService_GetOrder_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *orderServiceClient) GetOrderList(ctx context.Context, in *GetOrderListRequest, opts ...grpc.CallOption) (*OrderListResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(OrderListResponse) + err := c.cc.Invoke(ctx, OrderService_GetOrderList_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *orderServiceClient) UpdateOrderStatus(ctx context.Context, in *UpdateOrderStatusRequest, opts ...grpc.CallOption) (*Empty, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(Empty) + err := c.cc.Invoke(ctx, OrderService_UpdateOrderStatus_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *orderServiceClient) CancelOrder(ctx context.Context, in *CancelOrderRequest, opts ...grpc.CallOption) (*Empty, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(Empty) + err := c.cc.Invoke(ctx, OrderService_CancelOrder_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +// OrderServiceServer is the server API for OrderService service. +// All implementations must embed UnimplementedOrderServiceServer +// for forward compatibility. +type OrderServiceServer interface { + CreateOrder(context.Context, *CreateOrderRequest) (*CreateOrderResponse, error) + GetOrder(context.Context, *GetOrderRequest) (*Order, error) + GetOrderList(context.Context, *GetOrderListRequest) (*OrderListResponse, error) + UpdateOrderStatus(context.Context, *UpdateOrderStatusRequest) (*Empty, error) + CancelOrder(context.Context, *CancelOrderRequest) (*Empty, error) + mustEmbedUnimplementedOrderServiceServer() +} + +// UnimplementedOrderServiceServer must be embedded to have +// forward compatible implementations. +// +// NOTE: this should be embedded by value instead of pointer to avoid a nil +// pointer dereference when methods are called. +type UnimplementedOrderServiceServer struct{} + +func (UnimplementedOrderServiceServer) CreateOrder(context.Context, *CreateOrderRequest) (*CreateOrderResponse, error) { + return nil, status.Error(codes.Unimplemented, "method CreateOrder not implemented") +} +func (UnimplementedOrderServiceServer) GetOrder(context.Context, *GetOrderRequest) (*Order, error) { + return nil, status.Error(codes.Unimplemented, "method GetOrder not implemented") +} +func (UnimplementedOrderServiceServer) GetOrderList(context.Context, *GetOrderListRequest) (*OrderListResponse, error) { + return nil, status.Error(codes.Unimplemented, "method GetOrderList not implemented") +} +func (UnimplementedOrderServiceServer) UpdateOrderStatus(context.Context, *UpdateOrderStatusRequest) (*Empty, error) { + return nil, status.Error(codes.Unimplemented, "method UpdateOrderStatus not implemented") +} +func (UnimplementedOrderServiceServer) CancelOrder(context.Context, *CancelOrderRequest) (*Empty, error) { + return nil, status.Error(codes.Unimplemented, "method CancelOrder not implemented") +} +func (UnimplementedOrderServiceServer) mustEmbedUnimplementedOrderServiceServer() {} +func (UnimplementedOrderServiceServer) testEmbeddedByValue() {} + +// UnsafeOrderServiceServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to OrderServiceServer will +// result in compilation errors. +type UnsafeOrderServiceServer interface { + mustEmbedUnimplementedOrderServiceServer() +} + +func RegisterOrderServiceServer(s grpc.ServiceRegistrar, srv OrderServiceServer) { + // If the following call panics, it indicates UnimplementedOrderServiceServer was + // embedded by pointer and is nil. This will cause panics if an + // unimplemented method is ever invoked, so we test this at initialization + // time to prevent it from happening at runtime later due to I/O. + if t, ok := srv.(interface{ testEmbeddedByValue() }); ok { + t.testEmbeddedByValue() + } + s.RegisterService(&OrderService_ServiceDesc, srv) +} + +func _OrderService_CreateOrder_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(CreateOrderRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(OrderServiceServer).CreateOrder(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: OrderService_CreateOrder_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(OrderServiceServer).CreateOrder(ctx, req.(*CreateOrderRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _OrderService_GetOrder_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetOrderRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(OrderServiceServer).GetOrder(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: OrderService_GetOrder_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(OrderServiceServer).GetOrder(ctx, req.(*GetOrderRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _OrderService_GetOrderList_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetOrderListRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(OrderServiceServer).GetOrderList(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: OrderService_GetOrderList_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(OrderServiceServer).GetOrderList(ctx, req.(*GetOrderListRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _OrderService_UpdateOrderStatus_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(UpdateOrderStatusRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(OrderServiceServer).UpdateOrderStatus(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: OrderService_UpdateOrderStatus_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(OrderServiceServer).UpdateOrderStatus(ctx, req.(*UpdateOrderStatusRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _OrderService_CancelOrder_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(CancelOrderRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(OrderServiceServer).CancelOrder(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: OrderService_CancelOrder_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(OrderServiceServer).CancelOrder(ctx, req.(*CancelOrderRequest)) + } + return interceptor(ctx, in, info, handler) +} + +// OrderService_ServiceDesc is the grpc.ServiceDesc for OrderService service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var OrderService_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "cloudprint.OrderService", + HandlerType: (*OrderServiceServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "CreateOrder", + Handler: _OrderService_CreateOrder_Handler, + }, + { + MethodName: "GetOrder", + Handler: _OrderService_GetOrder_Handler, + }, + { + MethodName: "GetOrderList", + Handler: _OrderService_GetOrderList_Handler, + }, + { + MethodName: "UpdateOrderStatus", + Handler: _OrderService_UpdateOrderStatus_Handler, + }, + { + MethodName: "CancelOrder", + Handler: _OrderService_CancelOrder_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "cloudprint.proto", +} + +const ( + PrintService_GetPrinters_FullMethodName = "/cloudprint.PrintService/GetPrinters" + PrintService_GetPrinterStatus_FullMethodName = "/cloudprint.PrintService/GetPrinterStatus" + PrintService_RegisterPrinter_FullMethodName = "/cloudprint.PrintService/RegisterPrinter" + PrintService_PrinterHeartbeat_FullMethodName = "/cloudprint.PrintService/PrinterHeartbeat" + PrintService_SubmitPrintJob_FullMethodName = "/cloudprint.PrintService/SubmitPrintJob" + PrintService_CancelPrintJob_FullMethodName = "/cloudprint.PrintService/CancelPrintJob" + PrintService_SubscribeJobs_FullMethodName = "/cloudprint.PrintService/SubscribeJobs" + PrintService_ReportJobStatus_FullMethodName = "/cloudprint.PrintService/ReportJobStatus" +) + +// PrintServiceClient is the client API for PrintService service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +type PrintServiceClient interface { + GetPrinters(ctx context.Context, in *GetPrintersRequest, opts ...grpc.CallOption) (*PrinterListResponse, error) + GetPrinterStatus(ctx context.Context, in *GetPrinterStatusRequest, opts ...grpc.CallOption) (*PrinterStatusResponse, error) + RegisterPrinter(ctx context.Context, in *RegisterPrinterRequest, opts ...grpc.CallOption) (*RegisterPrinterResponse, error) + PrinterHeartbeat(ctx context.Context, in *PrinterHeartbeatRequest, opts ...grpc.CallOption) (*Empty, error) + SubmitPrintJob(ctx context.Context, in *SubmitPrintJobRequest, opts ...grpc.CallOption) (*SubmitPrintJobResponse, error) + CancelPrintJob(ctx context.Context, in *CancelPrintJobRequest, opts ...grpc.CallOption) (*Empty, error) + SubscribeJobs(ctx context.Context, in *SubscribeJobsRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[PrintJob], error) + ReportJobStatus(ctx context.Context, in *ReportJobStatusRequest, opts ...grpc.CallOption) (*Empty, error) +} + +type printServiceClient struct { + cc grpc.ClientConnInterface +} + +func NewPrintServiceClient(cc grpc.ClientConnInterface) PrintServiceClient { + return &printServiceClient{cc} +} + +func (c *printServiceClient) GetPrinters(ctx context.Context, in *GetPrintersRequest, opts ...grpc.CallOption) (*PrinterListResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(PrinterListResponse) + err := c.cc.Invoke(ctx, PrintService_GetPrinters_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *printServiceClient) GetPrinterStatus(ctx context.Context, in *GetPrinterStatusRequest, opts ...grpc.CallOption) (*PrinterStatusResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(PrinterStatusResponse) + err := c.cc.Invoke(ctx, PrintService_GetPrinterStatus_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *printServiceClient) RegisterPrinter(ctx context.Context, in *RegisterPrinterRequest, opts ...grpc.CallOption) (*RegisterPrinterResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(RegisterPrinterResponse) + err := c.cc.Invoke(ctx, PrintService_RegisterPrinter_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *printServiceClient) PrinterHeartbeat(ctx context.Context, in *PrinterHeartbeatRequest, opts ...grpc.CallOption) (*Empty, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(Empty) + err := c.cc.Invoke(ctx, PrintService_PrinterHeartbeat_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *printServiceClient) SubmitPrintJob(ctx context.Context, in *SubmitPrintJobRequest, opts ...grpc.CallOption) (*SubmitPrintJobResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(SubmitPrintJobResponse) + err := c.cc.Invoke(ctx, PrintService_SubmitPrintJob_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *printServiceClient) CancelPrintJob(ctx context.Context, in *CancelPrintJobRequest, opts ...grpc.CallOption) (*Empty, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(Empty) + err := c.cc.Invoke(ctx, PrintService_CancelPrintJob_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *printServiceClient) SubscribeJobs(ctx context.Context, in *SubscribeJobsRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[PrintJob], error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + stream, err := c.cc.NewStream(ctx, &PrintService_ServiceDesc.Streams[0], PrintService_SubscribeJobs_FullMethodName, cOpts...) + if err != nil { + return nil, err + } + x := &grpc.GenericClientStream[SubscribeJobsRequest, PrintJob]{ClientStream: stream} + if err := x.ClientStream.SendMsg(in); err != nil { + return nil, err + } + if err := x.ClientStream.CloseSend(); err != nil { + return nil, err + } + return x, nil +} + +// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. +type PrintService_SubscribeJobsClient = grpc.ServerStreamingClient[PrintJob] + +func (c *printServiceClient) ReportJobStatus(ctx context.Context, in *ReportJobStatusRequest, opts ...grpc.CallOption) (*Empty, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(Empty) + err := c.cc.Invoke(ctx, PrintService_ReportJobStatus_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +// PrintServiceServer is the server API for PrintService service. +// All implementations must embed UnimplementedPrintServiceServer +// for forward compatibility. +type PrintServiceServer interface { + GetPrinters(context.Context, *GetPrintersRequest) (*PrinterListResponse, error) + GetPrinterStatus(context.Context, *GetPrinterStatusRequest) (*PrinterStatusResponse, error) + RegisterPrinter(context.Context, *RegisterPrinterRequest) (*RegisterPrinterResponse, error) + PrinterHeartbeat(context.Context, *PrinterHeartbeatRequest) (*Empty, error) + SubmitPrintJob(context.Context, *SubmitPrintJobRequest) (*SubmitPrintJobResponse, error) + CancelPrintJob(context.Context, *CancelPrintJobRequest) (*Empty, error) + SubscribeJobs(*SubscribeJobsRequest, grpc.ServerStreamingServer[PrintJob]) error + ReportJobStatus(context.Context, *ReportJobStatusRequest) (*Empty, error) + mustEmbedUnimplementedPrintServiceServer() +} + +// UnimplementedPrintServiceServer must be embedded to have +// forward compatible implementations. +// +// NOTE: this should be embedded by value instead of pointer to avoid a nil +// pointer dereference when methods are called. +type UnimplementedPrintServiceServer struct{} + +func (UnimplementedPrintServiceServer) GetPrinters(context.Context, *GetPrintersRequest) (*PrinterListResponse, error) { + return nil, status.Error(codes.Unimplemented, "method GetPrinters not implemented") +} +func (UnimplementedPrintServiceServer) GetPrinterStatus(context.Context, *GetPrinterStatusRequest) (*PrinterStatusResponse, error) { + return nil, status.Error(codes.Unimplemented, "method GetPrinterStatus not implemented") +} +func (UnimplementedPrintServiceServer) RegisterPrinter(context.Context, *RegisterPrinterRequest) (*RegisterPrinterResponse, error) { + return nil, status.Error(codes.Unimplemented, "method RegisterPrinter not implemented") +} +func (UnimplementedPrintServiceServer) PrinterHeartbeat(context.Context, *PrinterHeartbeatRequest) (*Empty, error) { + return nil, status.Error(codes.Unimplemented, "method PrinterHeartbeat not implemented") +} +func (UnimplementedPrintServiceServer) SubmitPrintJob(context.Context, *SubmitPrintJobRequest) (*SubmitPrintJobResponse, error) { + return nil, status.Error(codes.Unimplemented, "method SubmitPrintJob not implemented") +} +func (UnimplementedPrintServiceServer) CancelPrintJob(context.Context, *CancelPrintJobRequest) (*Empty, error) { + return nil, status.Error(codes.Unimplemented, "method CancelPrintJob not implemented") +} +func (UnimplementedPrintServiceServer) SubscribeJobs(*SubscribeJobsRequest, grpc.ServerStreamingServer[PrintJob]) error { + return status.Error(codes.Unimplemented, "method SubscribeJobs not implemented") +} +func (UnimplementedPrintServiceServer) ReportJobStatus(context.Context, *ReportJobStatusRequest) (*Empty, error) { + return nil, status.Error(codes.Unimplemented, "method ReportJobStatus not implemented") +} +func (UnimplementedPrintServiceServer) mustEmbedUnimplementedPrintServiceServer() {} +func (UnimplementedPrintServiceServer) testEmbeddedByValue() {} + +// UnsafePrintServiceServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to PrintServiceServer will +// result in compilation errors. +type UnsafePrintServiceServer interface { + mustEmbedUnimplementedPrintServiceServer() +} + +func RegisterPrintServiceServer(s grpc.ServiceRegistrar, srv PrintServiceServer) { + // If the following call panics, it indicates UnimplementedPrintServiceServer was + // embedded by pointer and is nil. This will cause panics if an + // unimplemented method is ever invoked, so we test this at initialization + // time to prevent it from happening at runtime later due to I/O. + if t, ok := srv.(interface{ testEmbeddedByValue() }); ok { + t.testEmbeddedByValue() + } + s.RegisterService(&PrintService_ServiceDesc, srv) +} + +func _PrintService_GetPrinters_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetPrintersRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(PrintServiceServer).GetPrinters(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: PrintService_GetPrinters_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(PrintServiceServer).GetPrinters(ctx, req.(*GetPrintersRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _PrintService_GetPrinterStatus_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetPrinterStatusRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(PrintServiceServer).GetPrinterStatus(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: PrintService_GetPrinterStatus_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(PrintServiceServer).GetPrinterStatus(ctx, req.(*GetPrinterStatusRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _PrintService_RegisterPrinter_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(RegisterPrinterRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(PrintServiceServer).RegisterPrinter(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: PrintService_RegisterPrinter_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(PrintServiceServer).RegisterPrinter(ctx, req.(*RegisterPrinterRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _PrintService_PrinterHeartbeat_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(PrinterHeartbeatRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(PrintServiceServer).PrinterHeartbeat(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: PrintService_PrinterHeartbeat_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(PrintServiceServer).PrinterHeartbeat(ctx, req.(*PrinterHeartbeatRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _PrintService_SubmitPrintJob_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(SubmitPrintJobRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(PrintServiceServer).SubmitPrintJob(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: PrintService_SubmitPrintJob_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(PrintServiceServer).SubmitPrintJob(ctx, req.(*SubmitPrintJobRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _PrintService_CancelPrintJob_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(CancelPrintJobRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(PrintServiceServer).CancelPrintJob(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: PrintService_CancelPrintJob_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(PrintServiceServer).CancelPrintJob(ctx, req.(*CancelPrintJobRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _PrintService_SubscribeJobs_Handler(srv interface{}, stream grpc.ServerStream) error { + m := new(SubscribeJobsRequest) + if err := stream.RecvMsg(m); err != nil { + return err + } + return srv.(PrintServiceServer).SubscribeJobs(m, &grpc.GenericServerStream[SubscribeJobsRequest, PrintJob]{ServerStream: stream}) +} + +// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. +type PrintService_SubscribeJobsServer = grpc.ServerStreamingServer[PrintJob] + +func _PrintService_ReportJobStatus_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ReportJobStatusRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(PrintServiceServer).ReportJobStatus(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: PrintService_ReportJobStatus_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(PrintServiceServer).ReportJobStatus(ctx, req.(*ReportJobStatusRequest)) + } + return interceptor(ctx, in, info, handler) +} + +// PrintService_ServiceDesc is the grpc.ServiceDesc for PrintService service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var PrintService_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "cloudprint.PrintService", + HandlerType: (*PrintServiceServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "GetPrinters", + Handler: _PrintService_GetPrinters_Handler, + }, + { + MethodName: "GetPrinterStatus", + Handler: _PrintService_GetPrinterStatus_Handler, + }, + { + MethodName: "RegisterPrinter", + Handler: _PrintService_RegisterPrinter_Handler, + }, + { + MethodName: "PrinterHeartbeat", + Handler: _PrintService_PrinterHeartbeat_Handler, + }, + { + MethodName: "SubmitPrintJob", + Handler: _PrintService_SubmitPrintJob_Handler, + }, + { + MethodName: "CancelPrintJob", + Handler: _PrintService_CancelPrintJob_Handler, + }, + { + MethodName: "ReportJobStatus", + Handler: _PrintService_ReportJobStatus_Handler, + }, + }, + Streams: []grpc.StreamDesc{ + { + StreamName: "SubscribeJobs", + Handler: _PrintService_SubscribeJobs_Handler, + ServerStreams: true, + }, + }, + Metadata: "cloudprint.proto", +} + +const ( + LibraryService_GetCategories_FullMethodName = "/cloudprint.LibraryService/GetCategories" + LibraryService_GetFiles_FullMethodName = "/cloudprint.LibraryService/GetFiles" + LibraryService_UploadFile_FullMethodName = "/cloudprint.LibraryService/UploadFile" + LibraryService_DeleteFile_FullMethodName = "/cloudprint.LibraryService/DeleteFile" +) + +// LibraryServiceClient is the client API for LibraryService service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +type LibraryServiceClient interface { + GetCategories(ctx context.Context, in *GetCategoriesRequest, opts ...grpc.CallOption) (*CategoryListResponse, error) + GetFiles(ctx context.Context, in *GetLibraryFilesRequest, opts ...grpc.CallOption) (*LibraryFileListResponse, error) + UploadFile(ctx context.Context, opts ...grpc.CallOption) (grpc.ClientStreamingClient[UploadLibraryFileRequest, UploadLibraryFileResponse], error) + DeleteFile(ctx context.Context, in *DeleteLibraryFileRequest, opts ...grpc.CallOption) (*Empty, error) +} + +type libraryServiceClient struct { + cc grpc.ClientConnInterface +} + +func NewLibraryServiceClient(cc grpc.ClientConnInterface) LibraryServiceClient { + return &libraryServiceClient{cc} +} + +func (c *libraryServiceClient) GetCategories(ctx context.Context, in *GetCategoriesRequest, opts ...grpc.CallOption) (*CategoryListResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(CategoryListResponse) + err := c.cc.Invoke(ctx, LibraryService_GetCategories_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *libraryServiceClient) GetFiles(ctx context.Context, in *GetLibraryFilesRequest, opts ...grpc.CallOption) (*LibraryFileListResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(LibraryFileListResponse) + err := c.cc.Invoke(ctx, LibraryService_GetFiles_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *libraryServiceClient) UploadFile(ctx context.Context, opts ...grpc.CallOption) (grpc.ClientStreamingClient[UploadLibraryFileRequest, UploadLibraryFileResponse], error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + stream, err := c.cc.NewStream(ctx, &LibraryService_ServiceDesc.Streams[0], LibraryService_UploadFile_FullMethodName, cOpts...) + if err != nil { + return nil, err + } + x := &grpc.GenericClientStream[UploadLibraryFileRequest, UploadLibraryFileResponse]{ClientStream: stream} + return x, nil +} + +// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. +type LibraryService_UploadFileClient = grpc.ClientStreamingClient[UploadLibraryFileRequest, UploadLibraryFileResponse] + +func (c *libraryServiceClient) DeleteFile(ctx context.Context, in *DeleteLibraryFileRequest, opts ...grpc.CallOption) (*Empty, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(Empty) + err := c.cc.Invoke(ctx, LibraryService_DeleteFile_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +// LibraryServiceServer is the server API for LibraryService service. +// All implementations must embed UnimplementedLibraryServiceServer +// for forward compatibility. +type LibraryServiceServer interface { + GetCategories(context.Context, *GetCategoriesRequest) (*CategoryListResponse, error) + GetFiles(context.Context, *GetLibraryFilesRequest) (*LibraryFileListResponse, error) + UploadFile(grpc.ClientStreamingServer[UploadLibraryFileRequest, UploadLibraryFileResponse]) error + DeleteFile(context.Context, *DeleteLibraryFileRequest) (*Empty, error) + mustEmbedUnimplementedLibraryServiceServer() +} + +// UnimplementedLibraryServiceServer must be embedded to have +// forward compatible implementations. +// +// NOTE: this should be embedded by value instead of pointer to avoid a nil +// pointer dereference when methods are called. +type UnimplementedLibraryServiceServer struct{} + +func (UnimplementedLibraryServiceServer) GetCategories(context.Context, *GetCategoriesRequest) (*CategoryListResponse, error) { + return nil, status.Error(codes.Unimplemented, "method GetCategories not implemented") +} +func (UnimplementedLibraryServiceServer) GetFiles(context.Context, *GetLibraryFilesRequest) (*LibraryFileListResponse, error) { + return nil, status.Error(codes.Unimplemented, "method GetFiles not implemented") +} +func (UnimplementedLibraryServiceServer) UploadFile(grpc.ClientStreamingServer[UploadLibraryFileRequest, UploadLibraryFileResponse]) error { + return status.Error(codes.Unimplemented, "method UploadFile not implemented") +} +func (UnimplementedLibraryServiceServer) DeleteFile(context.Context, *DeleteLibraryFileRequest) (*Empty, error) { + return nil, status.Error(codes.Unimplemented, "method DeleteFile not implemented") +} +func (UnimplementedLibraryServiceServer) mustEmbedUnimplementedLibraryServiceServer() {} +func (UnimplementedLibraryServiceServer) testEmbeddedByValue() {} + +// UnsafeLibraryServiceServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to LibraryServiceServer will +// result in compilation errors. +type UnsafeLibraryServiceServer interface { + mustEmbedUnimplementedLibraryServiceServer() +} + +func RegisterLibraryServiceServer(s grpc.ServiceRegistrar, srv LibraryServiceServer) { + // If the following call panics, it indicates UnimplementedLibraryServiceServer was + // embedded by pointer and is nil. This will cause panics if an + // unimplemented method is ever invoked, so we test this at initialization + // time to prevent it from happening at runtime later due to I/O. + if t, ok := srv.(interface{ testEmbeddedByValue() }); ok { + t.testEmbeddedByValue() + } + s.RegisterService(&LibraryService_ServiceDesc, srv) +} + +func _LibraryService_GetCategories_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetCategoriesRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(LibraryServiceServer).GetCategories(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: LibraryService_GetCategories_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(LibraryServiceServer).GetCategories(ctx, req.(*GetCategoriesRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _LibraryService_GetFiles_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetLibraryFilesRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(LibraryServiceServer).GetFiles(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: LibraryService_GetFiles_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(LibraryServiceServer).GetFiles(ctx, req.(*GetLibraryFilesRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _LibraryService_UploadFile_Handler(srv interface{}, stream grpc.ServerStream) error { + return srv.(LibraryServiceServer).UploadFile(&grpc.GenericServerStream[UploadLibraryFileRequest, UploadLibraryFileResponse]{ServerStream: stream}) +} + +// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. +type LibraryService_UploadFileServer = grpc.ClientStreamingServer[UploadLibraryFileRequest, UploadLibraryFileResponse] + +func _LibraryService_DeleteFile_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(DeleteLibraryFileRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(LibraryServiceServer).DeleteFile(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: LibraryService_DeleteFile_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(LibraryServiceServer).DeleteFile(ctx, req.(*DeleteLibraryFileRequest)) + } + return interceptor(ctx, in, info, handler) +} + +// LibraryService_ServiceDesc is the grpc.ServiceDesc for LibraryService service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var LibraryService_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "cloudprint.LibraryService", + HandlerType: (*LibraryServiceServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "GetCategories", + Handler: _LibraryService_GetCategories_Handler, + }, + { + MethodName: "GetFiles", + Handler: _LibraryService_GetFiles_Handler, + }, + { + MethodName: "DeleteFile", + Handler: _LibraryService_DeleteFile_Handler, + }, + }, + Streams: []grpc.StreamDesc{ + { + StreamName: "UploadFile", + Handler: _LibraryService_UploadFile_Handler, + ClientStreams: true, + }, + }, + Metadata: "cloudprint.proto", +} + +const ( + PriceService_GetPriceList_FullMethodName = "/cloudprint.PriceService/GetPriceList" + PriceService_CreatePriceItem_FullMethodName = "/cloudprint.PriceService/CreatePriceItem" + PriceService_UpdatePriceItem_FullMethodName = "/cloudprint.PriceService/UpdatePriceItem" +) + +// PriceServiceClient is the client API for PriceService service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +type PriceServiceClient interface { + GetPriceList(ctx context.Context, in *GetPriceListRequest, opts ...grpc.CallOption) (*PriceListResponse, error) + CreatePriceItem(ctx context.Context, in *CreatePriceItemRequest, opts ...grpc.CallOption) (*PriceItem, error) + UpdatePriceItem(ctx context.Context, in *UpdatePriceItemRequest, opts ...grpc.CallOption) (*PriceItem, error) +} + +type priceServiceClient struct { + cc grpc.ClientConnInterface +} + +func NewPriceServiceClient(cc grpc.ClientConnInterface) PriceServiceClient { + return &priceServiceClient{cc} +} + +func (c *priceServiceClient) GetPriceList(ctx context.Context, in *GetPriceListRequest, opts ...grpc.CallOption) (*PriceListResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(PriceListResponse) + err := c.cc.Invoke(ctx, PriceService_GetPriceList_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *priceServiceClient) CreatePriceItem(ctx context.Context, in *CreatePriceItemRequest, opts ...grpc.CallOption) (*PriceItem, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(PriceItem) + err := c.cc.Invoke(ctx, PriceService_CreatePriceItem_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *priceServiceClient) UpdatePriceItem(ctx context.Context, in *UpdatePriceItemRequest, opts ...grpc.CallOption) (*PriceItem, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(PriceItem) + err := c.cc.Invoke(ctx, PriceService_UpdatePriceItem_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +// PriceServiceServer is the server API for PriceService service. +// All implementations must embed UnimplementedPriceServiceServer +// for forward compatibility. +type PriceServiceServer interface { + GetPriceList(context.Context, *GetPriceListRequest) (*PriceListResponse, error) + CreatePriceItem(context.Context, *CreatePriceItemRequest) (*PriceItem, error) + UpdatePriceItem(context.Context, *UpdatePriceItemRequest) (*PriceItem, error) + mustEmbedUnimplementedPriceServiceServer() +} + +// UnimplementedPriceServiceServer must be embedded to have +// forward compatible implementations. +// +// NOTE: this should be embedded by value instead of pointer to avoid a nil +// pointer dereference when methods are called. +type UnimplementedPriceServiceServer struct{} + +func (UnimplementedPriceServiceServer) GetPriceList(context.Context, *GetPriceListRequest) (*PriceListResponse, error) { + return nil, status.Error(codes.Unimplemented, "method GetPriceList not implemented") +} +func (UnimplementedPriceServiceServer) CreatePriceItem(context.Context, *CreatePriceItemRequest) (*PriceItem, error) { + return nil, status.Error(codes.Unimplemented, "method CreatePriceItem not implemented") +} +func (UnimplementedPriceServiceServer) UpdatePriceItem(context.Context, *UpdatePriceItemRequest) (*PriceItem, error) { + return nil, status.Error(codes.Unimplemented, "method UpdatePriceItem not implemented") +} +func (UnimplementedPriceServiceServer) mustEmbedUnimplementedPriceServiceServer() {} +func (UnimplementedPriceServiceServer) testEmbeddedByValue() {} + +// UnsafePriceServiceServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to PriceServiceServer will +// result in compilation errors. +type UnsafePriceServiceServer interface { + mustEmbedUnimplementedPriceServiceServer() +} + +func RegisterPriceServiceServer(s grpc.ServiceRegistrar, srv PriceServiceServer) { + // If the following call panics, it indicates UnimplementedPriceServiceServer was + // embedded by pointer and is nil. This will cause panics if an + // unimplemented method is ever invoked, so we test this at initialization + // time to prevent it from happening at runtime later due to I/O. + if t, ok := srv.(interface{ testEmbeddedByValue() }); ok { + t.testEmbeddedByValue() + } + s.RegisterService(&PriceService_ServiceDesc, srv) +} + +func _PriceService_GetPriceList_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetPriceListRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(PriceServiceServer).GetPriceList(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: PriceService_GetPriceList_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(PriceServiceServer).GetPriceList(ctx, req.(*GetPriceListRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _PriceService_CreatePriceItem_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(CreatePriceItemRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(PriceServiceServer).CreatePriceItem(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: PriceService_CreatePriceItem_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(PriceServiceServer).CreatePriceItem(ctx, req.(*CreatePriceItemRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _PriceService_UpdatePriceItem_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(UpdatePriceItemRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(PriceServiceServer).UpdatePriceItem(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: PriceService_UpdatePriceItem_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(PriceServiceServer).UpdatePriceItem(ctx, req.(*UpdatePriceItemRequest)) + } + return interceptor(ctx, in, info, handler) +} + +// PriceService_ServiceDesc is the grpc.ServiceDesc for PriceService service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var PriceService_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "cloudprint.PriceService", + HandlerType: (*PriceServiceServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "GetPriceList", + Handler: _PriceService_GetPriceList_Handler, + }, + { + MethodName: "CreatePriceItem", + Handler: _PriceService_CreatePriceItem_Handler, + }, + { + MethodName: "UpdatePriceItem", + Handler: _PriceService_UpdatePriceItem_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "cloudprint.proto", +} + +const ( + PayService_CreateWxPayOrder_FullMethodName = "/cloudprint.PayService/CreateWxPayOrder" + PayService_QueryPayStatus_FullMethodName = "/cloudprint.PayService/QueryPayStatus" + PayService_HandlePayCallback_FullMethodName = "/cloudprint.PayService/HandlePayCallback" + PayService_PayByBalance_FullMethodName = "/cloudprint.PayService/PayByBalance" +) + +// PayServiceClient is the client API for PayService service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +type PayServiceClient interface { + CreateWxPayOrder(ctx context.Context, in *WxPayRequest, opts ...grpc.CallOption) (*WxPayResponse, error) + QueryPayStatus(ctx context.Context, in *QueryPayStatusRequest, opts ...grpc.CallOption) (*PayStatusResponse, error) + HandlePayCallback(ctx context.Context, in *PayCallbackRequest, opts ...grpc.CallOption) (*PayCallbackResponse, error) + PayByBalance(ctx context.Context, in *PayByBalanceRequest, opts ...grpc.CallOption) (*StatusResponse, error) +} + +type payServiceClient struct { + cc grpc.ClientConnInterface +} + +func NewPayServiceClient(cc grpc.ClientConnInterface) PayServiceClient { + return &payServiceClient{cc} +} + +func (c *payServiceClient) CreateWxPayOrder(ctx context.Context, in *WxPayRequest, opts ...grpc.CallOption) (*WxPayResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(WxPayResponse) + err := c.cc.Invoke(ctx, PayService_CreateWxPayOrder_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *payServiceClient) QueryPayStatus(ctx context.Context, in *QueryPayStatusRequest, opts ...grpc.CallOption) (*PayStatusResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(PayStatusResponse) + err := c.cc.Invoke(ctx, PayService_QueryPayStatus_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *payServiceClient) HandlePayCallback(ctx context.Context, in *PayCallbackRequest, opts ...grpc.CallOption) (*PayCallbackResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(PayCallbackResponse) + err := c.cc.Invoke(ctx, PayService_HandlePayCallback_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *payServiceClient) PayByBalance(ctx context.Context, in *PayByBalanceRequest, opts ...grpc.CallOption) (*StatusResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(StatusResponse) + err := c.cc.Invoke(ctx, PayService_PayByBalance_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +// PayServiceServer is the server API for PayService service. +// All implementations must embed UnimplementedPayServiceServer +// for forward compatibility. +type PayServiceServer interface { + CreateWxPayOrder(context.Context, *WxPayRequest) (*WxPayResponse, error) + QueryPayStatus(context.Context, *QueryPayStatusRequest) (*PayStatusResponse, error) + HandlePayCallback(context.Context, *PayCallbackRequest) (*PayCallbackResponse, error) + PayByBalance(context.Context, *PayByBalanceRequest) (*StatusResponse, error) + mustEmbedUnimplementedPayServiceServer() +} + +// UnimplementedPayServiceServer must be embedded to have +// forward compatible implementations. +// +// NOTE: this should be embedded by value instead of pointer to avoid a nil +// pointer dereference when methods are called. +type UnimplementedPayServiceServer struct{} + +func (UnimplementedPayServiceServer) CreateWxPayOrder(context.Context, *WxPayRequest) (*WxPayResponse, error) { + return nil, status.Error(codes.Unimplemented, "method CreateWxPayOrder not implemented") +} +func (UnimplementedPayServiceServer) QueryPayStatus(context.Context, *QueryPayStatusRequest) (*PayStatusResponse, error) { + return nil, status.Error(codes.Unimplemented, "method QueryPayStatus not implemented") +} +func (UnimplementedPayServiceServer) HandlePayCallback(context.Context, *PayCallbackRequest) (*PayCallbackResponse, error) { + return nil, status.Error(codes.Unimplemented, "method HandlePayCallback not implemented") +} +func (UnimplementedPayServiceServer) PayByBalance(context.Context, *PayByBalanceRequest) (*StatusResponse, error) { + return nil, status.Error(codes.Unimplemented, "method PayByBalance not implemented") +} +func (UnimplementedPayServiceServer) mustEmbedUnimplementedPayServiceServer() {} +func (UnimplementedPayServiceServer) testEmbeddedByValue() {} + +// UnsafePayServiceServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to PayServiceServer will +// result in compilation errors. +type UnsafePayServiceServer interface { + mustEmbedUnimplementedPayServiceServer() +} + +func RegisterPayServiceServer(s grpc.ServiceRegistrar, srv PayServiceServer) { + // If the following call panics, it indicates UnimplementedPayServiceServer was + // embedded by pointer and is nil. This will cause panics if an + // unimplemented method is ever invoked, so we test this at initialization + // time to prevent it from happening at runtime later due to I/O. + if t, ok := srv.(interface{ testEmbeddedByValue() }); ok { + t.testEmbeddedByValue() + } + s.RegisterService(&PayService_ServiceDesc, srv) +} + +func _PayService_CreateWxPayOrder_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(WxPayRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(PayServiceServer).CreateWxPayOrder(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: PayService_CreateWxPayOrder_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(PayServiceServer).CreateWxPayOrder(ctx, req.(*WxPayRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _PayService_QueryPayStatus_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryPayStatusRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(PayServiceServer).QueryPayStatus(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: PayService_QueryPayStatus_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(PayServiceServer).QueryPayStatus(ctx, req.(*QueryPayStatusRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _PayService_HandlePayCallback_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(PayCallbackRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(PayServiceServer).HandlePayCallback(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: PayService_HandlePayCallback_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(PayServiceServer).HandlePayCallback(ctx, req.(*PayCallbackRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _PayService_PayByBalance_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(PayByBalanceRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(PayServiceServer).PayByBalance(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: PayService_PayByBalance_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(PayServiceServer).PayByBalance(ctx, req.(*PayByBalanceRequest)) + } + return interceptor(ctx, in, info, handler) +} + +// PayService_ServiceDesc is the grpc.ServiceDesc for PayService service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var PayService_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "cloudprint.PayService", + HandlerType: (*PayServiceServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "CreateWxPayOrder", + Handler: _PayService_CreateWxPayOrder_Handler, + }, + { + MethodName: "QueryPayStatus", + Handler: _PayService_QueryPayStatus_Handler, + }, + { + MethodName: "HandlePayCallback", + Handler: _PayService_HandlePayCallback_Handler, + }, + { + MethodName: "PayByBalance", + Handler: _PayService_PayByBalance_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "cloudprint.proto", +} + +const ( + AdminService_Login_FullMethodName = "/cloudprint.AdminService/Login" + AdminService_GetStatistics_FullMethodName = "/cloudprint.AdminService/GetStatistics" +) + +// AdminServiceClient is the client API for AdminService service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +type AdminServiceClient interface { + Login(ctx context.Context, in *AdminLoginRequest, opts ...grpc.CallOption) (*AdminLoginResponse, error) + GetStatistics(ctx context.Context, in *GetStatisticsRequest, opts ...grpc.CallOption) (*Statistics, error) +} + +type adminServiceClient struct { + cc grpc.ClientConnInterface +} + +func NewAdminServiceClient(cc grpc.ClientConnInterface) AdminServiceClient { + return &adminServiceClient{cc} +} + +func (c *adminServiceClient) Login(ctx context.Context, in *AdminLoginRequest, opts ...grpc.CallOption) (*AdminLoginResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(AdminLoginResponse) + err := c.cc.Invoke(ctx, AdminService_Login_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *adminServiceClient) GetStatistics(ctx context.Context, in *GetStatisticsRequest, opts ...grpc.CallOption) (*Statistics, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(Statistics) + err := c.cc.Invoke(ctx, AdminService_GetStatistics_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +// AdminServiceServer is the server API for AdminService service. +// All implementations must embed UnimplementedAdminServiceServer +// for forward compatibility. +type AdminServiceServer interface { + Login(context.Context, *AdminLoginRequest) (*AdminLoginResponse, error) + GetStatistics(context.Context, *GetStatisticsRequest) (*Statistics, error) + mustEmbedUnimplementedAdminServiceServer() +} + +// UnimplementedAdminServiceServer must be embedded to have +// forward compatible implementations. +// +// NOTE: this should be embedded by value instead of pointer to avoid a nil +// pointer dereference when methods are called. +type UnimplementedAdminServiceServer struct{} + +func (UnimplementedAdminServiceServer) Login(context.Context, *AdminLoginRequest) (*AdminLoginResponse, error) { + return nil, status.Error(codes.Unimplemented, "method Login not implemented") +} +func (UnimplementedAdminServiceServer) GetStatistics(context.Context, *GetStatisticsRequest) (*Statistics, error) { + return nil, status.Error(codes.Unimplemented, "method GetStatistics not implemented") +} +func (UnimplementedAdminServiceServer) mustEmbedUnimplementedAdminServiceServer() {} +func (UnimplementedAdminServiceServer) testEmbeddedByValue() {} + +// UnsafeAdminServiceServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to AdminServiceServer will +// result in compilation errors. +type UnsafeAdminServiceServer interface { + mustEmbedUnimplementedAdminServiceServer() +} + +func RegisterAdminServiceServer(s grpc.ServiceRegistrar, srv AdminServiceServer) { + // If the following call panics, it indicates UnimplementedAdminServiceServer was + // embedded by pointer and is nil. This will cause panics if an + // unimplemented method is ever invoked, so we test this at initialization + // time to prevent it from happening at runtime later due to I/O. + if t, ok := srv.(interface{ testEmbeddedByValue() }); ok { + t.testEmbeddedByValue() + } + s.RegisterService(&AdminService_ServiceDesc, srv) +} + +func _AdminService_Login_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(AdminLoginRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(AdminServiceServer).Login(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: AdminService_Login_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(AdminServiceServer).Login(ctx, req.(*AdminLoginRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _AdminService_GetStatistics_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetStatisticsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(AdminServiceServer).GetStatistics(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: AdminService_GetStatistics_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(AdminServiceServer).GetStatistics(ctx, req.(*GetStatisticsRequest)) + } + return interceptor(ctx, in, info, handler) +} + +// AdminService_ServiceDesc is the grpc.ServiceDesc for AdminService service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var AdminService_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "cloudprint.AdminService", + HandlerType: (*AdminServiceServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "Login", + Handler: _AdminService_Login_Handler, + }, + { + MethodName: "GetStatistics", + Handler: _AdminService_GetStatistics_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "cloudprint.proto", +} diff --git a/cloudprint-backend/scripts/db.sql b/cloudprint-backend/scripts/db.sql new file mode 100644 index 0000000..13c24db --- /dev/null +++ b/cloudprint-backend/scripts/db.sql @@ -0,0 +1,182 @@ +-- 云印享 - 付费打印服务系统数据库初始化脚本 +-- 数据库: cloudprint + +CREATE DATABASE IF NOT EXISTS `cloudprint` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; +USE `cloudprint`; + +-- 用户表 +CREATE TABLE IF NOT EXISTS `user` ( + `id` INT PRIMARY KEY AUTO_INCREMENT, + `openid` VARCHAR(64) UNIQUE NOT NULL COMMENT '微信OpenID', + `nickname` VARCHAR(128) DEFAULT '' COMMENT '昵称', + `avatar` VARCHAR(512) DEFAULT '' COMMENT '头像URL', + `balance` DECIMAL(10,2) DEFAULT 0.00 COMMENT '余额', + `created_at` DATETIME DEFAULT CURRENT_TIMESTAMP, + `updated_at` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + INDEX `idx_openid` (`openid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户表'; + +-- 管理员表 +CREATE TABLE IF NOT EXISTS `admin` ( + `id` INT PRIMARY KEY AUTO_INCREMENT, + `username` VARCHAR(64) UNIQUE NOT NULL COMMENT '用户名', + `password_hash` VARCHAR(256) NOT NULL COMMENT '密码哈希', + `nickname` VARCHAR(128) DEFAULT '' COMMENT '昵称', + `role` TINYINT DEFAULT 1 COMMENT '1:普通管理员 2:超级管理员', + `created_at` DATETIME DEFAULT CURRENT_TIMESTAMP, + INDEX `idx_username` (`username`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='管理员表'; + +-- 打印机表 +CREATE TABLE IF NOT EXISTS `printer` ( + `id` INT PRIMARY KEY AUTO_INCREMENT, + `name` VARCHAR(128) UNIQUE NOT NULL COMMENT '系统打印机名', + `display_name` VARCHAR(128) NOT NULL COMMENT '显示名称', + `api_key` VARCHAR(64) UNIQUE NOT NULL COMMENT '客户端认证Key', + `is_active` TINYINT DEFAULT 1 COMMENT '是否启用', + `status` TINYINT DEFAULT 0 COMMENT '0:空闲 1:打印中 2:离线', + `last_heartbeat` DATETIME DEFAULT NULL COMMENT '最后心跳时间', + `created_at` DATETIME DEFAULT CURRENT_TIMESTAMP, + INDEX `idx_name` (`name`), + INDEX `idx_api_key` (`api_key`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='打印机表'; + +-- 订单表 +CREATE TABLE IF NOT EXISTS `order` ( + `id` INT PRIMARY KEY AUTO_INCREMENT, + `order_no` VARCHAR(32) UNIQUE NOT NULL COMMENT '订单号', + `user_id` INT NOT NULL COMMENT '用户ID', + `status` TINYINT DEFAULT 0 COMMENT '0:待支付 1:已支付 2:打印中 3:已完成 4:已取消', + `total_amount` DECIMAL(10,2) NOT NULL COMMENT '总金额', + `remark` VARCHAR(512) DEFAULT '' COMMENT '备注', + `created_at` DATETIME DEFAULT CURRENT_TIMESTAMP, + `paid_at` DATETIME DEFAULT NULL COMMENT '支付时间', + INDEX `idx_order_no` (`order_no`), + INDEX `idx_user_id` (`user_id`), + INDEX `idx_status` (`status`), + INDEX `idx_created_at` (`created_at`), + FOREIGN KEY (`user_id`) REFERENCES `user`(`id`) ON DELETE RESTRICT +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='订单表'; + +-- 订单明细表 +CREATE TABLE IF NOT EXISTS `order_item` ( + `id` INT PRIMARY KEY AUTO_INCREMENT, + `order_id` INT NOT NULL COMMENT '订单ID', + `file_id` INT NOT NULL COMMENT '文件ID', + `printer_id` INT DEFAULT NULL COMMENT '打印机ID', + `copies` INT DEFAULT 1 COMMENT '份数', + `color` TINYINT DEFAULT 0 COMMENT '是否彩色 0:黑白 1:彩色', + `duplex` TINYINT DEFAULT 0 COMMENT '是否双面 0:单面 1:双面', + `page_range` VARCHAR(64) DEFAULT 'all' COMMENT '页面范围', + `price` DECIMAL(10,2) NOT NULL COMMENT '价格', + INDEX `idx_order_id` (`order_id`), + INDEX `idx_file_id` (`file_id`), + FOREIGN KEY (`order_id`) REFERENCES `order`(`id`) ON DELETE CASCADE, + FOREIGN KEY (`file_id`) REFERENCES `file`(`id`) ON DELETE RESTRICT +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='订单明细表'; + +-- 文件表 +CREATE TABLE IF NOT EXISTS `file` ( + `id` INT PRIMARY KEY AUTO_INCREMENT, + `file_name` VARCHAR(256) NOT NULL COMMENT '文件名', + `file_path` VARCHAR(512) NOT NULL COMMENT '文件路径', + `file_type` VARCHAR(32) NOT NULL COMMENT '文件类型', + `file_size` BIGINT NOT NULL COMMENT '文件大小(字节)', + `uploader_type` VARCHAR(16) NOT NULL COMMENT '上传者类型: user/admin/system', + `uploader_id` INT NOT NULL COMMENT '上传者ID', + `created_at` DATETIME DEFAULT CURRENT_TIMESTAMP, + INDEX `idx_uploader` (`uploader_type`, `uploader_id`), + INDEX `idx_file_type` (`file_type`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='文件表'; + +-- 文库分类表 +CREATE TABLE IF NOT EXISTS `library_category` ( + `id` INT PRIMARY KEY AUTO_INCREMENT, + `name` VARCHAR(128) NOT NULL COMMENT '分类名称', + `icon` VARCHAR(128) DEFAULT '' COMMENT '图标', + `sort_order` INT DEFAULT 0 COMMENT '排序', + `created_at` DATETIME DEFAULT CURRENT_TIMESTAMP +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='文库分类表'; + +-- 文库文件表 +CREATE TABLE IF NOT EXISTS `library_file` ( + `id` INT PRIMARY KEY AUTO_INCREMENT, + `category_id` INT NOT NULL COMMENT '分类ID', + `file_id` INT NOT NULL COMMENT '文件ID', + `title` VARCHAR(256) NOT NULL COMMENT '标题', + `description` VARCHAR(512) DEFAULT '' COMMENT '描述', + `page_count` INT DEFAULT 0 COMMENT '页数', + `download_count` INT DEFAULT 0 COMMENT '下载次数', + `created_at` DATETIME DEFAULT CURRENT_TIMESTAMP, + INDEX `idx_category_id` (`category_id`), + INDEX `idx_file_id` (`file_id`), + FOREIGN KEY (`category_id`) REFERENCES `library_category`(`id`) ON DELETE CASCADE, + FOREIGN KEY (`file_id`) REFERENCES `file`(`id`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='文库文件表'; + +-- 打印任务表 +CREATE TABLE IF NOT EXISTS `print_job` ( + `id` INT PRIMARY KEY AUTO_INCREMENT, + `job_no` VARCHAR(32) UNIQUE NOT NULL COMMENT '任务号', + `printer_id` INT NOT NULL COMMENT '打印机ID', + `order_item_id` INT NOT NULL COMMENT '订单明细ID', + `status` VARCHAR(16) DEFAULT 'pending' COMMENT 'pending/printing/completed/failed/cancelled', + `progress` INT DEFAULT 0 COMMENT '进度(0-100)', + `error_msg` VARCHAR(512) DEFAULT '' COMMENT '错误信息', + `started_at` DATETIME DEFAULT NULL COMMENT '开始时间', + `completed_at` DATETIME DEFAULT NULL COMMENT '完成时间', + INDEX `idx_job_no` (`job_no`), + INDEX `idx_printer_id` (`printer_id`), + INDEX `idx_status` (`status`), + FOREIGN KEY (`printer_id`) REFERENCES `printer`(`id`) ON DELETE RESTRICT, + FOREIGN KEY (`order_item_id`) REFERENCES `order_item`(`id`) ON DELETE RESTRICT +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='打印任务表'; + +-- 价目表 +CREATE TABLE IF NOT EXISTS `price_list` ( + `id` INT PRIMARY KEY AUTO_INCREMENT, + `name` VARCHAR(128) NOT NULL COMMENT '项目名称', + `type` VARCHAR(32) NOT NULL COMMENT '纸张类型: A4/A3/照片纸', + `price` DECIMAL(10,2) NOT NULL COMMENT '单价', + `unit` VARCHAR(16) NOT NULL COMMENT '单位: 页/张/份', + `color_enabled` TINYINT DEFAULT 1 COMMENT '是否支持彩色', + `is_active` TINYINT DEFAULT 1 COMMENT '是否启用', + `sort_order` INT DEFAULT 0 COMMENT '排序', + `created_at` DATETIME DEFAULT CURRENT_TIMESTAMP, + INDEX `idx_type` (`type`), + INDEX `idx_is_active` (`is_active`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='价目表'; + +-- 支付记录表 +CREATE TABLE IF NOT EXISTS `payment` ( + `id` INT PRIMARY KEY AUTO_INCREMENT, + `order_no` VARCHAR(32) UNIQUE NOT NULL COMMENT '订单号', + `pay_type` VARCHAR(16) DEFAULT 'wechat' COMMENT '支付类型: wechat/balance', + `pay_status` TINYINT DEFAULT 0 COMMENT '0:待支付 1:支付中 2:成功 3:失败', + `transaction_id` VARCHAR(64) DEFAULT '' COMMENT '微信交易号', + `paid_at` DATETIME DEFAULT NULL COMMENT '支付时间', + `created_at` DATETIME DEFAULT CURRENT_TIMESTAMP, + INDEX `idx_order_no` (`order_no`), + INDEX `idx_pay_status` (`pay_status`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='支付记录表'; + +-- 初始化管理员账号 (密码: admin123) +-- 密码哈希使用 bcrypt 生成 +INSERT INTO `admin` (`username`, `password_hash`, `nickname`, `role`) VALUES +('admin', '$2a$10$N9qo8uLOickgx2ZMRZoMy.MqrqJlmZ2j3.N9qo8uLOickgx2ZMRZoG', '系统管理员', 2); + +-- 初始化默认价目表 +INSERT INTO `price_list` (`name`, `type`, `price`, `unit`, `color_enabled`, `is_active`, `sort_order`) VALUES +('A4黑白打印', 'A4', 0.10, '页', 0, 1, 1), +('A4彩色打印', 'A4', 0.30, '页', 1, 1, 2), +('A3黑白打印', 'A3', 0.20, '页', 0, 1, 3), +('A3彩色打印', 'A3', 0.60, '页', 1, 1, 4), +('照片打印', '照片纸', 2.00, '张', 1, 1, 5); + +-- 初始化默认文库分类 +INSERT INTO `library_category` (`name`, `icon`, `sort_order`) VALUES +('学习资料', 'book', 1), +('考试真题', 'exam', 2), +('简历模板', 'resume', 3), +('合同协议', 'contract', 4), +('其他资料', 'other', 5);