diff --git a/apis/domain/certify.go b/apis/domain/certify.go new file mode 100644 index 0000000..5c1f761 --- /dev/null +++ b/apis/domain/certify.go @@ -0,0 +1,73 @@ +package domain + +import ( + "github.com/XingfenD/rainyun_api_go_sdk/apis/common" + "github.com/XingfenD/rainyun_api_go_sdk/constant" +) + +// 备案域名过白 +// +// domain: 域名 +// +// region: 区域:cn-sq1/cn-nb1/cn-xy1/cn-cq1 +func (s *DomainService) AddDomainToWhiteList(domain, region string) (*common.BasicOperationResponse, error) { + path := "/product/domain_white_list" + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_POST, path, nil, AddDomainToWhiteListRequest{ + Domain: domain, + Region: region, + }, &resp) + + return &resp, err +} + +// 获取域名白名单列表 +func (s *DomainService) GetDomainWhiteList(req *GetDomainWhiteListRequest) (*GetDomainWhiteListResponse, error) { + path := "/product/domain/whitelist" + + var resp GetDomainWhiteListResponse + querys, err := common.MarshalQueryParams(req) + if err != nil { + return nil, err + } + err = s.client.Do(constant.HTTPMethod_GET, path, querys, nil, &resp) + return &resp, err +} + +// 获取已验证域名列表 +func (s *DomainService) GetVerifiedDomainList(req *GetVerifiedDomainListRequest) (*GetVerifiedDomainListResponse, error) { + path := "/product/domain/certify" + + var resp GetVerifiedDomainListResponse + querys, err := common.MarshalQueryParams(req) + if err != nil { + return nil, err + } + err = s.client.Do(constant.HTTPMethod_GET, path, querys, nil, &resp) + return &resp, err +} + +// 添加域名认证 +// +// domain: 域名 +func (s *DomainService) AddDomainCertify(domain string) (*GetDomainVerificationInfoResponse, error) { + path := "/product/domain/certify" + + var resp GetDomainVerificationInfoResponse + err := s.client.Do(constant.HTTPMethod_POST, path, nil, AddDomainVerificationRequest{Domain: domain}, &resp) + + return &resp, err +} + +// 域名认证校验 +// +// domain: 域名 +func (s *DomainService) VerifyDomainCertify(domain string) (*common.BasicOperationResponse, error) { + path := "/product/domain/certify/verify" + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_POST, path, nil, AddDomainVerificationRequest{Domain: domain}, &resp) + + return &resp, err +} diff --git a/apis/domain/client.go b/apis/domain/client.go new file mode 100644 index 0000000..cc0925c --- /dev/null +++ b/apis/domain/client.go @@ -0,0 +1,11 @@ +package domain + +import "github.com/XingfenD/rainyun_api_go_sdk/apis" + +type DomainService struct { + client *apis.RyClient +} + +func NewDomainService(c *apis.RyClient) *DomainService { + return &DomainService{client: c} +} diff --git a/apis/domain/dns.go b/apis/domain/dns.go new file mode 100644 index 0000000..76c89ad --- /dev/null +++ b/apis/domain/dns.go @@ -0,0 +1,72 @@ +package domain + +import ( + "fmt" + + "github.com/XingfenD/rainyun_api_go_sdk/apis/common" + "github.com/XingfenD/rainyun_api_go_sdk/constant" +) + +// 添加域名DNS解析 +// +// id: 域名ID +func (s *DomainService) AddDomainDNSRecord(id int, req *AddDomainDNSRecordRequest) (*common.BasicOperationResponse, error) { + path := fmt.Sprintf("/product/domain/%d/dns", id) + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_POST, path, nil, req, &resp) + + return &resp, err +} + +// 修改域名DNS解析 +// +// req.RecordID 指定要修改的记录 +func (s *DomainService) UpdateDomainDNSRecord(id int, req *AddDomainDNSRecordRequest) (*common.BasicOperationResponse, error) { + path := fmt.Sprintf("/product/domain/%d/dns", id) + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_PATCH, path, nil, req, &resp) + + return &resp, err +} + +// 删除域名DNS解析 +func (s *DomainService) DeleteDomainDNSRecord(id, recordID int) (*common.BasicOperationResponse, error) { + path := fmt.Sprintf("/product/domain/%d/dns", id) + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_DELETE, path, nil, DeleteDomainDNSRecordRequest{RecordID: recordID}, &resp) + + return &resp, err +} + +// 添加域名DNSSEC +func (s *DomainService) AddDomainDNSSEC(id int, req *AddDomainDNSSECRequest) (*common.BasicOperationResponse, error) { + path := fmt.Sprintf("/product/domain/%d/dnssec", id) + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_POST, path, nil, req, &resp) + + return &resp, err +} + +// 删除域名DNSSEC +func (s *DomainService) DeleteDomainDNSSEC(id int, req *DeleteDomainDNSSECRequest) (*common.BasicOperationResponse, error) { + path := fmt.Sprintf("/product/domain/%d/dnssec/delete", id) + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_POST, path, nil, req, &resp) + + return &resp, err +} + +// 同步域名DNSSEC +func (s *DomainService) SyncDomainDNSSEC(id int) (*common.BasicOperationResponse, error) { + path := fmt.Sprintf("/product/domain/%d/dnssec/sync", id) + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_POST, path, nil, nil, &resp) + + return &resp, err +} diff --git a/apis/domain/domain.go b/apis/domain/domain.go new file mode 100644 index 0000000..58d78a8 --- /dev/null +++ b/apis/domain/domain.go @@ -0,0 +1,104 @@ +package domain + +import ( + "fmt" + + "github.com/XingfenD/rainyun_api_go_sdk/apis/common" + "github.com/XingfenD/rainyun_api_go_sdk/constant" +) + +// 关闭域名锁定 +func (s *DomainService) UnlockDomain(id int) (*common.BasicOperationResponse, error) { + path := fmt.Sprintf("/product/domain/%d/lock/disable", id) + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_PUT, path, nil, nil, &resp) + + return &resp, err +} + +// 开启域名锁定 +func (s *DomainService) LockDomain(id int) (*common.BasicOperationResponse, error) { + path := fmt.Sprintf("/product/domain/%d/lock/enable", id) + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_PUT, path, nil, nil, &resp) + + return &resp, err +} + +// 修改域名NS服务器 +func (s *DomainService) UpdateDomainNS(id int, nss []string) (*common.BasicOperationResponse, error) { + path := fmt.Sprintf("/product/domain/%d/nameservers", id) + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_PUT, path, nil, UpdateDomainNSRequest{NameServers: nss}, &resp) + + return &resp, err +} + +// 重置域名NS服务器 +func (s *DomainService) ResetDomainNS(id int) (*common.BasicOperationResponse, error) { + path := fmt.Sprintf("/product/domain/%d/nameservers/reset", id) + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_POST, path, nil, nil, &resp) + + return &resp, err +} + +// 续费域名 +func (s *DomainService) RenewDomain(id, years int) (*common.BasicOperationResponse, error) { + path := fmt.Sprintf("/product/domain/%d/renew", id) + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_POST, path, nil, RenewDomainRequest{Years: years}, &resp) + + return &resp, err +} + +// 域名过户 +func (s *DomainService) TransferDomain(id int, req *DomainTransferRequest) (*common.BasicOperationResponse, error) { + path := fmt.Sprintf("/product/domain/%d/transfer", id) + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_POST, path, nil, req, &resp) + + return &resp, err +} + +// 更新域名管理密码 +func (s *DomainService) UpdateDomainPassword(id int, password string) (*common.BasicOperationResponse, error) { + path := fmt.Sprintf("/product/domain/%d/password", id) + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_POST, path, nil, UpdateDomainPasswordRequest{Password: password}, &resp) + + return &resp, err +} + +// 获取域名whois信息 +func (s *DomainService) GetDomainWhoisInfo(req *GetDomainWhoisInfoRequest) (*GetDomainWhoisInfoResponse, error) { + path := "/product/domain/whois" + + var resp GetDomainWhoisInfoResponse + querys, err := common.MarshalQueryParams(req) + if err != nil { + return nil, err + } + err = s.client.Do(constant.HTTPMethod_GET, path, querys, nil, &resp) + return &resp, err +} + +// 检查域名能否注册 +func (s *DomainService) CheckDomainAvailability(req *CheckDomainAvailableRequest) (*CheckDomainAvailableResponse, error) { + path := "/product/domain/check" + + var resp CheckDomainAvailableResponse + querys, err := common.MarshalQueryParams(req) + if err != nil { + return nil, err + } + err = s.client.Do(constant.HTTPMethod_GET, path, querys, nil, &resp) + return &resp, err +} diff --git a/apis/domain/model.go b/apis/domain/model.go new file mode 100644 index 0000000..7756105 --- /dev/null +++ b/apis/domain/model.go @@ -0,0 +1,264 @@ +package domain + +import "github.com/XingfenD/rainyun_api_go_sdk/apis/common" + +// 添加域名过白请求 +type AddDomainToWhiteListRequest struct { + Domain string `json:"domain"` // 域名 + Region string `json:"region"` // 区域:cn-sq1/cn-nb1/cn-xy1/cn-cq1 +} + +// 获取域名白名单列表查询参数 +type GetDomainWhiteListRequest struct { + Options common.StandQueryParameters `json:"options"` +} + +// 域名白名单列表响应 +type GetDomainWhiteListResponse struct { + Code int `json:"code"` + Data DomainWhiteListData `json:"data"` +} + +// 域名白名单列表数据 +type DomainWhiteListData struct { + TotalRecords int `json:"TotalRecords"` + Records []DomainWhiteListRecord `json:"Records"` +} + +// 域名白名单记录 +type DomainWhiteListRecord struct { + ID int `json:"id"` // ID + UID int `json:"uid"` + Domain string `json:"domain"` // 域名 + SiteLicense string `json:"site_license"` // 备案号(貌似只有早期过白的会有这个) + Region string `json:"region"` // 区域 + AddTime int `json:"add_time"` // 时间 + Status int `json:"status"` // 状态: 1:已处理 +} + +// 获取已验证域名列表查询参数 +type GetVerifiedDomainListRequest struct { + Options common.StandQueryParameters `json:"options"` +} + +// 已验证域名列表响应 +type GetVerifiedDomainListResponse struct { + Code int `json:"code"` + Data VerifiedDomainListData `json:"data"` +} + +// 已验证域名列表数据 +type VerifiedDomainListData struct { + TotalRecords int `json:"TotalRecords"` + Records []VerifiedDomainRecord `json:"Records"` +} + +// 已验证域名记录 +type VerifiedDomainRecord struct { + ID int `json:"id"` // id + UID int `json:"uid"` + Domain string `json:"domain"` // 域名 + AddTime int `json:"add_time"` // 时间 +} + +// 添加域名认证请求 +type AddDomainVerificationRequest struct { + Domain string `json:"domain"` +} + +// 域名验证信息响应 +type GetDomainVerificationInfoResponse struct { + Code int `json:"code"` + Data DomainVerificationData `json:"data"` +} + +// 域名验证信息数据 +type DomainVerificationData struct { + Rr string `json:"rr"` // 主机名 + TopDomain string `json:"top_domain"` // 主域名 + Record string `json:"record"` // 记录值 +} + +// 添加域名DNS解析请求 +type AddDomainDNSRecordRequest struct { + Host string `json:"host"` // 主机名 + Level int `json:"level"` // 优先等级 + Line string `json:"line"` // 线路,必须有一个默认的才可以 DEFAULT/LTEL/LCNC/LMOB/LEDU/LSEO/LFOR + RainProductID int `json:"rain_product_id"` // 雨云产品id(搭配其它产品时使用) + RainProductType string `json:"rain_product_type"` // 雨云产品类型(搭配其它产品时使用) rcs/rvh/rgs/rbm + RecordID int `json:"record_id"` // 记录id(修改时使用) + TTL int `json:"ttl"` // 解析生效时间 + Type string `json:"type"` // 解析类型 A/AAAA/CNAME/TXT/MX/SRV + Value string `json:"value"` // 解析值 +} + +// 删除域名DNS解析请求 +type DeleteDomainDNSRecordRequest struct { + RecordID int `json:"record_id"` // 记录id +} + +// 添加域名DNSSEC请求 +type AddDomainDNSSECRequest struct { + Domain string `json:"domain"` + Keyalg string `json:"keyalg"` + Keydigest string `json:"keydigest"` + Keytag string `json:"keytag"` + Keytype string `json:"keytype"` +} + +// 删除域名DNSSEC请求 +type DeleteDomainDNSSECRequest struct { + Domain string `json:"domain"` + Keydigest string `json:"keydigest"` + Keytag int `json:"keytag"` +} + +// 修改域名NS服务器请求 +type UpdateDomainNSRequest struct { + NameServers []string `json:"name_servers"` +} + +// 续费域名请求 +type RenewDomainRequest struct { + Years int `json:"years"` // 续费年限 +} + +// 域名过户请求 +type DomainTransferRequest struct { + NewTemplateInfo EditDomainTemplateRequest `json:"new_template_info"` // 和SysID二选一,如果没模板就用这个新建模板 + SysID string `json:"sys_id"` // 新域名模板ID +} + +// 查询域名模板列表查询参数 +type GetDomainTemplateListRequest struct { + Options common.StandQueryParameters `json:"options"` +} + +// 域名模板列表响应 +type GetDomainTemplateListResponse struct { + Code int `json:"code"` + Data DomainTemplateListData `json:"data"` +} + +// 域名模板列表数据 +type DomainTemplateListData struct { + TotalRecords int `json:"TotalRecords"` + Records []DomainTemplateDetail `json:"Records"` // 域名模板详情 +} + +// 删除域名信息模板请求 +type DeleteDomainTemplateRequest struct { + SysID string `json:"sys_id"` // 模板标识 +} + +// 获取域名模板详情请求 +type GetDomainTemplateDetailRequest struct { + SysID string `json:"sys_id"` // 模板标识 +} + +// 获取域名模板详情响应 +type GetDomainTemplateDetailResponse struct { + Code int `json:"code"` + Data DomainTemplateDetail `json:"data"` +} + +// 域名模板详情 +type DomainTemplateDetail struct { + ID int `json:"id"` + UID int `json:"uid"` + AddTime int `json:"add_time"` // 添加时间 + SysID string `json:"sys_id"` // 模板标识 + Type string `json:"type"` // 所有者类型,I是个人,E是企业 + Owner string `json:"owner"` // 模板所有者 + ContactName string `json:"contact_name"` // 联系人姓名 + CompanyName string `json:"company_name"` // 企业名称,如果是企业模板就有这个 + Email string `json:"email"` // 联系人邮箱 + Country string `json:"country"` // 所在国家 + Province string `json:"province"` // 中文,省 + City string `json:"city"` // 中文,市 + ZipCode string `json:"zip_code"` // 中文,邮编 + Phone string `json:"phone"` // 联系电话 + Address string `json:"address"` // 中文,通讯地址 + IDType string `json:"id_type"` // 证件类型,如SFZ + IDNum string `json:"id_num"` // 证件值 + CStatus string `json:"c_status"` // 不明, 1 + CFailInfo string `json:"c_fail_info"` // 模板失败信息 + RStatus string `json:"r_status"` // 不明, 1 + RFailInfo string `json:"r_fail_info"` // 不明 +} + +// 更新域名管理密码请求 +type UpdateDomainPasswordRequest struct { + Password string `json:"password"` +} + +// 编辑域名模板请求 +type EditDomainTemplateRequest struct { + Address string `json:"address"` // 中文,通讯地址 + City string `json:"city"` // 中文,市 + CompanyEnName string `json:"company_en_name"` // 企业英文名称,如果类型是企业就要传入 + CompanyName string `json:"company_name"` // 企业名称,如果类型是企业就要传入 + Country string `json:"country"` // 所在国家 + Email string `json:"email"` // 联系人邮箱 + IDImg string `json:"id_img"` // base64编码的证件照片 + IDNum string `json:"id_num"` // 证件值 + IDType string `json:"id_type"` // 证件类型,如SFZ + Name string `json:"name"` // 联系人名 + Phone string `json:"phone"` // 联系电话 + Province string `json:"province"` // 中文,省 + SysID string `json:"sys_id"` // 模板标识(修改时使用) + Type string `json:"type"` // 所有者类型,I是个人,E是企业 + ZipCode string `json:"zip_code"` // 中文,邮编 +} + +// 获取域名whois信息请求 +type GetDomainWhoisInfoRequest struct { + Domain string `json:"domain"` +} + +// 域名WHOIS信息响应 +type GetDomainWhoisInfoResponse struct { + Code int `json:"code"` + Data DomainWhoisInfoData `json:"data"` +} + +// 域名WHOIS信息数据 +type DomainWhoisInfoData struct { + RegDate string `json:"reg_date"` // 注册时间 + ExpDate string `json:"exp_date"` // 到期时间 + Status string `json:"status"` // 域名状态 + Owner string `json:"owner"` // 域名所有者 + Registrar string `json:"registrar"` // 域名注册商 + Email string `json:"email"` // 域名所有者邮箱 + Nameserver string `json:"nameserver"` // 域名服务器 + BizServer string `json:"biz_server"` + Body string `json:"body"` // 域名WHOIS信息原文 + Updated string `json:"updated"` // WHOIS信息更新时间 +} + +// 检查域名能否注册请求 +type CheckDomainAvailableRequest struct { + Domain string `json:"domain"` // 要检查的域名(中文域名同时支持汉字及punycode转码) + Suffix string `json:"suffix"` // 要检查的后缀,多个的话,用英文逗号分割 +} + +// 检查域名能否注册响应 +type CheckDomainAvailableResponse struct { + Code int `json:"code"` + Data []CheckDomainAvailableItem `json:"data"` +} + +// 检查域名能否注册数据 +type CheckDomainAvailableItem struct { + IsAvail bool `json:"is_avail"` // 是否可注册 + SpecialType string `json:"special_type"` + Name string `json:"name"` // 域名 + Price DomainPrice `json:"price"` +} + +// 域名价格 +type DomainPrice struct { + FirstYearPrice int `json:"first_year_price"` // 首年价格 + BuyPrice int `json:"buy_price"` // 购买价格 + RenewPrice int `json:"renew_price"` // 续费价格 +} diff --git a/apis/domain/template.go b/apis/domain/template.go new file mode 100644 index 0000000..6b3d719 --- /dev/null +++ b/apis/domain/template.go @@ -0,0 +1,52 @@ +package domain + +import ( + "github.com/XingfenD/rainyun_api_go_sdk/apis/common" + "github.com/XingfenD/rainyun_api_go_sdk/constant" +) + +// 查询域名模板列表 +func (s *DomainService) GetDomainTemplateList(req *GetDomainTemplateListRequest) (*GetDomainTemplateListResponse, error) { + path := "/product/domain/template/" + + var resp GetDomainTemplateListResponse + querys, err := common.MarshalQueryParams(req) + if err != nil { + return nil, err + } + err = s.client.Do(constant.HTTPMethod_GET, path, querys, nil, &resp) + return &resp, err +} + +// 删除域名信息模板 +func (s *DomainService) DeleteDomainTemplate(sysID string) (*common.BasicOperationResponse, error) { + path := "/product/domain/template/" + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_DELETE, path, nil, DeleteDomainTemplateRequest{SysID: sysID}, &resp) + + return &resp, err +} + +// 编辑域名模板 +func (s *DomainService) EditDomainTemplate(req *EditDomainTemplateRequest) (*common.BasicOperationResponse, error) { + path := "/product/domain/template" + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_PUT, path, nil, req, &resp) + + return &resp, err +} + +// 获取域名模板详情 +func (s *DomainService) GetDomainTemplateDetail(req *GetDomainTemplateDetailRequest) (*GetDomainTemplateDetailResponse, error) { + path := "/product/domain/template/detail/" + + var resp GetDomainTemplateDetailResponse + querys, err := common.MarshalQueryParams(req) + if err != nil { + return nil, err + } + err = s.client.Do(constant.HTTPMethod_GET, path, querys, nil, &resp) + return &resp, err +} diff --git a/apis/product/client.go b/apis/product/client.go new file mode 100644 index 0000000..51ad4ae --- /dev/null +++ b/apis/product/client.go @@ -0,0 +1,11 @@ +package product + +import "github.com/XingfenD/rainyun_api_go_sdk/apis" + +type ProductService struct { + client *apis.RyClient +} + +func NewProductService(c *apis.RyClient) *ProductService { + return &ProductService{client: c} +} diff --git a/apis/product/count.go b/apis/product/count.go new file mode 100644 index 0000000..781d3b9 --- /dev/null +++ b/apis/product/count.go @@ -0,0 +1,72 @@ +package product + +import ( + "github.com/XingfenD/rainyun_api_go_sdk/constant" +) + +// 产品数量 +type ProductCount struct { + TotalCount int `json:"TotalCount"` +} + +// RbmProductCount 域名转售(RBM)产品数量 +type RbmProductCount struct { + TotalCount int `json:"TotalCount"` + AboutToExpire any `json:"AboutToExpire"` +} + +// 产品数量列表 +type ProductCountData struct { + Ros ProductCount `json:"ros"` + Rvh ProductCount `json:"rvh"` + Rcs ProductCount `json:"rcs"` + Rgpu ProductCount `json:"rgpu"` + Rgs ProductCount `json:"rgs"` + Ssl ProductCount `json:"ssl"` + Rbm RbmProductCount `json:"rbm"` + Domain ProductCount `json:"domain"` + Rcdn ProductCount `json:"rcdn"` + Rca ProductCount `json:"rca"` +} + +type GetProductCountListResponse struct { + Code int `json:"code"` + Data ProductCountData `json:"data"` +} + +// 产品ID列表 +type ProductIDListData struct { + Rca []int `json:"rca"` + Rcs []int `json:"rcs"` + Ros []int `json:"ros"` + Rvh []int `json:"rvh"` + Rgpu []int `json:"rgpu"` + Rgs []int `json:"rgs"` + Ssl []int `json:"ssl"` + Rbm []int `json:"rbm"` + Domain []int `json:"domain"` + Rcdn []int `json:"rcdn"` +} + +type GetProductIDListResponse struct { + Code int `json:"code"` + Data ProductIDListData `json:"data"` +} + +// 获取各产品数量 +func (s *ProductService) GetProductCountList() (*GetProductCountListResponse, error) { + path := "/product/" + + var resp GetProductCountListResponse + err := s.client.Do(constant.HTTPMethod_GET, path, nil, nil, &resp) + return &resp, err +} + +// 获取产品ID列表 +func (s *ProductService) GetProductIDList() (*GetProductIDListResponse, error) { + path := "/product/id_list" + + var resp GetProductIDListResponse + err := s.client.Do(constant.HTTPMethod_GET, path, nil, nil, &resp) + return &resp, err +} diff --git a/apis/product/panel_user.go b/apis/product/panel_user.go new file mode 100644 index 0000000..405e44b --- /dev/null +++ b/apis/product/panel_user.go @@ -0,0 +1,112 @@ +package product + +import ( + "fmt" + + "github.com/XingfenD/rainyun_api_go_sdk/apis/common" + "github.com/XingfenD/rainyun_api_go_sdk/constant" +) + +// 增减面板用户产品请求 +type ModifyPanelUserProductRequests struct { + Action string `json:"action"` // 操作:add/del + ProductID int `json:"product_id"` // 产品ID + ProductType string `json:"product_type"` // 产品类型: rcs/rgs/ros/rbm 只支持这四种产品 + Name string `json:"name"` // 子用户名 +} + +// 面板用户请求 +type PanelUserRequest struct { + Name string `json:"name"` + Password string `json:"password"` +} + +// 面板用户产品 +type PanelUserProduct struct { + Name string `json:"name"` // 自用户名 + ProductType string `json:"product_type"` // 产品类型: rcs/rgs/ros/rbm 只支持这四种产品 + ProductID int `json:"product_id"` // 产品ID +} + +// 面板用户记录 +type PanelUserRecord struct { + Name string `json:"name"` // 面板用户名 + Password string `json:"password"` // 面板用户密码 + UserID int `json:"user_id"` // 你的UID + CreateDate int `json:"create_date"` // 创建时间 + Products []PanelUserProduct `json:"products"` // 产品列表 +} + +// 面板用户列表 +type PanelUserListData struct { + TotalRecords int `json:"TotalRecords"` // 面板用户总数 + Records []PanelUserRecord `json:"Records"` +} + +type GetPanelUserListRequest struct { + Options common.StandQueryParameters `json:"options"` +} + +type GetPanelUserListResponse struct { + Code int `json:"code"` + Data PanelUserListData `json:"data"` +} + +// 获取面板用户列表 +func (s *ProductService) GetPanelUserList(req *GetPanelUserListRequest) (*GetPanelUserListResponse, error) { + path := "/product/panel_users/" + + var resp GetPanelUserListResponse + querys, err := common.MarshalQueryParams(req) + if err != nil { + return nil, err + } + err = s.client.Do(constant.HTTPMethod_GET, path, querys, nil, &resp) + return &resp, err +} + +// 增减面板用户产品 +func (s *ProductService) ModifyPanelUserProduct(req *ModifyPanelUserProductRequests) (*common.BasicOperationResponse, error) { + path := "/product/panel_users/" + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_PUT, path, nil, req, &resp) + return &resp, err +} + +// 创建面板用户 +// +// name: 子用户用户名 +// +// pass: 子用户密码 +func (s *ProductService) CreatePanelUser(name string, pass string) (*common.BasicOperationResponse, error) { + path := "/product/panel_users/" + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_POST, path, nil, PanelUserRequest{Name: name, Password: pass}, &resp) + return &resp, err +} + +// 面板用户改密 +// +// name: 子用户用户名 +// +// pass: 子用户新密码 +func (s *ProductService) ChangePanelUserPassword(name string, pass string) (*common.BasicOperationResponse, error) { + path := "/product/panel_users/" + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_PATCH, path, nil, PanelUserRequest{Name: name, Password: pass}, &resp) + return &resp, err +} + +// 删除面板用户 +// +// name: 子用户用户名 +func (s *ProductService) DeletePanelUser(name string) (*common.BasicOperationResponse, error) { + path := fmt.Sprintf("/product/panel_users/%s", name) + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_DELETE, path, nil, nil, &resp) + return &resp, err +} diff --git a/apis/product/renew.go b/apis/product/renew.go new file mode 100644 index 0000000..d65c982 --- /dev/null +++ b/apis/product/renew.go @@ -0,0 +1,22 @@ +package product + +import ( + "github.com/XingfenD/rainyun_api_go_sdk/apis/common" + "github.com/XingfenD/rainyun_api_go_sdk/constant" +) + +// 积分续费请求 +type PointRenewalRequest struct { + DurationDay int `json:"duration_day"` // 续费天数 + ProductID int `json:"product_id"` // 产品ID + ProductType string `json:"product_type"` // 产品类型: rcs/rgs/ros/rvh/rcdn +} + +// 积分续费 +func (s *ProductService) PointRenewal(req *PointRenewalRequest) (*common.BasicOperationResponse, error) { + path := "/product/point_renew" + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_POST, path, nil, req, &resp) + return &resp, err +} diff --git a/apis/public/get_egg_type_list.go b/apis/public/get_egg_type_list.go new file mode 100644 index 0000000..fdef780 --- /dev/null +++ b/apis/public/get_egg_type_list.go @@ -0,0 +1,41 @@ +package public + +import "github.com/XingfenD/rainyun_api_go_sdk/constant" + +// https://api.rainyun.com/#/paths/product~1rgs~1egg_type/get + +// 获取蛋(游戏类型)类型列表 +type GetEggTypeListResponse struct { + Code int `json:"code"` + Data []EggTypeItem `json:"data"` +} + +type EggTypeItem struct { + ID int `json:"id"` // 蛋(游戏类型)ID + EggName string `json:"egg_name"` // 蛋(游戏类型)名称 + Egg EggItem `json:"egg"` + Docker string `json:"docker"` // docker镜像地址 + McsmDocker string `json:"mcsm_docker"` + Env EggTypeEnv `json:"env"` + Order int `json:"order"` + IsHidden bool `json:"is_hidden"` + UpdateTime int `json:"update_time"` + AutoUpdate bool `json:"auto_update"` +} + +type EggTypeEnv struct { + ServerType string `json:"SERVER_TYPE"` + ServerVersion string `json:"SERVER_VERSION"` + Subver string `json:"SUBVER"` + Latest bool `json:"LATEST"` + Prerelease bool `json:"PRERELEASE"` +} + +func (s *PublicService) GetEggTypeList() (*GetEggTypeListResponse, error) { + path := "/product/rgs/egg_type" + + var resp GetEggTypeListResponse + err := s.client.Do(constant.HTTPMethod_GET, path, nil, nil, &resp) + + return &resp, err +} diff --git a/apis/public/get_eggs.go b/apis/public/get_eggs.go new file mode 100644 index 0000000..b11a5b2 --- /dev/null +++ b/apis/public/get_eggs.go @@ -0,0 +1,31 @@ +package public + +import "github.com/XingfenD/rainyun_api_go_sdk/constant" + +// https://api.rainyun.com/#/paths/product~1rgs~1egg/get + +// 获取蛋(游戏)列表 +type GetEggListResponse struct { + Code int `json:"code"` + Data []EggItem `json:"data"` +} + +type EggItem struct { + Name string `json:"name"` // 名称 + EggGroup string `json:"egg_group"` // 分组 + Title string `json:"title"` // 标题 + Desc string `json:"desc"` // 描述 + IconURL string `json:"icon_url"` // 图标 + Order int `json:"order"` // 排序 + IsHidden bool `json:"is_hidden"` // 是否隐藏 + SaveDirs []string `json:"save_dirs"` // 重装时建议的需要保留的目录 +} + +func (s *PublicService) GetEggList() (*GetEggListResponse, error) { + path := "/product/rgs/egg" + + var resp GetEggListResponse + err := s.client.Do(constant.HTTPMethod_GET, path, nil, nil, &resp) + + return &resp, err +} diff --git a/apis/public/get_rcs_os_list.go b/apis/public/get_rcs_os_list.go new file mode 100644 index 0000000..8a1ebb9 --- /dev/null +++ b/apis/public/get_rcs_os_list.go @@ -0,0 +1,39 @@ +package public + +import "github.com/XingfenD/rainyun_api_go_sdk/constant" + +// https://api.rainyun.com/#/paths/product~1rcs~1os-templates/get + +// 获取RCS操作系统列表 +type GetRcsOSListResponse struct { + Code int `json:"code"` + Data []RcsOSListItem `json:"data"` +} + +type RcsOSListItem struct { + ID int `json:"id"` // 系统ID + Region string `json:"region"` // 地域 + Subtype string `json:"subtype"` // 类型(kvm) + Machine string `json:"machine"` // unknown + Name string `json:"name"` // 英文名 + Version string `json:"version"` // 版本 + SyncStatus string `json:"sync_status"` + OsType string `json:"os_type"` // 系统类型(windows/linux) + ChineseName string `json:"chinese_name"` // 中文名 + Icon string `json:"icon"` // 图标 + IsWithBbr bool `json:"is_with_bbr"` // 是否支持BBR + IsEol bool `json:"is_eol"` // 是否已过时 + IsAvailable bool `json:"is_available"` // 是否可用 + Order int `json:"order"` // 排序 + LatestFilename string `json:"latest_filename"` // 最新文件名 + NoVMAgent bool `json:"no_vm_agent"` // 是否无虚拟机Agent +} + +func (s *PublicService) GetRcsOSList() (*GetRcsOSListResponse, error) { + path := "/product/rcs/os-templates" + + var resp GetRcsOSListResponse + err := s.client.Do(constant.HTTPMethod_GET, path, nil, nil, &resp) + + return &resp, err +} diff --git a/apis/public/get_rgs_os_list.go b/apis/public/get_rgs_os_list.go new file mode 100644 index 0000000..723192b --- /dev/null +++ b/apis/public/get_rgs_os_list.go @@ -0,0 +1,39 @@ +package public + +import "github.com/XingfenD/rainyun_api_go_sdk/constant" + +// https://api.rainyun.com/#/paths/product~1rgs~1os-templates/get + +// 获取游戏云系统列表 +type GetRgsOSListResponse struct { + Code int `json:"code"` + Data []RgsOSListItem `json:"data"` +} + +type RgsOSListItem struct { + ID int `json:"id"` + Region string `json:"region"` + Subtype string `json:"subtype"` + Machine string `json:"machine"` + Name string `json:"name"` + Version string `json:"version"` + SyncStatus string `json:"sync_status"` + OsType string `json:"os_type"` + ChineseName string `json:"chinese_name"` + Icon string `json:"icon"` + IsWithBbr bool `json:"is_with_bbr"` + IsEol bool `json:"is_eol"` + IsAvailable bool `json:"is_available"` + Order int `json:"order"` + LatestFilename string `json:"latest_filename"` + NoVMAgent bool `json:"no_vm_agent"` +} + +func (s *PublicService) GetRgsOSList() (*GetRgsOSListResponse, error) { + path := "/product/rgs/os-templates" + + var resp GetRgsOSListResponse + err := s.client.Do(constant.HTTPMethod_GET, path, nil, nil, &resp) + + return &resp, err +} diff --git a/apis/public/get_ros_plans.go b/apis/public/get_ros_plans.go new file mode 100644 index 0000000..1b96510 --- /dev/null +++ b/apis/public/get_ros_plans.go @@ -0,0 +1,38 @@ +package public + +import "github.com/XingfenD/rainyun_api_go_sdk/constant" + +// https://api.rainyun.com/#/paths/product~1ros~1plans/get + +// 获取对象存储套餐列表 +type GetRosPlanListResponse struct { + Code int `json:"code"` + Data []RosPlanItem `json:"data"` +} + +type RosPlanItem struct { + ID int `json:"id"` + Region string `json:"region"` + Subtype string `json:"subtype"` + PlanName string `json:"plan_name"` + Machine string `json:"machine"` + ChargeType string `json:"charge_type"` + Chinese string `json:"chinese"` + IsFree bool `json:"is_free"` + PointRenewPrice any `json:"point_renew_price"` // 积分续费价格 + IsSelling bool `json:"is_selling"` + Price int `json:"price"` + StorageSize int `json:"storage_size"` + Bandwidth int `json:"bandwidth"` + ExtraTransferPrice float64 `json:"extra_transfer_price"` + ExtraStoragePrice float64 `json:"extra_storage_price"` +} + +func (s *PublicService) GetRosPlanList() (*GetRosPlanListResponse, error) { + path := "/product/ros/plans" + + var resp GetRosPlanListResponse + err := s.client.Do(constant.HTTPMethod_GET, path, nil, nil, &resp) + + return &resp, err +} diff --git a/apis/rbm/changeos.go b/apis/rbm/changeos.go new file mode 100644 index 0000000..28535a0 --- /dev/null +++ b/apis/rbm/changeos.go @@ -0,0 +1,22 @@ +package rbm + +import ( + "fmt" + + "github.com/XingfenD/rainyun_api_go_sdk/apis/common" + "github.com/XingfenD/rainyun_api_go_sdk/constant" +) + +// RBM实例更换系统请求 +type RBMChangeOSRequest struct { + OsID int `json:"os_id"` +} + +// RBM实例更换系统 +func (s *RbmService) ChangeRBMOS(id int, req *RBMChangeOSRequest) (*common.BasicOperationResponse, error) { + path := fmt.Sprintf("/product/rbm/%d/changeos", id) + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_POST, path, nil, req, &resp) + return &resp, err +} diff --git a/apis/rbm/client.go b/apis/rbm/client.go new file mode 100644 index 0000000..94cbe55 --- /dev/null +++ b/apis/rbm/client.go @@ -0,0 +1,11 @@ +package rbm + +import "github.com/XingfenD/rainyun_api_go_sdk/apis" + +type RbmService struct { + client *apis.RyClient +} + +func NewRbmService(c *apis.RyClient) *RbmService { + return &RbmService{client: c} +} diff --git a/apis/rbm/eip.go b/apis/rbm/eip.go new file mode 100644 index 0000000..020ee6a --- /dev/null +++ b/apis/rbm/eip.go @@ -0,0 +1,60 @@ +package rbm + +import ( + "fmt" + + "github.com/XingfenD/rainyun_api_go_sdk/apis/common" + "github.com/XingfenD/rainyun_api_go_sdk/constant" +) + +// 创建并绑定弹性IP到RBM请求 +type RBMAssociateEIPRequest struct { + WithFlags string `json:"with_flags"` // IP特征(可选) + WithIPNum int `json:"with_ip_num"` // 数量 + WithIPType string `json:"with_ip_type"` // IPv4/IPv6 +} + +// 更换IP请求 +type RBMChangeIPRequest struct { + DisableOldIPReason string `json:"disable_old_ip_reason"` // 禁用旧IP的原因(可选) + IP string `json:"ip"` // 旧IP地址 + ToIP string `json:"to_ip"` // 不明,可选 +} + +// 设置IP描述请求 +type RBMSetIPDescriptionRequest struct { + Description string `json:"description"` + IP string `json:"ip"` +} + +// 放弃IP请求 +type RBMReleaseIPRequest struct { + IP string `json:"ip"` +} + +// 创建并绑定弹性IP到RBM +func (s *RbmService) AssociateEIP(id int, req *RBMAssociateEIPRequest) (*common.BasicOperationResponse, error) { + path := fmt.Sprintf("/product/rbm/%d/eip", id) + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_POST, path, nil, req, &resp) + return &resp, err +} + +// 设置IP描述 +func (s *RbmService) SetIPDescription(id int, req *RBMSetIPDescriptionRequest) (*common.BasicOperationResponse, error) { + path := fmt.Sprintf("/product/rbm/%d/eip/description", id) + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_POST, path, nil, req, &resp) + return &resp, err +} + +// 放弃IP +func (s *RbmService) ReleaseIP(id int, req *RBMReleaseIPRequest) (*common.BasicOperationResponse, error) { + path := fmt.Sprintf("/product/rbm/%d/eip/discard", id) + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_POST, path, nil, req, &resp) + return &resp, err +} diff --git a/apis/rbm/lifecycle.go b/apis/rbm/lifecycle.go new file mode 100644 index 0000000..5242c16 --- /dev/null +++ b/apis/rbm/lifecycle.go @@ -0,0 +1,44 @@ +package rbm + +import ( + "fmt" + + "github.com/XingfenD/rainyun_api_go_sdk/apis/common" + "github.com/XingfenD/rainyun_api_go_sdk/constant" +) + +// RBM实例启动KVM代理 +func (s *RbmService) StartKVMAgent(id int) (*common.BasicOperationResponse, error) { + path := fmt.Sprintf("/product/rbm/%d/kvm-proxy", id) + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_POST, path, nil, nil, &resp) + return &resp, err +} + +// RBM重新启动KVM +func (s *RbmService) RestartKVM(id int) (*common.BasicOperationResponse, error) { + path := fmt.Sprintf("/product/rbm/%d/kvm-reboot", id) + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_POST, path, nil, nil, &resp) + return &resp, err +} + +// RBM实例关机 +func (s *RbmService) ShutdownRBM(id int) (*common.BasicOperationResponse, error) { + path := fmt.Sprintf("/product/rbm/%d/poweroff", id) + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_POST, path, nil, nil, &resp) + return &resp, err +} + +// RBM实例开机 +func (s *RbmService) StartRBM(id int) (*common.BasicOperationResponse, error) { + path := fmt.Sprintf("/product/rbm/%d/poweron", id) + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_POST, path, nil, nil, &resp) + return &resp, err +} diff --git a/apis/rbm/plan.go b/apis/rbm/plan.go new file mode 100644 index 0000000..040d857 --- /dev/null +++ b/apis/rbm/plan.go @@ -0,0 +1,42 @@ +package rbm + +import "github.com/XingfenD/rainyun_api_go_sdk/constant" + +type GetRbmPlanListResponse struct { + Code int `json:"code"` + Data []RbmPlan `json:"data"` +} + +// RbmPlan RBM套餐 +type RbmPlan struct { + ID int `json:"id"` // 套餐ID + Region string `json:"region"` // 地域 + Line string `json:"line"` // 线路 3c/single/bgp + Subtype string `json:"subtype"` // rbm + PlanName string `json:"plan_name"` // 套餐名称 + Machine string `json:"machine"` // 意义不明 generic/generic_2 + ChargeType string `json:"charge_type"` // 计费方式 package(流量不限)/package_traffic(流量叠加) + Chinese string `json:"chinese"` // 中文名 + IsFree bool `json:"is_free"` // 是否免费(为什么会有这种参数) + PointRenewPrice any `json:"point_renew_price"` // 积分续费价格,全是 null + IsSelling bool `json:"is_selling"` // 是否在售 + Price int `json:"price"` // 价格 + TrafficBaseGb int `json:"traffic_base_gb"` // 流量基数,单位GB + TrafficPrice any `json:"traffic_price"` // 流量价格,单位GB,package_traffic 计费方式才有值 + CPU int `json:"cpu"` // cpu核数 + Memory int `json:"memory"` // 内存,单位GB + Storage int `json:"storage"` // 存储,单位GB + NetIn int `json:"net_in"` // 入网带宽,单位Mbps + NetOut int `json:"net_out"` // 出网带宽,单位Mbps + AvailableStock int `json:"available_stock"` // 可用库存 + IPPrices any `json:"ip_prices"` // IP价格,单位元/月 +} + +// 获取RBM套餐列表 +func (s *RbmService) GetRBMPlanList() (*GetRbmPlanListResponse, error) { + path := "/product/rbm/models" + + var resp GetRbmPlanListResponse + err := s.client.Do(constant.HTTPMethod_GET, path, nil, nil, &resp) + return &resp, err +} diff --git a/apis/rbm/traffic.go b/apis/rbm/traffic.go new file mode 100644 index 0000000..607517c --- /dev/null +++ b/apis/rbm/traffic.go @@ -0,0 +1,22 @@ +package rbm + +import ( + "fmt" + + "github.com/XingfenD/rainyun_api_go_sdk/apis/common" + "github.com/XingfenD/rainyun_api_go_sdk/constant" +) + +// 充流量请求 +type RBMChargeTrafficRequest struct { + TrafficInGb int `json:"traffic_in_gb"` +} + +// 充流量 +func (s *RbmService) ChargeTraffic(id int, req *RBMChargeTrafficRequest) (*common.BasicOperationResponse, error) { + path := fmt.Sprintf("/product/rbm/%d/traffic/charge", id) + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_POST, path, nil, req, &resp) + return &resp, err +} diff --git a/apis/rca/appstore.go b/apis/rca/appstore.go new file mode 100644 index 0000000..c2233bf --- /dev/null +++ b/apis/rca/appstore.go @@ -0,0 +1,172 @@ +package rca + +import ( + "fmt" + + "github.com/XingfenD/rainyun_api_go_sdk/constant" +) + +// 云应用创建App模板请求 +type RcaCreateAppTemplateRequest struct { + CrossVersionUpdate bool `json:"cross_version_update"` // 是否支持跨版本更新 + Description string `json:"description"` // 描述 + DisableUpdate bool `json:"disable_update"` // 是否禁用版本更新功能,禁用后已安装应用无法检测到更新 + Logo string `json:"logo"` // logo(base64),最大50KB,可以不传 + Name string `json:"name"` // 应用名称(英文标识) + ProjectLink string `json:"project_link"` // 应用项目链接 + Readme string `json:"readme"` // 介绍(markdown) + Tags []string `json:"tags"` // 标签,多选,目前支持的tag可以参考现有应用 + Title string `json:"title"` // 应用标题 + Website string `json:"website"` // 应用官方网站链接 +} + +// App模板 +type AppTemplate struct { + ID int `json:"id"` // 模板id + UID int `json:"uid"` + Name string `json:"name"` + Title string `json:"title"` + Description string `json:"description"` + Logo string `json:"logo"` + Type string `json:"type"` + Tags []string `json:"tags"` + Website string `json:"website"` + Github string `json:"github"` + CreateDate int `json:"create_date"` + Readme string `json:"readme"` + Provider string `json:"provider"` + CrossVersionUpdate bool `json:"cross_version_update"` + Downloads int `json:"downloads"` + IsPublic bool `json:"is_public"` + ReviewStatus string `json:"review_status"` + ReviewComment string `json:"review_comment"` + StopReason string `json:"stop_reason"` + DisableUpdate bool `json:"disable_update"` +} + +type RcaCreateAppTemplateResponse struct { + Code int `json:"code"` + Data AppTemplate `json:"data"` +} + +// App模板版本 +type AppTemplateVersion struct { + ID int `json:"id"` + Version string `json:"version"` + IsPublic bool `json:"is_public"` +} + +type AppTemplateVersionData struct { + Data AppTemplate `json:"data"` + Versions []AppTemplateVersion `json:"versions"` +} + +type CreateAppTemplateVersionResponse struct { + Code int `json:"code"` + Data AppTemplateVersionData `json:"data"` +} + +// 配置文件 +type AppTemplateConfigMap struct { + ContainerPath string `json:"container_path"` // 配置文件存放在容器里面的目录 + Content string `json:"content"` // 文件内容,最大1MB + FileName string `json:"file_name"` // 文件名 +} + +// 环境变量 +type AppTemplateEnv struct { + Key string `json:"key"` // 键 + Value string `json:"value"` // 值,允许空白 +} + +// 安装选项 +type AppTemplateOption struct { + Default string `json:"default"` // 默认值 + Disabled bool `json:"disabled"` // 是否不允许编辑 + EnvKey string `json:"env_key"` // 绑定到环境变量的Key + Label string `json:"label"` // 标签,告知用户这个选项是干什么用的,例如root用户密码 + Random bool `json:"random"` // 是否进行随机化生成 + Required bool `json:"required"` // 是否必选 + Rule string `json:"rule"` // 规则,可用项目按照前端已实现支持的规则来 + Type string `json:"type"` // 类型,如:password number等 + Value string `json:"value"` // 填入值 + Values []AppTemplateOptionValue `json:"values"` // 选项,type为select时提供给客户选择 +} + +// 选项可选值 +type AppTemplateOptionValue struct { + Label string `json:"label"` // 提示显示 + Value string `json:"value"` // 对应值 +} + +// 资源需求 +type AppTemplateResourceRequest struct { + MinCPU int `json:"min_cpu"` // 如1000,单位是m + MinMemory int `json:"min_memory"` // 如4096,单位是Mi +} + +// 脚本钩子 +type AppTemplateScripts struct { + Install string `json:"install"` // install(安装应用的时候执行,可以用于下载特定的持久化文件,可以指定运行环境,在底层这个是用initContainer来实现 + InstallImage string `json:"install_image"` // 执行安装脚本所使用的容器镜像,其他阶段会使用运行时镜像 + PostStart string `json:"post_start"` // poststart(容器创建后立即执行) + PreStop string `json:"pre_stop"` // prestop(终止前运行) +} + +// 服务 +type AppTemplateService struct { + ExternalPort string `json:"external_port"` // 外部端口,之所以是string,因为支持以变量形式传入 + InternalPort string `json:"internal_port"` // 内部端口,对应AppPort,之所以是string,因为支持以变量形式传入 + Label string `json:"label"` // 标签,可以是中文 + Name string `json:"name"` // 服务名称 + Protocol string `json:"protocol"` // 协议 + Type string `json:"type"` // 类型,可以是internal或external,对应clusterIP或者lb +} + +// 文件目录挂载 +type AppTemplateVolumeMount struct { + MountContentType string `json:"mount_content_type"` // 挂载类型,文件file或目录dir + MountPath string `json:"mount_path"` // 容器内路径 + Name string `json:"name"` // 挂载描述 + PreContent string `json:"pre_content"` // file类型专用,以base64存储的预先准备二进制数据,这个是用于一些小型二进制文件例如.db或者如/etc/localtime等的预先准备,模拟在docker中如"./data/cloudreve.db:/cloudreve/cloudreve.db"或/etc/timezone:/etc/timezone:ro + SubPath string `json:"sub_path"` // Project卷内路径,不能以.或者/开头 +} + +// 创建App模板版本请求 +// +// 我尝试创建了一个函数用于将docker compose文件转换成这种格式,但在编写了近1000行代码后,我成功的放弃了这个想法 +// :( +type CreateAppTemplateVersionRequest struct { + Args []string `json:"args"` // 运行参数 + Command []string `json:"command"` // 运行命令 + ConfigMaps []AppTemplateConfigMap `json:"config_maps"` + Env []AppTemplateEnv `json:"env"` // 环境变量 + Image string `json:"image"` // 容器镜像,如nginx:1.21.0 + Options []AppTemplateOption `json:"options"` + ReleaseID int `json:"release_id"` // 更新用release ID + ResourceRequest AppTemplateResourceRequest `json:"resource_request"` // 资源需求 + Scripts AppTemplateScripts `json:"scripts"` // 脚本钩子 + Services []AppTemplateService `json:"services"` + Version string `json:"version"` // 版本号,如1.21.0 + VolumeMounts []AppTemplateVolumeMount `json:"volume_mounts"` // 文件目录,如data:/var/lib/mysql +} + +// 云应用创建App模板 +func (s *RcaService) CreateRcaAppTemplate(req *RcaCreateAppTemplateRequest) (*RcaCreateAppTemplateResponse, error) { + path := "/product/rca/appstore/" + + var resp RcaCreateAppTemplateResponse + err := s.client.Do(constant.HTTPMethod_POST, path, nil, req, &resp) + return &resp, err +} + +// 创建App模板版本 +// +// id: APP模板ID +func (s *RcaService) CreateRcaAppTemplateVersion(id int, req *CreateAppTemplateVersionRequest) (*CreateAppTemplateVersionResponse, error) { + path := fmt.Sprintf("/product/rca/appstore/%d/release", id) + + var resp CreateAppTemplateVersionResponse + err := s.client.Do(constant.HTTPMethod_POST, path, nil, req, &resp) + return &resp, err +} diff --git a/apis/rca/client.go b/apis/rca/client.go new file mode 100644 index 0000000..37eba69 --- /dev/null +++ b/apis/rca/client.go @@ -0,0 +1,11 @@ +package rca + +import "github.com/XingfenD/rainyun_api_go_sdk/apis" + +type RcaService struct { + client *apis.RyClient +} + +func NewRcaService(c *apis.RyClient) *RcaService { + return &RcaService{client: c} +} diff --git a/apis/rca/project.go b/apis/rca/project.go new file mode 100644 index 0000000..dda70c2 --- /dev/null +++ b/apis/rca/project.go @@ -0,0 +1,254 @@ +package rca + +import ( + "fmt" + + "github.com/XingfenD/rainyun_api_go_sdk/apis/common" + "github.com/XingfenD/rainyun_api_go_sdk/constant" +) + +// 云应用区域信息 +type PriceInfo struct { + Cpu float64 `json:"cpu"` + Memory float64 `json:"memory"` + Ipv4 float64 `json:"ipv4"` + Traffic float64 `json:"traffic"` + Disk float64 `json:"disk"` +} + +type RcaRegion struct { + ID int `json:"id"` + Name string `json:"name"` + ChineseName string `json:"chinese_name"` + WebsiteServiceDomain string `json:"website_service_domain"` + SftpServiceDomain string `json:"sftp_service_domain"` + PublicServiceDomain string `json:"public_service_domain"` + PriceInfo PriceInfo `json:"price_info"` +} + +type GetRcaRegionInfoResponse struct { + Code int `json:"code"` + Data []RcaRegion `json:"data"` +} + +// 开通云应用产品请求 +type ActivateRcaRequest struct { + RegionID int `json:"region_id"` +} + +// 创建云应用项目请求 +type CreateRcaProjectRequest struct { + ChargeType string `json:"charge_type"` // 计费类型: 动态计费: elastic + CPULimit int `json:"cpu_limit"` // (仅限package模式)CPU限制(毫核),1核心=1000,0.1核=100 + DiskSize int `json:"disk_size"` // 磁盘大小(GiB) + Ipv4Count int `json:"ipv4_count"` // 要添加的IPv4地址数量 + Ipv6Count int `json:"ipv6_count"` // 要添加的IPv6地址数量 + MemoryLimit int `json:"memory_limit"` // (仅限package模式)内存限制(MiB) + Name string `json:"name"` // 名称 + RegionID int `json:"region_id"` // 部署区域 +} + +// 云应用节点信息 +type RcaNode struct { + UUID string `json:"UUID"` + AuthKey string `json:"AuthKey"` + Region string `json:"Region"` + IPRegion string `json:"IpRegion"` + Machine string `json:"Machine"` + Product string `json:"Product"` + Subtype string `json:"Subtype"` + ChineseName string `json:"ChineseName"` + PhysicalNode string `json:"PhysicalNode"` + Config string `json:"Config"` + Stock any `json:"Stock"` + StatusData string `json:"StatusData"` + ShowMonitorData string `json:"ShowMonitorData"` + UpdateTime string `json:"UpdateTime"` + GitRepositoryName string `json:"GitRepositoryName"` + CertifyRequired bool `json:"CertifyRequired"` + IsDisableBackup bool `json:"IsDisableBackup"` + IsHidden bool `json:"IsHidden"` + NodeName string `json:"NodeName"` +} + +type RcaResourceLimits struct { + MaxCPU int `json:"max_cpu"` + MaxMemory int `json:"max_memory"` +} + +// 云应用项目资源使用情况 +type RcaProjectUsageData struct { + CPU int `json:"cpu"` + Memory int `json:"memory"` + NetOut int `json:"net_out"` + NetIn int `json:"net_in"` + DiskUsage int `json:"disk_usage"` + TrafficToday int `json:"traffic_today"` + Status string `json:"status"` + StatusReason string `json:"status_reason"` + AllocatedCPU int `json:"allocated_cpu"` + AllocatedMemory int `json:"allocated_memory"` + AppCount int `json:"app_count"` + WebsiteCount int `json:"website_count"` + DatabaseCount int `json:"database_count"` + Ipv4Count int `json:"ipv4_count"` + HealthyPods int `json:"healthy_pods"` + UnhealthyPods int `json:"unhealthy_pods"` +} + +// 备份目标 +type RcaBackupTarget struct { + Type string `json:"type"` // 目标类型,支持项目本地备份或者远程S3存储(local/s3) + S3Endpoint string `json:"s3_endpoint"` // S3的端点(仅支持Virtual Host,不支持Path-Style模式) + S3Bucket string `json:"s3_bucket"` // S3存储桶名 + S3AccessKey string `json:"s3_access_key"` // S3的AK + S3SecretKey string `json:"s3_secret_key"` // S3的SK + S3BackupDirectory string `json:"s3_backup_directory"` // s3备份存储的目录 +} + +// 云应用项目 +type RcaProject struct { + ID int `json:"ID"` + UID int `json:"UID"` + PlanID int `json:"PlanID"` + CreateDate int `json:"CreateDate"` // 创建时间 + NodeUUID string `json:"NodeUUID"` + Node RcaNode `json:"Node"` + Status string `json:"Status"` + StopReason string `json:"StopReason"` + RewardPointsToBeCollect int `json:"RewardPointsToBeCollect"` + Tag string `json:"Tag"` + ExpDate int `json:"ExpDate"` + ExpireNotice int `json:"ExpireNotice"` + AutoRenew bool `json:"AutoRenew"` + UnsubscribeAble bool `json:"UnsubscribeAble"` + Try bool `json:"Try"` + Name string `json:"name"` + RegionID int `json:"region_id"` + Region *RcaRegion `json:"region"` + Namespace string `json:"namespace"` + APIToken string `json:"APIToken"` + ResourceLimits RcaResourceLimits `json:"resource_limits"` + UsageData RcaProjectUsageData `json:"usage_data"` + VolumeSize int `json:"volume_size"` + ChargeType string `json:"charge_type"` // 计费类型: elastic + HourlyPrice float64 `json:"hourly_price"` // 小时价格 + NextChargeTime int `json:"next_charge_time"` + BackupTarget RcaBackupTarget `json:"backup_target"` // 备份目标 + SftpSetting any `json:"sftp_setting"` + IdleAlarmFlag bool `json:"idle_alarm_flag"` + PaymentDueEnd int `json:"payment_due_end"` +} + +type CreateRcaProjectResponse struct { + Code int `json:"code"` + Data RcaProject `json:"data"` +} + +type RcaProjectListData struct { + TotalRecords int `json:"TotalRecords"` + Records []RcaProject `json:"Records"` +} + +type GetRcaProjectListResponse struct { + Code int `json:"code"` + Data RcaProjectListData `json:"data"` +} + +// 云应用项目的指标信息,示例如下: +type RcaProjectMetricsData struct { + Columns []string `json:"Columns"` + Values [][]float64 `json:"Values"` +} + +type GetRcaProjectMetricsResponse struct { + Code int `json:"code"` + Data RcaProjectMetricsData `json:"data"` +} + +type RcaProjectDetailData struct { + Data RcaProject `json:"Data"` +} + +type GetRcaProjectDetailResponse struct { + Code int `json:"code"` + Data RcaProjectDetailData `json:"data"` +} + +// 云应用获取区域信息 +func (s *RcaService) GetRcaRegionInfo() (*GetRcaRegionInfoResponse, error) { + path := "/product/rca/region" + + var resp GetRcaRegionInfoResponse + err := s.client.Do(constant.HTTPMethod_GET, path, nil, nil, &resp) + return &resp, err +} + +// 开通云应用产品 +// +// regionID: 地域ID +func (s *RcaService) ActivateRca(regionID int) (*common.BasicOperationResponse, error) { + path := "/product/rca/activate" + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_POST, path, nil, ActivateRcaRequest{RegionID: regionID}, &resp) + return &resp, err +} + +// 创建云应用项目 +func (s *RcaService) CreateRcaProject(req *CreateRcaProjectRequest) (*CreateRcaProjectResponse, error) { + path := "/product/rca/project/" + + var resp CreateRcaProjectResponse + err := s.client.Do(constant.HTTPMethod_POST, path, nil, req, &resp) + return &resp, err +} + +// 云应用列出项目 +// +// options: 查询参数 可以用 EncodingStandardQueryParameters 获取. +func (s *RcaService) ListRcaProjects(options string) (*GetRcaProjectListResponse, error) { + path := "/product/rca/project/" + querys := map[string]string{"no_metrics": "false", "options": options} // no_metrics 含义不明 + + var resp GetRcaProjectListResponse + err := s.client.Do(constant.HTTPMethod_GET, path, querys, nil, &resp) + return &resp, err +} + +// 销毁云应用项目 +// +// id: RCA项目ID +func (s *RcaService) DestroyRcaProject(id int) (*common.BasicOperationResponse, error) { + path := fmt.Sprintf("/product/rca/project/%d/", id) + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_DELETE, path, nil, nil, &resp) + return &resp, err +} + +// 获取Rca项目的指标信息 +// +// id: RCA项目ID +// +// starttime: 开始时间(timestamp) +// +// endtime: 结束时间(timestamp) +func (s *RcaService) GetRcaProjectMetrics(id int, startTime int, endTime int) (*GetRcaProjectMetricsResponse, error) { + path := fmt.Sprintf("/product/rca/project/%d/metrics?start_time=%d&end_time=%d", id, startTime, endTime) + + var resp GetRcaProjectMetricsResponse + err := s.client.Do(constant.HTTPMethod_GET, path, nil, nil, &resp) + return &resp, err +} + +// 获取云应用项目详情 +// +// id: RCA项目ID +func (s *RcaService) GetRcaProjectDetail(id int) (*GetRcaProjectDetailResponse, error) { + path := fmt.Sprintf("/product/rca/project/%d/", id) + + var resp GetRcaProjectDetailResponse + err := s.client.Do(constant.HTTPMethod_GET, path, nil, nil, &resp) + return &resp, err +} diff --git a/apis/rca/raindrop.go b/apis/rca/raindrop.go new file mode 100644 index 0000000..e381cf5 --- /dev/null +++ b/apis/rca/raindrop.go @@ -0,0 +1,128 @@ +package rca + +import ( + "github.com/XingfenD/rainyun_api_go_sdk/apis/common" + "github.com/XingfenD/rainyun_api_go_sdk/constant" +) + +// 云应用雨点余额使用情况 +type RcaRaindropUsageData struct { + ExpectedRemainDays int `json:"expected_remain_days"` // 预计剩余天数 + LastMonthUsage float64 `json:"last_month_usage"` // 上月使用量 + ExpectedNextMonthUsage float64 `json:"expected_next_month_usage"` // 预计下月使用量 + FreeTrialRemainDays int `json:"free_trial_remain_days"` // 剩余免费试用天数 + IsBeforeFirstPayment bool `json:"is_before_first_payment"` +} + +type GetRcaRaindropUsageResponse struct { + Code int `json:"code"` + Data RcaRaindropUsageData `json:"data"` +} + +// 雨点套餐 +type RaindropPlan struct { + ID int `json:"id"` + Amount int `json:"amount"` + Price int `json:"price"` + IsSelling bool `json:"is_selling"` + PlanName string `json:"plan_name"` + Chinese string `json:"chinese"` +} + +type GetRcaRaindropPlansListResponse struct { + Code int `json:"code"` + Data []RaindropPlan `json:"data"` +} + +// 雨点消费明细 +type RaindropConsumeData struct { + BasicPrice float64 `json:"basic_price"` + TrafficBytes int `json:"traffic_bytes"` + TrafficPrice float64 `json:"traffic_price"` +} + +// 雨点消费记录 +type RaindropConsumeRecord struct { + ID int `json:"id"` + UID int `json:"uid"` + Time int `json:"time"` + Type string `json:"type"` + ProductID int `json:"product_id"` + Amount float64 `json:"amount"` + Data RaindropConsumeData `json:"data"` +} + +// 雨点消费历史 +type RaindropConsumeLogData struct { + TotalRecords int `json:"TotalRecords"` + Records []RaindropConsumeRecord `json:"Records"` +} + +type GetRaindropConsumeLogResponse struct { + Code int `json:"code"` + Data RaindropConsumeLogData `json:"data"` +} + +// 云应用购买雨点请求 +type BuyRaindropRequest struct { + PlanID int `json:"plan_id"` + WithCouponID int `json:"with_coupon_id"` +} + +// 雨点余额 +type GetRcaRaindropBalanceResponse struct { + Code int `json:"code"` + Data float64 `json:"data"` +} + +// 云应用获取雨点余额使用情况 +func (s *RcaService) GetRcaRaindropUsage() (*GetRcaRaindropUsageResponse, error) { + path := "/product/rca/raindrop/usage" + + var resp GetRcaRaindropUsageResponse + err := s.client.Do(constant.HTTPMethod_GET, path, nil, nil, &resp) + return &resp, err +} + +// 云应用获取雨点套餐列表 +func (s *RcaService) GetRcaRaindropPlansList() (*GetRcaRaindropPlansListResponse, error) { + path := "/product/rca/raindrop/plans" + + var resp GetRcaRaindropPlansListResponse + err := s.client.Do(constant.HTTPMethod_GET, path, nil, nil, &resp) + return &resp, err +} + +// 云应用获取雨点消费历史 +// +// options: 查询参数 可以用 EncodingStandardQueryParameters 获取. +func (s *RcaService) GetRaindropConsumeLog(options string) (*GetRaindropConsumeLogResponse, error) { + path := "/product/rca/raindrop/consume_log" + querys := map[string]string{"options": options} + + var resp GetRaindropConsumeLogResponse + err := s.client.Do(constant.HTTPMethod_GET, path, querys, nil, &resp) + return &resp, err +} + +// 云应用购买雨点 +// +// planID: 雨点套餐ID +// +// couponID: 优惠券ID +func (s *RcaService) BuyRaindrop(planID int, couponID int) (*common.BasicOperationResponse, error) { + path := "/product/rca/raindrop" + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_POST, path, nil, BuyRaindropRequest{PlanID: planID, WithCouponID: couponID}, &resp) + return &resp, err +} + +// 云应用获取雨点余额 +func (s *RcaService) GetRcaRaindropBalance() (*GetRcaRaindropBalanceResponse, error) { + path := "/product/rca/raindrop" + + var resp GetRcaRaindropBalanceResponse + err := s.client.Do(constant.HTTPMethod_GET, path, nil, nil, &resp) + return &resp, err +} diff --git a/apis/rca/resource.go b/apis/rca/resource.go new file mode 100644 index 0000000..c63bb62 --- /dev/null +++ b/apis/rca/resource.go @@ -0,0 +1,130 @@ +package rca + +import ( + "fmt" + + "github.com/XingfenD/rainyun_api_go_sdk/apis/common" + "github.com/XingfenD/rainyun_api_go_sdk/constant" +) + +// 云应用项目设置备份目标请求 +type SetRcaProjectBackupTargetRequest struct { + S3AccessKey string `json:"s3_access_key"` // S3的AK + S3BackupDirectory string `json:"s3_backup_directory"` // s3备份存储的目录 + S3Bucket string `json:"s3_bucket"` // S3存储桶名 + S3Endpoint string `json:"s3_endpoint"` // S3的端点(仅支持Virtual Host,不支持Path-Style模式) + S3SecretKey string `json:"s3_secret_key"` // S3的SK + TargetType string `json:"target_type"` // 目标类型,支持项目本地备份或者远程S3存储(local/s3) +} + +// 云应用项目磁盘扩容请求 +type RcaProjectDiskExpansionRequest struct { + NewDiskSize int `json:"new_disk_size"` // 以GB显示的新项目磁盘大小 +} + +// 云应用增加IP地址请求 +type RcaAddsIpAddressRequest struct { + Ipv4Count int `json:"ipv4_count"` // 要添加的IPv4地址数量 + Ipv6Count int `json:"ipv6_count"` // 要添加的IPv6地址数量 +} + +// 云应用移除IP地址请求 +type RcaRemoveIPRequest struct { + IPID int `json:"ip_id"` // 要删除的IP地址ID +} + +// 云应用项目修改SFTP设置请求 +type RcaProjectSetSftpConfigRequest struct { + Password string `json:"password"` + Username string `json:"username"` +} + +// 云应用IP信息 +type RcaIP struct { + ID int `json:"id"` // ip id + Region string `json:"region"` // 地域 + Type string `json:"type"` // ip类型(IPv4/IPv6) + IP string `json:"ip"` // ip地址 + AddressPool string `json:"address_pool"` // ip池(user-ip-pool) + Gateway string `json:"gateway"` // 网关 + Block string `json:"block"` // CIDR(24) + UID int `json:"uid"` // 用户id + ProjectID int `json:"project_id"` + Info string `json:"info"` + AllocatedDate int `json:"allocated_date"` // 分配时间 +} + +type GetRcaProjectIPsResponse struct { + Code int `json:"code"` + Data []RcaIP `json:"data"` +} + +// 云应用项目设置备份目标 +// +// id: RCA项目ID +func (s *RcaService) SetRcaProjectBackupTarget(id int, req *SetRcaProjectBackupTargetRequest) (*common.BasicOperationResponse, error) { + path := fmt.Sprintf("/product/rca/project/%d/backup_target", id) + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_PATCH, path, nil, req, &resp) + return &resp, err +} + +// 云应用项目磁盘扩容 +// +// id: RCA项目ID +func (s *RcaService) ExpandRcaProjectDisk(id int, req *RcaProjectDiskExpansionRequest) (*common.BasicOperationResponse, error) { + path := fmt.Sprintf("/product/rca/project/%d/disk_expand", id) + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_POST, path, nil, req, &resp) + return &resp, err +} + +// 云应用增加IP地址 +// +// id: RCA项目ID +func (s *RcaService) AddRcaProjectIP(id int, req *RcaAddsIpAddressRequest) (*common.BasicOperationResponse, error) { + path := fmt.Sprintf("/product/rca/project/%d/eip", id) + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_POST, path, nil, req, &resp) + return &resp, err +} + +// 云应用移除IP地址 +// +// id: RCA项目ID +func (s *RcaService) RemoveRcaProjectIP(id int, req *RcaRemoveIPRequest) (*common.BasicOperationResponse, error) { + path := fmt.Sprintf("/product/rca/project/%d/eip", id) + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_DELETE, path, nil, req, &resp) + return &resp, err +} + +// 云应用项目修改SFTP设置 +// +// id: RCA项目ID +// +// password: 密码 +// +// username: 用户名 +func (s *RcaService) SetRcaProjectSFTPConfig(id int, password string, username string) (*common.BasicOperationResponse, error) { + path := fmt.Sprintf("/product/rca/project/%d/sftp", id) + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_PATCH, path, nil, RcaProjectSetSftpConfigRequest{Password: password, Username: username}, &resp) + return &resp, err +} + +// 云应用项目列出IP地址 +// +// id: RCA项目ID +func (s *RcaService) ListRcaProjectIPs(id int) (*GetRcaProjectIPsResponse, error) { + path := fmt.Sprintf("/product/rca/project/%d/eip", id) + + var resp GetRcaProjectIPsResponse + err := s.client.Do(constant.HTTPMethod_GET, path, nil, nil, &resp) + return &resp, err +} diff --git a/apis/rgs/backup.go b/apis/rgs/backup.go new file mode 100644 index 0000000..7b0904e --- /dev/null +++ b/apis/rgs/backup.go @@ -0,0 +1,68 @@ +package rgs + +import ( + "fmt" + + "github.com/XingfenD/rainyun_api_go_sdk/apis/common" + "github.com/XingfenD/rainyun_api_go_sdk/apis/rcs" + "github.com/XingfenD/rainyun_api_go_sdk/constant" +) + +// 游戏云创建备份 +// +// id: 游戏云 ID +// +// label: 备份标签 +func (s *RgsService) CreateRgsBackup(id int, label string) (*common.BasicOperationResponse, error) { + path := fmt.Sprintf("/product/rgs/%d/backup", id) + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_POST, path, nil, rcs.CreateRcsBackupRequest{Label: label}, &resp) + return &resp, err +} + +// 游戏云删除备份 +// +// id: 游戏云 ID, bid: 备份ID +func (s *RgsService) DeleteRgsBackup(id, bid int) (*common.BasicOperationResponse, error) { + path := fmt.Sprintf("/product/rgs/%d/backup/%d", id, bid) + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_DELETE, path, nil, nil, &resp) + return &resp, err +} + +// 游戏云取消备份 +// +// id: RGS ID, bid: 备份ID +func (s *RgsService) CancelRgsBackup(id, bid int) (*common.BasicOperationResponse, error) { + path := fmt.Sprintf("/product/rgs/%d/backup/%d/cancel", id, bid) + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_POST, path, nil, nil, &resp) + return &resp, err +} + +// 游戏云还原备份 +// +// id: 游戏云 ID, bid: 备份ID +func (s *RgsService) RestoreRgsBackup(id, bid int) (*common.BasicOperationResponse, error) { + path := fmt.Sprintf("/product/rgs/%d/backup/%d/restore", id, bid) + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_POST, path, nil, nil, &resp) + return &resp, err +} + +// 游戏云设置备份选项 +// +// id: RGS ID +// +// 没错就是Rcs,这俩是一样的 +func (s *RgsService) EnableRgsAutoBackup(id int, req *rcs.RcsSetBackupOptionsRequest) (*common.BasicOperationResponse, error) { + path := fmt.Sprintf("/product/rgs/%d/backup/setting", id) + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_PATCH, path, nil, req, &resp) + return &resp, err +} diff --git a/apis/rgs/changeos.go b/apis/rgs/changeos.go new file mode 100644 index 0000000..d215764 --- /dev/null +++ b/apis/rgs/changeos.go @@ -0,0 +1,20 @@ +package rgs + +import ( + "fmt" + + "github.com/XingfenD/rainyun_api_go_sdk/apis/common" + "github.com/XingfenD/rainyun_api_go_sdk/apis/rcs" + "github.com/XingfenD/rainyun_api_go_sdk/constant" +) + +// 游戏云重装系统 +// +// id: RGS ID +func (s *RgsService) ReinstallRgs(id int, req *rcs.ReinstallRcsRequest) (*common.BasicOperationResponse, error) { + path := fmt.Sprintf("/product/rgs/%d/changeos", id) + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_POST, path, nil, req, &resp) + return &resp, err +} diff --git a/apis/rgs/client.go b/apis/rgs/client.go new file mode 100644 index 0000000..b5e0846 --- /dev/null +++ b/apis/rgs/client.go @@ -0,0 +1,11 @@ +package rgs + +import "github.com/XingfenD/rainyun_api_go_sdk/apis" + +type RgsService struct { + client *apis.RyClient +} + +func NewRgsService(c *apis.RyClient) *RgsService { + return &RgsService{client: c} +} diff --git a/apis/rgs/create_rgs.go b/apis/rgs/create_rgs.go new file mode 100644 index 0000000..a4317d2 --- /dev/null +++ b/apis/rgs/create_rgs.go @@ -0,0 +1,157 @@ +package rgs + +import "github.com/XingfenD/rainyun_api_go_sdk/constant" + +// 创建游戏云请求 +type CreateRgsRequest struct { + AppVars []RgsAppVar `json:"app_vars"` // 当空数组时,进行单次任务下发(可选) + Config RgsConfig `json:"config"` + CPULimitMode bool `json:"cpu_limit_mode"` + Duration int `json:"duration"` // 创建时长(月) + EggTypeID int `json:"egg_type_id"` // 游戏类型 + NodeUUID string `json:"node_uuid"` + OnlineMode bool `json:"online_mode"` + OsID int `json:"os_id"` + PanelUser string `json:"panel_user"` // 游戏云面板用户 + PayMode string `json:"pay_mode"` + PlanID int `json:"plan_id"` + Subtype string `json:"subtype"` // kvm/mcsm + Try bool `json:"try"` + WithCouponID int `json:"with_coupon_id"` + WithEipFlags string `json:"with_eip_flags"` // 是否开启高防,us_ddosip -> 美国高防,nb_ddosip -> 宁波高防 + WithEipNum int `json:"with_eip_num"` + WithEipType string `json:"with_eip_type"` + Zone string `json:"zone"` +} + +type RgsAppVar struct { + AppID int `json:"app_id"` + Retry bool `json:"retry"` // 重发之前的任务,此项存在时,无需传入参数 + Vars any `json:"vars"` +} + +// 游戏云配置信息 +type RgsConfig struct { + CPU int `json:"cpu"` + Memory int `json:"memory"` + NetOut int `json:"net_out"` + NetIn int `json:"net_in"` + BaseDisk int `json:"base_disk"` + DataDisk int `json:"data_disk"` + Allocation int `json:"allocation"` + Database int `json:"database"` + Backup int `json:"backup"` +} + +// 创建游戏云响应 +type CreateRgsResponse struct { + Code int `json:"code"` + Data RgsCreateData `json:"data"` +} + +// RgsCreateData 创建游戏云返回的完整实例数据 +type RgsCreateData struct { + RgsRecord + Node RgsNode `json:"Node"` // 节点信息 + Plan RgsPlan `json:"Plan"` + EggTypeID int `json:"EggTypeId"` + EggType any `json:"EggType"` + PteroUserName string `json:"PteroUserName"` + PteroUser any `json:"PteroUser"` + ServerID int `json:"ServerID"` + AllocationID int `json:"AllocationID"` + ServerUUID string `json:"ServerUUID"` + DaemonUUID string `json:"DaemonUUID"` + GameInfo any `json:"GameInfo"` +} + +type RgsNode struct { + UUID string `json:"UUID"` + AuthKey string `json:"AuthKey"` + Region string `json:"Region"` + IPRegion string `json:"IpRegion"` + Machine string `json:"Machine"` + Product string `json:"Product"` + Subtype string `json:"Subtype"` + ChineseName string `json:"ChineseName"` + PhysicalNode string `json:"PhysicalNode"` + Config string `json:"Config"` + Stock any `json:"Stock"` + StatusData string `json:"StatusData"` + ShowMonitorData string `json:"ShowMonitorData"` + UpdateTime string `json:"UpdateTime"` + GitRepositoryName string `json:"GitRepositoryName"` + CertifyRequired bool `json:"CertifyRequired"` + IsDisableBackup bool `json:"IsDisableBackup"` + IsHidden bool `json:"IsHidden"` + NodeName string `json:"NodeName"` +} + +type RgsPlan struct { + ID int `json:"id"` + Region string `json:"region"` + Subtype string `json:"subtype"` + PlanName string `json:"plan_name"` + Machine string `json:"machine"` + ChargeType string `json:"charge_type"` + Chinese string `json:"chinese"` + IsFree bool `json:"is_free"` + PointRenewPrice any `json:"point_renew_price"` + IsSelling bool `json:"is_selling"` + StockDiscount int `json:"stock_discount"` + EipStockDiscount int `json:"eip_stock_discount"` + IPPrices any `json:"ip_prices"` + IPSelling any `json:"ip_selling"` + CPUPrice int `json:"cpu_price"` + MemoryPrice int `json:"memory_price"` + NetInPrice int `json:"net_in_price"` + NetOutPrice int `json:"net_out_price"` + BaseDiskPrice int `json:"base_disk_price"` + DataDiskPrice int `json:"data_disk_price"` + Config []RgsPlanConfig `json:"config"` // 这里不知道为什么要返还一堆套餐列表 + AutoRestock int `json:"auto_restock"` + AvailableStock int `json:"available_stock"` + CPUPointDefault int `json:"cpu_point_default"` + CPUPointConsume int `json:"cpu_point_consume"` + CPUPointPrice float64 `json:"cpu_point_price"` + CPUBase float64 `json:"cpu_base"` + CPUMax int `json:"cpu_max"` + EipPrice int `json:"eip_price"` + DefencePrice int `json:"defence_price"` + AllocationPrice int `json:"allocation_price"` + DatabasePrice int `json:"database_price"` + BackupPrice int `json:"backup_price"` + DailyModeSupport bool `json:"daily_mode_support"` + DailyPriceScale int `json:"daily_price_scale"` +} + +type RgsPlanConfig struct { + CPU int `json:"cpu"` + Memory int `json:"memory"` + NetIn int `json:"net_in,omitempty"` + CPUMax int `json:"cpu_max,omitempty"` + CPUMin int `json:"cpu_min,omitempty"` + NetOut int `json:"net_out"` + BaseDisk int `json:"base_disk,omitempty"` + DataDisk int `json:"data_disk,omitempty"` + BasePrice int `json:"base_price"` + MemoryMax int `json:"memory_max"` + MemoryMin int `json:"memory_min"` + NetInMax int `json:"net_in_max,omitempty"` + NetInMin int `json:"net_in_min,omitempty"` + NetOutMax int `json:"net_out_max,omitempty"` + NetOutMin int `json:"net_out_min"` + BaseDiskMax int `json:"base_disk_max,omitempty"` + BaseDiskMin int `json:"base_disk_min,omitempty"` + DataDiskMax int `json:"data_disk_max,omitempty"` + DataDiskMin int `json:"data_disk_min,omitempty"` +} + +// 创建游戏云 +func (s *RgsService) CreateRgs(req *CreateRgsRequest) (*CreateRgsResponse, error) { + path := "/product/rgs" + + var resp CreateRgsResponse + err := s.client.Do(constant.HTTPMethod_POST, path, nil, req, &resp) + return &resp, err +} diff --git a/apis/rgs/eip.go b/apis/rgs/eip.go new file mode 100644 index 0000000..df29762 --- /dev/null +++ b/apis/rgs/eip.go @@ -0,0 +1,42 @@ +package rgs + +import ( + "fmt" + + "github.com/XingfenD/rainyun_api_go_sdk/apis/common" + "github.com/XingfenD/rainyun_api_go_sdk/apis/rcs" + "github.com/XingfenD/rainyun_api_go_sdk/constant" +) + +// 创建并绑定弹性IP到游戏云 +// +// id: 游戏云 ID +func (s *RgsService) CreateAndBindElasticIpToRgs(id int, req *rcs.CreateAndBindIpToRcsRequest) (*common.BasicOperationResponse, error) { + path := fmt.Sprintf("/product/rgs/%d/eip", id) + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_POST, path, nil, req, &resp) + return &resp, err +} + +// 更换游戏云IP +// +// id: 游戏云 ID +func (s *RgsService) ChangeRgsIP(id int, req *rcs.ChangeRcsIPRequest) (*common.BasicOperationResponse, error) { + path := fmt.Sprintf("/product/rgs/%d/eip/change", id) + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_POST, path, nil, req, &resp) + return &resp, err +} + +// 放弃游戏云IP +// +// id: 游戏云ID +func (s *RgsService) DisCardRgsIP(id int, req rcs.DisCardRcsIPRequest) (*common.BasicOperationResponse, error) { + path := fmt.Sprintf("/product/rgs/%d/eip/discard", id) + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_POST, path, nil, req, &resp) + return &resp, err +} diff --git a/apis/rgs/firewall.go b/apis/rgs/firewall.go new file mode 100644 index 0000000..d7cfd83 --- /dev/null +++ b/apis/rgs/firewall.go @@ -0,0 +1,66 @@ +package rgs + +import ( + "fmt" + + "github.com/XingfenD/rainyun_api_go_sdk/apis/common" + "github.com/XingfenD/rainyun_api_go_sdk/apis/rcs" + "github.com/XingfenD/rainyun_api_go_sdk/constant" +) + +type GetRgsFirewallRulesRequest struct { + Options common.StandQueryParameters `json:"options"` +} + +type GetRgsFirewallRulesResponse struct { + Code int `json:"code"` + Data rcs.RcsFirewallRuleList `json:"data"` +} + +// 获取游戏云防火墙规则列表 +// +// id: 游戏云 ID +func (s *RgsService) GetRgsFirewallRules(id int, req *GetRgsFirewallRulesRequest) (*GetRgsFirewallRulesResponse, error) { + path := fmt.Sprintf("/product/rgs/%d/firewall/rule", id) + + var resp GetRgsFirewallRulesResponse + querys, err := common.MarshalQueryParams(req) + if err != nil { + return nil, err + } + err = s.client.Do(constant.HTTPMethod_GET, path, querys, nil, &resp) + return &resp, err +} + +// 创建/设置游戏云防火墙规则 +// +// id: 游戏云 ID +func (s *RgsService) SetRgsFirewallRule(id int, req *rcs.SetRcsFirewallRuleRequest) (*common.BasicOperationResponse, error) { + path := fmt.Sprintf("/product/rgs/%d/firewall/rule", id) + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_POST, path, nil, req, &resp) + return &resp, err +} + +// 删除游戏云防火墙规则 +// +// id: 游戏云 ID +func (s *RgsService) DeleteRgsFirewallRule(id, ruleID int) (*common.BasicOperationResponse, error) { + path := fmt.Sprintf("/product/rgs/%d/firewall/rule/%d", id, ruleID) + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_DELETE, path, nil, nil, &resp) + return &resp, err +} + +// 移动游戏云防火墙规则优先级 +// +// id: 游戏云 ID +func (s *RgsService) MobileRgsFirewallRulePriority(id, ruleID int, req rcs.MobileRcsFirewallRulePriorityRequest) (*common.BasicOperationResponse, error) { + path := fmt.Sprintf("/product/rgs/%d/firewall/rule/%d/pos", id, ruleID) + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_PUT, path, nil, req, &resp) + return &resp, err +} diff --git a/apis/rgs/get_rgs_detail.go b/apis/rgs/get_rgs_detail.go new file mode 100644 index 0000000..65366dc --- /dev/null +++ b/apis/rgs/get_rgs_detail.go @@ -0,0 +1,46 @@ +package rgs + +import ( + "fmt" + + "github.com/XingfenD/rainyun_api_go_sdk/constant" +) + +// 游戏云详情 +// 由于响应实在过于庞大,我们只维护部分必要的响应,如有扩展需求,请在项目的data文件夹下寻找响应实例自行解码 +type GetRgsDetailResponse struct { + Code int `json:"code"` + Data RgsDetailData `json:"data"` +} + +type RgsDetailData struct { + Data RgsRecord `json:"Data"` + NatList []RgsNatItem `json:"NatList"` // 端口映射列表 + EIPList any `json:"EIPList"` + ConfigPrice int `json:"ConfigPrice"` + RenewPointPrice RgsRenewPointPrice `json:"RenewPointPrice"` // 积分续费 +} + +type RgsNatItem struct { + ID int `json:"ID"` + PortIn int `json:"PortIn"` + PortOut int `json:"PortOut"` + PortType string `json:"PortType"` + Tag string `json:"Tag"` +} + +type RgsRenewPointPrice struct { + Num7 int `json:"7"` // 积分续费七天 + Num31 int `json:"31"` // 积分续费31天 +} + +// 获取游戏云详情 +// +// id: 游戏云 ID +func (s *RgsService) GetRgsDetail(id int) (*GetRgsDetailResponse, error) { + path := fmt.Sprintf("/product/rgs/%d", id) + + var resp GetRgsDetailResponse + err := s.client.Do(constant.HTTPMethod_GET, path, nil, nil, &resp) + return &resp, err +} diff --git a/apis/rgs/get_rgs_list.go b/apis/rgs/get_rgs_list.go new file mode 100644 index 0000000..2eaaded --- /dev/null +++ b/apis/rgs/get_rgs_list.go @@ -0,0 +1,126 @@ +package rgs + +import ( + "github.com/XingfenD/rainyun_api_go_sdk/apis/common" + "github.com/XingfenD/rainyun_api_go_sdk/constant" +) + +type GetRgsListRequest struct { + Options common.StandQueryParameters `json:"options"` +} + +type GetRgsListResponse struct { + Code int `json:"code"` + Data RgsListData `json:"data"` +} + +type RgsListData struct { + TotalRecords int `json:"TotalRecords"` + Records []RgsRecord `json:"Records"` +} + +// 游戏云记录信息 +// 由于响应实在过于庞大,我们只维护部分必要的响应,如有扩展需求,请在项目的data文件夹下寻找响应实例自行解码 +type RgsRecord struct { + ExpDate int `json:"ExpDate"` + ExpireNotice int `json:"ExpireNotice"` + AutoRenew bool `json:"AutoRenew"` + UnsubscribeAble bool `json:"UnsubscribeAble"` + Try bool `json:"Try"` + ID int `json:"ID"` + UID int `json:"UID"` + PlanID int `json:"PlanID"` + CreateDate int `json:"CreateDate"` + Status string `json:"Status"` + StopReason string `json:"StopReason"` + RewardPointsToBeCollect int `json:"RewardPointsToBeCollect"` // 待领取的积分 + Tag string `json:"Tag"` + OsID int `json:"OsID"` + OsName string `json:"OsName"` + HostName string `json:"HostName"` + DefaultPass string `json:"DefaultPass"` + MainIPv4 string `json:"MainIPv4"` + IntIPv4 string `json:"IntIPv4"` + UsageData RgsUsageData `json:"UsageData"` + Zone string `json:"Zone"` + NatPublicIP string `json:"NatPublicIP"` + NatPublicDomain string `json:"NatPublicDomain"` + NATSpareDomain string `json:"NATSpareDomain"` + NetIn int `json:"NetIn"` + NetOut int `json:"NetOut"` + NowNetIn int `json:"NowNetIn"` + NowNetOut int `json:"NowNetOut"` + NetMode string `json:"NetMode"` + BridgeSyncing bool `json:"BridgeSyncing"` + VnetID int `json:"VnetID"` + UpdateTime int `json:"UpdateTime"` + FwSyncTime int `json:"FwSyncTime"` + FwMode string `json:"FwMode"` + AbCPULimit int `json:"AbCpuLimit"` + AbNetLimit int `json:"AbNetLimit"` + AbWhiteReason string `json:"AbWhiteReason"` + OsInfo RgsOsInfo `json:"OsInfo"` + CPU int `json:"CPU"` + Memory int `json:"Memory"` + BaseDisk int `json:"BaseDisk"` + DataDisk int `json:"DataDisk"` + InitedDate int `json:"InitedDate"` + Allocation int `json:"Allocation"` + Database int `json:"Database"` + Backup int `json:"Backup"` + CPULimitMode bool `json:"CpuLimitMode"` + CPULimitStatus bool `json:"CpuLimitStatus"` + CPUPoint int `json:"CpuPoint"` + DailyMode bool `json:"DailyMode"` // 是否日付模式 + RBSKeepLast int `json:"RBSKeepLast"` + RBSAutoBackup string `json:"RBSAutoBackup"` + RBSLastAutoBackupDate int `json:"RBSLastAutoBackupDate"` + McsmUserName string `json:"McsmUserName"` + McsmUser McsmUser `json:"McsmUser"` +} + +type RgsUsageData struct { + CPU int `json:"CPU"` + Mem int `json:"Mem"` + MemUsage int `json:"MemUsage"` + DiskRead int `json:"DiskRead"` + DiskWrite int `json:"DiskWrite"` + Disk int `json:"Disk"` + NetOut int `json:"NetOut"` + NetIn int `json:"NetIn"` + UpdateTime int `json:"UpdateTime"` +} + +type RgsOsInfo struct { + ID int `json:"id"` + Region string `json:"region"` + Subtype string `json:"subtype"` + Machine string `json:"machine"` + Name string `json:"name"` + Version string `json:"version"` + SyncStatus string `json:"sync_status"` + OsType string `json:"os_type"` + ChineseName string `json:"chinese_name"` + Icon string `json:"icon"` + IsWithBbr bool `json:"is_with_bbr"` + IsEol bool `json:"is_eol"` + IsAvailable bool `json:"is_available"` + Order int `json:"order"` + LatestFilename string `json:"latest_filename"` + NoVMAgent bool `json:"no_vm_agent"` +} + +// 获取游戏云列表 +// +// options: 查询参数 可以用 common.StandQueryParameters 获取 +func (s *RgsService) GetRgsList(req *GetRgsListRequest) (*GetRgsListResponse, error) { + path := "/product/rgs" + + var resp GetRgsListResponse + querys, err := common.MarshalQueryParams(req) + if err != nil { + return nil, err + } + err = s.client.Do(constant.HTTPMethod_GET, path, querys, nil, &resp) + return &resp, err +} diff --git a/apis/rgs/lifecycle.go b/apis/rgs/lifecycle.go new file mode 100644 index 0000000..128da83 --- /dev/null +++ b/apis/rgs/lifecycle.go @@ -0,0 +1,164 @@ +package rgs + +import ( + "fmt" + + "github.com/XingfenD/rainyun_api_go_sdk/apis/common" + "github.com/XingfenD/rainyun_api_go_sdk/apis/rcs" + "github.com/XingfenD/rainyun_api_go_sdk/constant" +) + +// 通用模式切换请求 +type RgsSwitchModeRequest struct { + Mode bool `json:"mode"` +} + +// 游戏云CPU充电请求 +type ChargeRgsCPURequest struct { + Mode string `json:"mode"` // 支付方式(money/point) + Money int `json:"money"` // 消耗用户余额(支付方式为point时0) + Points int `json:"points"` // 消耗用户积分(支付方式为money时0) +} + +// 游戏云更换egg(游戏类型)请求 +type ChangeRgsEggRequest struct { + EggTypeID int `json:"egg_type_id"` // 蛋ID + SaveDirs []string `json:"save_dirs"` // 要保留的目录 +} + +// 释放游戏云 +// +// id: 游戏云ID +func (s *RgsService) FreeRgs(id int) (*common.BasicOperationResponse, error) { + path := fmt.Sprintf("/product/rgs/%d/free", id) + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_POST, path, nil, nil, &resp) + return &resp, err +} + +// 游戏云重启操作 +// +// id: RGS ID +func (s *RgsService) RebootRgs(id int) (*common.BasicOperationResponse, error) { + path := fmt.Sprintf("/product/rgs/%d/reboot", id) + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_POST, path, nil, nil, &resp) + return &resp, err +} + +// 游戏云重置密码 +// +// id: 游戏云ID +// +// newPass: 新密码,留空则自动生成 +func (s *RgsService) ResetRgsPassword(id int, newPass string) (*common.BasicOperationResponse, error) { + path := fmt.Sprintf("/product/rgs/%d/reset-password", id) + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_POST, path, nil, rcs.ResetRcsPasswordRequest{Password: newPass}, &resp) + return &resp, err +} + +// 游戏云开机 +// +// id: 游戏云ID +func (s *RgsService) StartRgs(id int) (*common.BasicOperationResponse, error) { + path := fmt.Sprintf("/product/rgs/%d/start", id) + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_POST, path, nil, nil, &resp) + return &resp, err +} + +// 游戏云关机 +// +// id: 游戏云ID +func (s *RgsService) StopRgs(id int) (*common.BasicOperationResponse, error) { + path := fmt.Sprintf("/product/rgs/%d/stop", id) + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_POST, path, nil, nil, &resp) + return &resp, err +} + +// 设置游戏云标签 +// +// id: 游戏云ID +// +// tag: 标签 +func (s *RgsService) SetRgsTag(id int, tag string) (*common.BasicOperationResponse, error) { + path := fmt.Sprintf("/product/rgs/%d/tag", id) + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_POST, path, nil, rcs.SetRcsTagRequest{TagName: tag}, &resp) + return &resp, err +} + +// 游戏云限制模式(是否用余额结算)切换 +// +// id: 游戏云 ID +// +// useMoney: 是否用余额结算CPU电量 +func (s *RgsService) SwitchRgsBalanceMode(id int, useMoney bool) (*common.BasicOperationResponse, error) { + path := fmt.Sprintf("/product/rgs/%d/cpu-limit-mode", id) + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_POST, path, nil, RgsSwitchModeRequest{Mode: useMoney}, &resp) + return &resp, err +} + +// 游戏云日付模式开关 +// +// id: 游戏云 ID +// +// dailyMode: true: 开启日付模式,false: 关闭日付模式 +func (s *RgsService) SwitchRgsDailyMode(id int, dailyMode bool) (*common.BasicOperationResponse, error) { + path := fmt.Sprintf("/product/rgs/%d/daily-mode", id) + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_POST, path, nil, RgsSwitchModeRequest{Mode: dailyMode}, &resp) + return &resp, err +} + +// 游戏云CPU充电 +// +// id: 游戏云 ID +func (s *RgsService) ChargeRgsCPU(id int, req *ChargeRgsCPURequest) (*common.BasicOperationResponse, error) { + path := fmt.Sprintf("/product/rgs/%d/cpu-charge", id) + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_POST, path, nil, req, &resp) + return &resp, err +} + +// 游戏云升级 +// +// id: 游戏云ID +// +// plan: 升级到的套餐ID +// +// coupon: 优惠券ID,默认为0 +func (s *RgsService) UpgradeRgs(id, plan, coupon int) (*common.BasicOperationResponse, error) { + path := fmt.Sprintf("/product/rgs/%d/upgrade", id) + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_POST, path, nil, rcs.UpgradeRcsRequest{DestPlan: plan, WithCouponID: coupon}, &resp) + return &resp, err +} + +// 游戏云更换egg(游戏类型) +// +// 此操作需要二步验证 +// +// eggTypeID: 游戏类型ID +// +// saveDirs: 要保留的目录 +func (s *RgsService) ChangeRgsEgg(id int, eggTypeID int, saveDirs []string) (*common.BasicOperationResponse, error) { + path := fmt.Sprintf("/product/rgs/%d/change-egg", id) + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_POST, path, nil, ChangeRgsEggRequest{EggTypeID: eggTypeID, SaveDirs: saveDirs}, &resp) + return &resp, err +} diff --git a/apis/rgs/mcsm.go b/apis/rgs/mcsm.go new file mode 100644 index 0000000..b4d02d0 --- /dev/null +++ b/apis/rgs/mcsm.go @@ -0,0 +1,53 @@ +package rgs + +import ( + "fmt" + + "github.com/XingfenD/rainyun_api_go_sdk/apis/common" + "github.com/XingfenD/rainyun_api_go_sdk/constant" +) + +// MCSM面板用户 +type McsmUser struct { + Name string `json:"name"` + Password string `json:"password"` + UserID int `json:"user_id,omitempty"` + PanelUUID string `json:"panel_uuid,omitempty"` +} + +// 创建MCSM面板用户 +// +// name: 用户名 +// +// password: 密码 +func (s *RgsService) CreateMcsmUser(name, password string) (*common.BasicOperationResponse, error) { + path := "/product/rgs/mcsm/panel_user" + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_POST, path, nil, McsmUser{Name: name, Password: password}, &resp) + return &resp, err +} + +// 编辑MCSM面板用户 +// +// name: 用户名 +// +// password: 密码 +func (s *RgsService) EditMcsmUser(name, password string) (*common.BasicOperationResponse, error) { + path := "/product/rgs/mcsm/panel_user" + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_PATCH, path, nil, McsmUser{Name: name, Password: password}, &resp) + return &resp, err +} + +// 删除MCSM面板用户 +// +// name: 用户名 +func (s *RgsService) DeleteMcsmUser(name string) (*common.BasicOperationResponse, error) { + path := fmt.Sprintf("/product/rgs/mcsm/panel_user/%s", name) + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_DELETE, path, nil, nil, &resp) + return &resp, err +} diff --git a/apis/rgs/monitor.go b/apis/rgs/monitor.go new file mode 100644 index 0000000..d8c1dc1 --- /dev/null +++ b/apis/rgs/monitor.go @@ -0,0 +1,38 @@ +package rgs + +import ( + "fmt" + + "github.com/XingfenD/rainyun_api_go_sdk/apis/common" + "github.com/XingfenD/rainyun_api_go_sdk/apis/rcs" + "github.com/XingfenD/rainyun_api_go_sdk/constant" +) + +type GetRgsMonitorDataRequest struct { + StartDate int `json:"start_date"` // 开始时间(时间戳) + EndDate int `json:"end_date"` // 结束时间(时间戳) +} + +type GetRgsMonitorDataResponse struct { + Code int `json:"code"` + Data rcs.RcsMonitorData `json:"data"` +} + +// 获取游戏云监控数据 +// +// id: 游戏云ID +// +// startDate: 开始时间 +// +// endDate: 结束时间 +func (s *RgsService) GetRgsMonitorData(id int, req *GetRgsMonitorDataRequest) (*GetRgsMonitorDataResponse, error) { + path := fmt.Sprintf("/product/rgs/%d/monitor", id) + + var resp GetRgsMonitorDataResponse + querys, err := common.MarshalQueryParams(req) + if err != nil { + return nil, err + } + err = s.client.Do(constant.HTTPMethod_GET, path, querys, nil, &resp) + return &resp, err +} diff --git a/apis/rgs/nat.go b/apis/rgs/nat.go new file mode 100644 index 0000000..527142a --- /dev/null +++ b/apis/rgs/nat.go @@ -0,0 +1,20 @@ +package rgs + +import ( + "fmt" + + "github.com/XingfenD/rainyun_api_go_sdk/apis/common" + "github.com/XingfenD/rainyun_api_go_sdk/apis/rcs" + "github.com/XingfenD/rainyun_api_go_sdk/constant" +) + +// 添加游戏云NAT端口映射 +// +// id: 游戏云 ID +func (s *RgsService) AddRgsNatPortMapping(id int, req *rcs.AddRcsNatPortMappingRequest) (*common.BasicOperationResponse, error) { + path := fmt.Sprintf("/product/rgs/%d/nat", id) + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_POST, path, nil, req, &resp) + return &resp, err +} diff --git a/apis/rgs/renew.go b/apis/rgs/renew.go new file mode 100644 index 0000000..0e2e47d --- /dev/null +++ b/apis/rgs/renew.go @@ -0,0 +1,111 @@ +package rgs + +import ( + "fmt" + + "github.com/XingfenD/rainyun_api_go_sdk/apis/common" + "github.com/XingfenD/rainyun_api_go_sdk/apis/rcs" + "github.com/XingfenD/rainyun_api_go_sdk/constant" +) + +type GetRgsRenewPriceRequest struct { + ProductID int `json:"product_id"` + Duration int `json:"duration"` + WithCouponID int `json:"with_coupon_id"` +} + +type GetRgsRenewPriceResponse struct { + Code int `json:"code"` + Data rcs.RcsRenewPrice `json:"data"` +} + +type GetRgsUpgradePriceRequest struct { + ProductID int `json:"product_id"` + Duration int `json:"duration"` + WithCouponID int `json:"with_coupon_id"` + Config RgsConfig `json:"config"` +} + +// 游戏云升级价格 +type GetRgsUpgradePriceResponse struct { + Code int `json:"code"` + Data RgsUpgradePriceData `json:"data"` +} + +type RgsUpgradePriceData struct { + Detail RgsUpgradePriceDetail `json:"detail"` + Price int `json:"price"` +} + +type RgsUpgradePriceDetail struct { + Price int `json:"price"` + AgentPrice int `json:"agent_price"` + StockPrice int `json:"stock_price"` + DefaultPrice int `json:"default_price"` + CouponValue int `json:"coupon_value"` + SaleReward int `json:"sale_reward"` + AgentReward int `json:"agent_reward"` + AgentID int `json:"agent_id"` + IgnoreAgent bool `json:"ignore_agent"` + PerScene RgsUpgradePerScene `json:"per_scene"` +} + +type RgsUpgradePerScene struct { + Upgrade int `json:"upgrade"` +} + +// 获取游戏云续费价格 +// +// id: RGS ID, duration: 续费时长(月), coupon: 优惠券ID +func (s *RgsService) GetRgsRenewPrice(req *GetRgsRenewPriceRequest) (*GetRgsRenewPriceResponse, error) { + path := "/product/rgs/price" + + var resp GetRgsRenewPriceResponse + querys, err := common.MarshalQueryParams(req) + if err != nil { + return nil, err + } + querys["scene"] = "renew" + querys["is_old"] = "true" + err = s.client.Do(constant.HTTPMethod_GET, path, querys, nil, &resp) + return &resp, err +} + +// 游戏云续费 +// +// id: 游戏云ID +func (s *RgsService) RenewRgs(id int, req rcs.RenewRcsRequest) (*common.BasicOperationResponse, error) { + path := fmt.Sprintf("/product/rgs/%d/renew", id) + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_POST, path, nil, req, &resp) + return &resp, err +} + +// 游戏云自动续费选项 +// +// id: 游戏云ID +func (s *RgsService) EnableRgsAutoRenew(id int, req rcs.EnableRcsAutoRenewRequest) (*common.BasicOperationResponse, error) { + path := fmt.Sprintf("/product/rgs/%d/renew/option", id) + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_POST, path, nil, req, &resp) + return &resp, err +} + +// 获取游戏云升级价格 +// +// id: RGS ID, duration: 续费时长(月), coupon: 优惠券ID +func (s *RgsService) GetRgsUpgradePrice(req *GetRgsUpgradePriceRequest) (*GetRgsUpgradePriceResponse, error) { + path := "/product/rgs/price" + + var resp GetRgsUpgradePriceResponse + querys, err := common.MarshalQueryParams(req) + if err != nil { + return nil, err + } + querys["scene"] = "upgrade" + querys["is_old"] = "true" + err = s.client.Do(constant.HTTPMethod_GET, path, querys, nil, &resp) + return &resp, err +} diff --git a/apis/rgs/vnc.go b/apis/rgs/vnc.go new file mode 100644 index 0000000..6dc42c4 --- /dev/null +++ b/apis/rgs/vnc.go @@ -0,0 +1,40 @@ +package rgs + +import ( + "fmt" + "net/url" + + "github.com/XingfenD/rainyun_api_go_sdk/apis/common" + "github.com/XingfenD/rainyun_api_go_sdk/constant" +) + +// 游戏云连接VNC +// +// id: 游戏云ID +// +// consoleType: 控制台类型,可选值: novnc,xtermjs +func (s *RgsService) GetRgsVnc(id int, consoleType string) (*common.VncConnectionInfo, error) { + path := fmt.Sprintf("/product/rgs/%d/vnc", id) + + var resp common.VncConnectionInfo + querys := map[string]string{"console_type": consoleType} + err := s.client.Do(constant.HTTPMethod_GET, path, querys, nil, &resp) + return &resp, err +} + +// 获取游戏云对应的PVE地址 +// +// id: 游戏云ID +func (s *RgsService) GetRgsPveAddress(id int) (string, error) { + v, err := s.GetRgsVnc(id, "novnc") + if err != nil { + return "", err + } + + parsedURL, err := url.Parse(v.Data.RequestURL) + if err != nil { + return "", err + } + + return parsedURL.Hostname(), nil +} diff --git a/apis/ros/bucket.go b/apis/ros/bucket.go new file mode 100644 index 0000000..dd5c1b9 --- /dev/null +++ b/apis/ros/bucket.go @@ -0,0 +1,196 @@ +package ros + +import ( + "fmt" + + "github.com/XingfenD/rainyun_api_go_sdk/apis/common" + "github.com/XingfenD/rainyun_api_go_sdk/constant" +) + +// 创建对象存储桶请求 +type CreateRosBucketRequest struct { + BucketName string `json:"bucket_name"` // 存储桶名称 + InstanceID int `json:"instance_id"` // 实例ID +} + +// 创建对象存储桶响应 +type CreateRosBucketResponse struct { + Code int `json:"code"` + Data RosBucket `json:"data"` +} + +// 获取对象存储桶列表请求 +type GetRosBucketListRequest struct { + Options common.StandQueryParameters `json:"options"` +} + +// 获取对象存储桶列表响应 +type GetRosBucketListResponse struct { + Code int `json:"code"` + Data RosBucketList `json:"data"` +} + +// 对象存储桶列表 +type RosBucketList struct { + TotalRecords int `json:"TotalRecords"` + Records []RosBucket `json:"Records"` +} + +// 获取对象存储桶详情响应 +type GetRosBucketDetailResponse struct { + Code int `json:"code"` + Data RosBucketDetail `json:"data"` +} + +// 对象存储桶详情 +type RosBucketDetail struct { + Data RosBucket `json:"Data"` +} + +// 修改存储桶Proxy设置请求 +// 一个请求只能设置一项设置,要设置的设置项需要放在 Setting 中,只需要写需要修改的设置项,其他不填 +type ModifyRosBucketProxySettingsRequest struct { + DomainList []string `json:"domain_list,omitempty"` // 域名列表 + GzipSettings RosGzipSettings `json:"gzip_settings,omitempty"` + IPRestrictSettings RosIPRestrictSettings `json:"ip_restrict_settings,omitempty"` + RefererRestrictSettings RosRefererRestrictSettings `json:"referer_restrict_settings,omitempty"` + Setting string `json:"setting"` // 必选项,要设置的选项(domain/ssl/waf/gzip/ip_restrict/referer_restrict) + SslSettings RosSslSettings `json:"ssl_settings,omitempty"` + WafSettings RosWafSettings `json:"waf_settings,omitempty"` +} + +// Gzip设置 +type RosGzipSettings struct { + CompressLevel int `json:"compress_level,omitempty"` // 压缩等级(1-5,默认为2) + FileTypes []string `json:"file_types,omitempty"` // 文件MIME类型,默认["*"] + IsEnable bool `json:"is_enable,omitempty"` // 是否启用GZIP压缩,默认启用 +} + +// IP访问限制设置 +type RosIPRestrictSettings struct { + Blacklist []string `json:"blacklist,omitempty"` // 黑名单IP或CIDR范围列表,和白名单列表只能二选一不能共存 + IsEnable bool `json:"is_enable,omitempty"` // 是否启用IP访问限制 + Whitelist []string `json:"whitelist,omitempty"` // 白名单IP或CIDR范围列表,和黑名单列表只能二选一不能共存 +} + +// Referer防盗链设置 +type RosRefererRestrictSettings struct { + Blacklist []string `json:"blacklist,omitempty"` // 黑名单域名列表,和白名单列表只能二选一不能共存 + BypassMissing bool `json:"bypass_missing,omitempty"` // 是否允许Referer请求头不存在或者格式有误 + IsEnable bool `json:"is_enable,omitempty"` // 是否启用Referer防盗链 + Whitelist []string `json:"whitelist,omitempty"` // 白名单域名列表,和黑名单列表只能二选一不能共存 +} + +// SSL设置,SSL证书会自动匹配 +type RosSslSettings struct { + IsEnable bool `json:"is_enable,omitempty"` // 是否启用SSL + IsForce bool `json:"is_force,omitempty"` // 是否强制使用SSL +} + +// WAF防火墙设置 +type RosWafSettings struct { + BlockTime int `json:"block_time,omitempty"` // 未通过JS验证时的封禁时间,秒 + GlobalJsCheck bool `json:"global_js_check,omitempty"` // 是否启用全局JS检查,只有超过阈值才会生效 + GlobalQPS int `json:"global_qps,omitempty"` // 全局访问速率限制,超过会被拒绝 + IsEnable bool `json:"is_enable,omitempty"` // 是否启用WAF防火墙 + PerIPJsCheck bool `json:"per_ip_js_check,omitempty"` // 是否启用单IP JS检查,只有超过阈值才会生效 + PerIPQPS int `json:"per_ip_qps,omitempty"` // 单个IP访问速率限制,超过会被拒绝 +} + +// 获取对象存储桶列表 +// +// ⚠️注意这个接口是拿不到AK和SK的,响应里面的AK和SK都是空的 +func (s *RosService) GetRosBucketList(req *GetRosBucketListRequest) (*GetRosBucketListResponse, error) { + path := "/product/ros/bucket/" + + var resp GetRosBucketListResponse + querys, err := common.MarshalQueryParams(req) + if err != nil { + return nil, err + } + err = s.client.Do(constant.HTTPMethod_GET, path, querys, nil, &resp) + return &resp, err +} + +// 创建对象存储桶 +// +// req: 创建参数(bucketName 存储桶名 >= 3 字符 <= 63 字符) +func (s *RosService) CreateRosBucket(req CreateRosBucketRequest) (*CreateRosBucketResponse, error) { + path := "/product/ros/bucket" + + var resp CreateRosBucketResponse + err := s.client.Do(constant.HTTPMethod_POST, path, nil, req, &resp) + return &resp, err +} + +// 获取对象存储桶详情 +// +// bucketID: 存储桶ID +func (s *RosService) GetRosBucketDetail(bucketID int) (*GetRosBucketDetailResponse, error) { + path := fmt.Sprintf("/product/ros/bucket/%d", bucketID) + + var resp GetRosBucketDetailResponse + err := s.client.Do(constant.HTTPMethod_GET, path, nil, nil, &resp) + return &resp, err +} + +// 删除对象存储桶 +// +// bucketID: 存储桶ID +func (s *RosService) DeleteRosBucket(bucketID int) (*common.BasicOperationResponse, error) { + path := fmt.Sprintf("/product/ros/bucket/%d", bucketID) + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_DELETE, path, nil, nil, &resp) + return &resp, err +} + +// 获取对象存储桶监控数据 +// +// bucketID: 存储桶ID +// +// req: 开始时间/结束时间(timestamp) +func (s *RosService) GetRosBucketMonitorData(bucketID int, req *GetRosMonitorDataRequest) (*GetRosMonitorDataResponse, error) { + path := fmt.Sprintf("/product/ros/bucket/%d/monitor", bucketID) + + var resp GetRosMonitorDataResponse + querys, err := common.MarshalQueryParams(req) + if err != nil { + return nil, err + } + err = s.client.Do(constant.HTTPMethod_GET, path, querys, nil, &resp) + return &resp, err +} + +// 修改存储桶Proxy设置 +// +// bucketID: 存储桶ID +func (s *RosService) ModifyRosBucketProxySettings(bucketID int, req *ModifyRosBucketProxySettingsRequest) (*common.BasicOperationResponse, error) { + path := fmt.Sprintf("/product/ros/bucket/%d/proxy", bucketID) + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_PATCH, path, nil, req, &resp) + return &resp, err +} + +// 对象存储桶重新生成密钥 +// +// bucketID: 存储桶ID +func (s *RosService) ReGenerateRosBucketKeys(bucketID int) (*common.BasicOperationResponse, error) { + path := fmt.Sprintf("/product/ros/bucket/%d/regenerate-keys", bucketID) + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_POST, path, nil, nil, &resp) + return &resp, err +} + +// 开关对象存储桶匿名访问 +// +// bucketID: 存储桶ID +func (s *RosService) SetRosBucketPublicAccess(bucketID int) (*common.BasicOperationResponse, error) { + path := fmt.Sprintf("/product/ros/bucket/%d/toggle-public-access", bucketID) + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_POST, path, nil, nil, &resp) + return &resp, err +} diff --git a/apis/ros/client.go b/apis/ros/client.go new file mode 100644 index 0000000..6c41a35 --- /dev/null +++ b/apis/ros/client.go @@ -0,0 +1,11 @@ +package ros + +import "github.com/XingfenD/rainyun_api_go_sdk/apis" + +type RosService struct { + client *apis.RyClient +} + +func NewRosService(c *apis.RyClient) *RosService { + return &RosService{client: c} +} diff --git a/apis/ros/instance.go b/apis/ros/instance.go new file mode 100644 index 0000000..72041e4 --- /dev/null +++ b/apis/ros/instance.go @@ -0,0 +1,224 @@ +package ros + +import ( + "fmt" + + "github.com/XingfenD/rainyun_api_go_sdk/apis/common" + "github.com/XingfenD/rainyun_api_go_sdk/constant" +) + +// 创建对象存储实例请求 +type CreateRosInstanceRequest struct { + Duration int `json:"duration"` // 购买时长(月) + PlanID int `json:"plan_id"` // 套餐ID + WithCouponID int `json:"with_coupon_id"` // 优惠券ID +} + +// 创建对象存储实例响应 +type CreateRosInstanceResponse struct { + Code int `json:"code"` + Data RosInstance `json:"data"` +} + +// 获取对象存储实例列表请求 +type GetRosInstanceListRequest struct { + Options common.StandQueryParameters `json:"options"` +} + +// 获取对象存储实例列表响应 +type GetRosInstanceListResponse struct { + Code int `json:"code"` + Data RosInstanceList `json:"data"` +} + +// 对象存储实例列表 +type RosInstanceList struct { + TotalRecords int `json:"TotalRecords"` + Records []RosInstance `json:"Records"` +} + +// 获取对象存储实例详情响应 +type GetRosInstanceDetailResponse struct { + Code int `json:"code"` + Data RosInstanceDetail `json:"data"` +} + +// 对象存储实例详情 +type RosInstanceDetail struct { + Data RosInstance `json:"Data"` + RenewPointPrice RosRenewPointPrice `json:"RenewPointPrice"` // 积分续费 +} + +// 对象存储积分续费价格 +type RosRenewPointPrice struct { + Num7 int `json:"7"` // 积分续费七天 + Num31 int `json:"31"` // 积分续费一个月 +} + +// ROS实例续费请求 +type RenewRosInstanceRequest struct { + Duration int `json:"duration"` // 续费时长(月) + WithCouponID int `json:"with_coupon_id"` // 优惠券ID +} + +// ROS实例自动续费选项 +type RosInstanceAutoRenewOption struct { + AutoRenewOption bool `json:"auto_renew_option"` +} + +// ROS实例缩放请求 +type ScaleRosInstanceRequest struct { + DestPlan int `json:"dest_plan"` // 目标套餐ID + WithCouponID int `json:"with_coupon_id"` // 优惠券ID +} + +// 设置对象存储实例标签请求 +type SetRosInstanceTagRequest struct { + TagName string `json:"tag_name"` +} + +// 开关对象存储实例的弹性计费选项请求 +type ToggleRosInstanceExtraAccountingRequest struct { + IsEnable bool `json:"is_enable"` +} + +// 创建对象存储实例 +// +// req: 创建参数 +func (s *RosService) CreateRosInstance(req CreateRosInstanceRequest) (*CreateRosInstanceResponse, error) { + path := "/product/ros/instance" + + var resp CreateRosInstanceResponse + err := s.client.Do(constant.HTTPMethod_POST, path, nil, req, &resp) + return &resp, err +} + +// 获取对象存储实例详情 +// +// instanceID: 实例ID +func (s *RosService) GetRosInstanceDetail(instanceID int) (*GetRosInstanceDetailResponse, error) { + path := fmt.Sprintf("/product/ros/instance/%d", instanceID) + + var resp GetRosInstanceDetailResponse + err := s.client.Do(constant.HTTPMethod_GET, path, nil, nil, &resp) + return &resp, err +} + +// 获取对象存储实例列表 +// +// ⚠️注意这个接口是拿不到AK和SK的,响应里面的AK和SK都是空的 +func (s *RosService) GetRosInstanceList(req *GetRosInstanceListRequest) (*GetRosInstanceListResponse, error) { + path := "/product/ros/instance/" + + var resp GetRosInstanceListResponse + querys, err := common.MarshalQueryParams(req) + if err != nil { + return nil, err + } + err = s.client.Do(constant.HTTPMethod_GET, path, querys, nil, &resp) + return &resp, err +} + +// 获取对象存储实例监控数据 +// +// instanceID: 实例ID +// +// req: 开始时间/结束时间(timestamp) +func (s *RosService) GetRosInstanceMonitorData(instanceID int, req *GetRosMonitorDataRequest) (*GetRosMonitorDataResponse, error) { + path := fmt.Sprintf("/product/ros/instance/%d/monitor", instanceID) + + var resp GetRosMonitorDataResponse + querys, err := common.MarshalQueryParams(req) + if err != nil { + return nil, err + } + err = s.client.Do(constant.HTTPMethod_GET, path, querys, nil, &resp) + return &resp, err +} + +// 对象存储实例续费 +// +// instanceID: 实例ID +// +// req: 续费参数 +func (s *RosService) RenewRosInstance(instanceID int, req RenewRosInstanceRequest) (*common.BasicOperationResponse, error) { + path := fmt.Sprintf("/product/ros/instance/%d/renew", instanceID) + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_POST, path, nil, req, &resp) + return &resp, err +} + +// 对象存储实例自动续费选项 +// +// instanceID: 实例ID +// +// isOpen: 是否开启自动续费 +func (s *RosService) SetRosInstanceAutoRenewOption(instanceID int, isOpen bool) (*common.BasicOperationResponse, error) { + path := fmt.Sprintf("/product/ros/instance/%d/renew/option", instanceID) + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_POST, path, nil, RosInstanceAutoRenewOption{AutoRenewOption: isOpen}, &resp) + return &resp, err +} + +// ROS实例缩放 +// +// instanceID: 实例ID +// +// req: 缩放参数 +func (s *RosService) ScaleRosInstance(instanceID int, req ScaleRosInstanceRequest) (*common.BasicOperationResponse, error) { + path := fmt.Sprintf("/product/ros/instance/%d/scale", instanceID) + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_POST, path, nil, req, &resp) + return &resp, err +} + +// 设置对象存储实例标签 +// +// instanceID: 实例ID +// +// tag: 标签 +func (s *RosService) SetRosInstanceTags(instanceID int, tag string) (*common.BasicOperationResponse, error) { + path := fmt.Sprintf("/product/ros/instance/%d/tag", instanceID) + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_PATCH, path, nil, SetRosInstanceTagRequest{TagName: tag}, &resp) + return &resp, err +} + +// 开关对象存储实例的弹性计费选项 +// +// instanceID: 实例ID +// +// isEnable: 是否开启 +func (s *RosService) ToggleRosInstanceExtraAccounting(instanceID int, isEnable bool) (*common.BasicOperationResponse, error) { + path := fmt.Sprintf("/product/ros/instance/%d/toggle-extra-accounting", instanceID) + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_PATCH, path, nil, ToggleRosInstanceExtraAccountingRequest{IsEnable: isEnable}, &resp) + return &resp, err +} + +// 对象存储实例重新生成密钥 +// +// instanceID: 实例ID +func (s *RosService) ReGenerateRosInstanceKeys(instanceID int) (*common.BasicOperationResponse, error) { + path := fmt.Sprintf("/product/ros/instance/%d/regenerate-keys", instanceID) + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_POST, path, nil, nil, &resp) + return &resp, err +} + +// 开关对象存储实例匿名访问 +// +// instanceID: 实例ID +func (s *RosService) SetRosInstancePublicAccess(instanceID int) (*common.BasicOperationResponse, error) { + path := fmt.Sprintf("/product/ros/instance/%d/toggle-public-access", instanceID) + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_POST, path, nil, nil, &resp) + return &resp, err +} diff --git a/apis/ros/model.go b/apis/ros/model.go new file mode 100644 index 0000000..8169c25 --- /dev/null +++ b/apis/ros/model.go @@ -0,0 +1,141 @@ +package ros + +// RosNode 节点信息 +type RosNode struct { + UUID string `json:"UUID"` + AuthKey string `json:"AuthKey"` + Region string `json:"Region"` + IPRegion string `json:"IpRegion"` + Machine string `json:"Machine"` + Product string `json:"Product"` + Subtype string `json:"Subtype"` + ChineseName string `json:"ChineseName"` + PhysicalNode string `json:"PhysicalNode"` + Config string `json:"Config"` + Stock any `json:"Stock"` + StatusData string `json:"StatusData"` + ShowMonitorData string `json:"ShowMonitorData"` + UpdateTime string `json:"UpdateTime"` + GitRepositoryName string `json:"GitRepositoryName"` + CertifyRequired bool `json:"CertifyRequired"` + IsDisableBackup bool `json:"IsDisableBackup"` + IsHidden bool `json:"IsHidden"` + NodeName string `json:"NodeName"` +} + +// RosPlan 套餐信息 +type RosPlan struct { + ID int `json:"id"` + Region string `json:"region"` + Subtype string `json:"subtype"` + PlanName string `json:"plan_name"` + Machine string `json:"machine"` + ChargeType string `json:"charge_type"` + Chinese string `json:"chinese"` + IsFree bool `json:"is_free"` + PointRenewPrice any `json:"point_renew_price"` + IsSelling bool `json:"is_selling"` + Price int `json:"price"` + StorageSize int `json:"storage_size"` + Bandwidth int `json:"bandwidth"` + ExtraTransferPrice float64 `json:"extra_transfer_price"` + ExtraStoragePrice float64 `json:"extra_storage_price"` +} + +// RosUsageData 实例使用数据 +type RosUsageData struct { + MetricsUsageTotalBytes int `json:"metrics_usage_total_bytes"` // 存储使用量 + MetricsReceivedBytes int `json:"metrics_received_bytes"` // 接收字节数 + MetricsSentBytes int `json:"metrics_sent_bytes"` // 发送字节数 + MetricsRequests int `json:"metrics_requests"` // 请求数 + SpeedReceivedBytes int `json:"speed_received_bytes"` // 接收字节速度 + SpeedSentBytes int `json:"speed_sent_bytes"` // 发送字节速度 + SpeedRequests int `json:"speed_requests"` // 请求速度 + UpdateTime int `json:"UpdateTime"` // 更新时间 +} + +// RosInstance 对象存储实例信息 +type RosInstance struct { + ID int `json:"ID"` + UID int `json:"UID"` + PlanID int `json:"PlanID"` + CreateDate int `json:"CreateDate"` // 创建时间 + NodeUUID string `json:"NodeUUID"` // 节点UUID + Node RosNode `json:"Node"` // 节点信息 + Status string `json:"Status"` + StopReason string `json:"StopReason"` + + RewardPointsToBeCollect int `json:"RewardPointsToBeCollect"` // 待领取积分奖励 + Tag string `json:"Tag"` + Plan RosPlan `json:"Plan"` + AccessKey string `json:"access_key"` // ⚠️列表接口拿不到AK,响应里面的AK是空的 + SecretKey string `json:"secret_key"` // ⚠️列表接口拿不到SK,响应里面的SK是空的 + IsPublicAccess bool `json:"is_public_access"` // 是否允许公共访问 + IsEnableExtraAccounting bool `json:"is_enable_extra_accounting"` // 是否启用额外计费 + LastResetDate int `json:"last_reset_date"` // 最后重置时间 + NextResetDate int `json:"next_reset_date"` // 下次重置时间 + ExpDate int `json:"ExpDate"` // 到期时间 + ExpireNotice int `json:"ExpireNotice"` + AutoRenew bool `json:"AutoRenew"` // 是否自动续费 + UnsubscribeAble bool `json:"UnsubscribeAble"` + Try bool `json:"Try"` // 是否试用 + PublicAPIURL string `json:"public_api_url"` + Buckets any `json:"buckets"` + ExtraPayTime int `json:"extra_pay_time"` + UsageData RosUsageData `json:"UsageData"` + Restrictions string `json:"restrictions"` + PublicAccessRestricted bool `json:"public_access_restricted"` +} + +// RosBucket 对象存储桶信息 +type RosBucket struct { + ID int `json:"id"` // 存储桶ID + Name string `json:"name"` // 存储桶名称 + UID int `json:"uid"` // 用户ID + CreateDate int `json:"create_date"` + AccessKey string `json:"access_key"` // ⚠️列表接口拿不到AK,响应里面的AK是空的 + SecretKey string `json:"secret_key"` // ⚠️列表接口拿不到SK,响应里面的SK是空的 + IsPublicAccess bool `json:"is_public_access"` // 是否公开 + InstanceID int `json:"instance_id"` // 实例ID + Instance RosInstance `json:"Instance"` + StopReason string `json:"stop_reason"` + DomainList any `json:"DomainList"` + SslIsEnable bool `json:"ssl_is_enable"` + SSLCertList any `json:"SSLCertList"` + SslAutoRedirect bool `json:"ssl_auto_redirect"` + WafIsEnable bool `json:"waf_is_enable"` + WafGlobalQPS int `json:"waf_global_qps"` + WafPerIPQPS int `json:"waf_per_ip_qps"` + WafBlockTime int `json:"waf_block_time"` + WafGlobalJsCheck bool `json:"waf_global_js_check"` + WafPerIPJsCheck bool `json:"waf_per_ip_js_check"` + RefererRestrictIsEnable bool `json:"referer_restrict_is_enable"` + RefererRestrictWhitelist any `json:"RefererRestrictWhitelist"` + RefererRestrictBlacklist any `json:"RefererRestrictBlacklist"` + RefererRestrictBypassMissing bool `json:"referer_restrict_bypass_missing"` + IPRestrictIsEnable bool `json:"ip_restrict_is_enable"` + IPRestrictWhitelist any `json:"IPRestrictWhitelist"` + IPRestrictBlacklist any `json:"IPRestrictBlacklist"` + GzipIsEnable bool `json:"gzip_is_enable"` + GzipCompressLevel int `json:"gzip_compress_level"` + UsageData RosUsageData `json:"UsageData"` + ReadyDelete bool `json:"ready_delete"` +} + +// 获取监控数据请求(桶和实例通用) +type GetRosMonitorDataRequest struct { + StartDate int `json:"start_date"` // 开始时间(timestamp) + EndDate int `json:"end_date"` // 结束时间(timestamp) +} + +// 获取监控数据响应(桶和实例通用) +type GetRosMonitorDataResponse struct { + Code int `json:"code"` + Data RosMonitorData `json:"data"` +} + +// RosMonitorData 对象存储监控数据(桶和实例通用) +type RosMonitorData struct { + Columns []string `json:"Columns"` + Values [][]any `json:"Values"` +} diff --git a/apis/ssl/certificate.go b/apis/ssl/certificate.go new file mode 100644 index 0000000..696d5a1 --- /dev/null +++ b/apis/ssl/certificate.go @@ -0,0 +1,128 @@ +package ssl + +import ( + "fmt" + + "github.com/XingfenD/rainyun_api_go_sdk/apis/common" + "github.com/XingfenD/rainyun_api_go_sdk/constant" +) + +// SSL证书 +type SslCertificate struct { + Cert string `json:"cert"` // 证书 + Key string `json:"key"` // 私钥 +} + +// SSL证书列表记录 +type SslCertificateRecord struct { + ID int `json:"ID"` + UID int `json:"UID"` + Domain string `json:"Domain"` // 域名(逗号分割) + Issuer string `json:"Issuer"` // 品牌 + StartDate int `json:"StartDate"` // 开始时间 + ExpDate int `json:"ExpDate"` // 结束时间 + UploadTime int `json:"UploadTime"` // 上传时间 + NginxErr string `json:"NginxErr"` // ? + BaishanCertID int `json:"BaishanCertID"` // 白山云证书ID + BindDomains any `json:"BindDomains"` // 绑定的域名 +} + +// SSL证书列表数据 +type SslCertificateListData struct { + TotalRecords int `json:"TotalRecords"` + Records []SslCertificateRecord `json:"Records"` +} + +type GetSslCertificateListResponse struct { + Code int `json:"code"` + Data SslCertificateListData `json:"data"` +} + +type GetSslCertificateListRequest struct { + Options common.StandQueryParameters `json:"options"` +} + +// 获取SSL证书列表 +func (s *SslService) GetSSLCertificateList(req *GetSslCertificateListRequest) (*GetSslCertificateListResponse, error) { + path := "/product/sslcenter/" + + var resp GetSslCertificateListResponse + querys, err := common.MarshalQueryParams(req) + if err != nil { + return nil, err + } + err = s.client.Do(constant.HTTPMethod_GET, path, querys, nil, &resp) + return &resp, err +} + +// 上传SSL证书 +// +// cert: 证书 +// +// key: 私钥 +func (s *SslService) UploadSSLCertificate(cert string, key string) (*common.BasicOperationResponse, error) { + path := "/product/sslcenter/" + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_POST, path, nil, SslCertificate{ + Cert: cert, + Key: key, + }, &resp) + return &resp, err +} + +// SSL证书详情数据 +type SslDetailData struct { + Cert string `json:"Cert"` // 证书 + Key string `json:"Key"` // 私钥 + DomainName string `json:"DomainName"` // 域名(逗号分割) + Issuer string `json:"Issuer"` // 品牌 + StartDate int `json:"StartDate"` // 开始时间 + ExpDate int `json:"ExpDate"` // 结束时间 + RemainDays int `json:"RemainDays"` // 剩余天数 +} + +type GetSslDetailResponse struct { + Code int `json:"code"` + Data SslDetailData `json:"data"` +} + +// 获取SSL证书详情 +// +// id: SSL证书ID +func (s *SslService) GetSslDetail(id int) (*GetSslDetailResponse, error) { + path := fmt.Sprintf("/product/sslcenter/%d", id) + + var resp GetSslDetailResponse + err := s.client.Do(constant.HTTPMethod_GET, path, nil, nil, &resp) + return &resp, err +} + +// 替换SSL证书 +// +// id: SSL证书ID +// +// cert: 证书 +// +// key: 私钥 +func (s *SslService) ReplaceSsl(id int, cert, key string) (*common.BasicOperationResponse, error) { + path := fmt.Sprintf("/product/sslcenter/%d", id) + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_PUT, path, nil, SslCertificate{ + Cert: cert, + Key: key, + }, &resp) + return &resp, err +} + +// 删除SSL证书 +// +// id: SSL证书ID +func (s *SslService) DeleteSsl(id int) (*common.BasicOperationResponse, error) { + path := fmt.Sprintf("/product/sslcenter/%d", id) + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_DELETE, path, nil, nil, &resp) + return &resp, err +} diff --git a/apis/ssl/client.go b/apis/ssl/client.go new file mode 100644 index 0000000..42b20eb --- /dev/null +++ b/apis/ssl/client.go @@ -0,0 +1,11 @@ +package ssl + +import "github.com/XingfenD/rainyun_api_go_sdk/apis" + +type SslService struct { + client *apis.RyClient +} + +func NewSslService(c *apis.RyClient) *SslService { + return &SslService{client: c} +} diff --git a/apis/user/client.go b/apis/user/client.go new file mode 100644 index 0000000..86a2785 --- /dev/null +++ b/apis/user/client.go @@ -0,0 +1,11 @@ +package user + +import "github.com/XingfenD/rainyun_api_go_sdk/apis" + +type UserService struct { + client *apis.RyClient +} + +func NewUserService(c *apis.RyClient) *UserService { + return &UserService{client: c} +} diff --git a/apis/user/mfa.go b/apis/user/mfa.go new file mode 100644 index 0000000..06f6d7d --- /dev/null +++ b/apis/user/mfa.go @@ -0,0 +1,40 @@ +package user + +import ( + "github.com/XingfenD/rainyun_api_go_sdk/apis/common" + "github.com/XingfenD/rainyun_api_go_sdk/constant" +) + +// Request2FARequest 请求二次验证 +type Request2FARequest struct { + Type string `json:"type"` +} + +// 请求二次验证 +// +// verificationMethod: 验证方式(sms/totp/email) +func (s *UserService) Request2FA(verificationMethod string) (*common.BasicOperationResponse, error) { + path := "/user/mfa/request" + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_POST, path, nil, Request2FARequest{Type: verificationMethod}, &resp) + + return &resp, err +} + +// Verify2FAResultRequest 验证二次验证结果 +type Verify2FAResultRequest struct { + AuthCode int `json:"auth_code"` +} + +// 验证二次验证结果 +// +// authCode: 验证码 +func (s *UserService) Verify2FAResult(authCode int) (*common.BasicOperationResponse, error) { + path := "/user/mfa/verify" + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_POST, path, nil, Verify2FAResultRequest{AuthCode: authCode}, &resp) + + return &resp, err +} diff --git a/apis/user/reward.go b/apis/user/reward.go new file mode 100644 index 0000000..34c7899 --- /dev/null +++ b/apis/user/reward.go @@ -0,0 +1,186 @@ +package user + +import ( + "github.com/XingfenD/rainyun_api_go_sdk/apis/common" + "github.com/XingfenD/rainyun_api_go_sdk/constant" +) + +type GetUserRewardProductsResponse struct { + Code int `json:"code"` + Data UserRewardProductsData `json:"data"` +} + +// UserRewardProductsData 用户可用积分兑换的产品 +type UserRewardProductsData struct { + Rcs []any `json:"rcs"` + Rvh []any `json:"rvh"` + Rgs []any `json:"rgs"` + Ros []any `json:"ros"` + Rbm []any `json:"rbm"` +} + +// 获取可兑换积分产品列表. +func (s *UserService) GetUserRewardProducts() (*GetUserRewardProductsResponse, error) { + path := "/user/reward/products" + + var resp GetUserRewardProductsResponse + err := s.client.Do(constant.HTTPMethod_GET, path, nil, nil, &resp) + + return &resp, err +} + +// 发布优惠券给下级用户 +type PublishCouponsToLowerLevelUsersRequest struct { + BaseLimit int `json:"base_limit"` // 满减条件(满多少才能用) + Color string `json:"color"` // 颜色: waring: 黄,danger: 红,success: 绿... + Count int `json:"count"` // 发放数量 + ExpDate int `json:"exp_date"` // 过期时间(timestamp) + FriendlyName string `json:"friendly_name"` // 优惠券标题 + Type string `json:"type"` // 类型: discount:折扣, normal: 直减 + UID int `json:"uid"` // 要发放到用户ID(如:114514),为空时则返回兑换码 + UsableDuration string `json:"usable_duration"` // unknown + UsableProduct string `json:"usable_product"` // 可用产品(默认全部),","分隔: renew,create,upgrade + UsableScenes string `json:"usable_scenes"` // 适用操作(默认全部),","分隔: rvh,rcs,rgs,ros,rbm + Value int `json:"value"` // 直减(元)/折扣(折), 折扣时:1~9:一~九折;11~99:一一~九九折 +} + +// 发布优惠券给下级用户 +func (s *UserService) PublishCouponsToLowerLevelUsers(req *PublishCouponsToLowerLevelUsersRequest) (*common.BasicOperationResponse, error) { + path := "/user/vip/coupon" + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_POST, path, nil, req, &resp) + + return &resp, err +} + +// 发送优惠券到积分商城 +type PostCouponsToPointsMallRequest struct { + AvailableDays int `json:"available_days"` // 可用天数 + BaseLimit int `json:"base_limit"` // 满减条件(满多少才能用) + BuyLimit int `json:"buy_limit"` // 领取次数限制 + Color string `json:"color"` // 颜色: waring: 黄, danger: 红, success: 绿, info: 蓝 + Count int `json:"count"` // 发放数量 + EndDate int `json:"end_date"` // 截止日期 + FirstSend bool `json:"first_send"` // 绑定微信后立即自动领取(设置后不可手动领取并且不会显示) + FriendlyName string `json:"friendly_name"` // 优惠券名称 + Name string `json:"name"` // 标识名称 + Order int `json:"order"` // 排序,越大越靠前 + Points int `json:"points"` // 领取积分 + Type string `json:"type"` // 类型: discount:折扣, normal: 直减 + UsableDuration string `json:"usable_duration"` // unknown + UsableProduct string `json:"usable_product"` // 可用产品(默认全部),","分隔: renew,create,upgrade + UsableScenes string `json:"usable_scenes"` // 适用操作(默认全部),","分隔: rvh,rcs,rgs,ros,rbm + Value int `json:"value"` // 直减(元)/折扣(折), 折扣时:1~9:一~九折;11~99:一一~九九折 +} + +// 发布优惠券到积分商城(供下级领取) +func (s *UserService) PostCouponsToPointsMall(req *PostCouponsToPointsMallRequest) (*common.BasicOperationResponse, error) { + path := "/user/vip/coupon" + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_POST, path, nil, req, &resp) + + return &resp, err +} + +type GetPointsMallItemsResponse struct { + Code int `json:"code"` + Data []PointsMallItem `json:"data"` +} + +// PointsMallItem 积分商城物品 +type PointsMallItem struct { + ID int `json:"id"` + Name string `json:"name"` + Points int `json:"points"` + Type string `json:"type"` + AvailableStock int `json:"available_stock"` + FriendlyName string `json:"friendly_name"` + ItemData PointsMallItemData `json:"item_data"` + BuyLimit int `json:"buy_limit"` + SenderID int `json:"sender_id"` + FirstSend bool `json:"first_send"` + ByInvite bool `json:"by_invite"` + Color string `json:"color"` + Order int `json:"order"` + PublicTime int `json:"public_time"` + EndDate int `json:"end_date"` + AutoRefresh int `json:"auto_refresh"` + RefreshLimit int `json:"refresh_limit"` + MoneyRequired int `json:"money_required"` +} + +// PointsMallItemData 积分商城物品数据 +type PointsMallItemData struct { + Color string `json:"color,omitempty"` + FriendlyName string `json:"friendly_name,omitempty"` + UsableScenes string `json:"usable_scenes,omitempty"` + AvailableDays int `json:"available_days,omitempty"` + UsableProduct string `json:"usable_product,omitempty"` + BaseLimit int `json:"base_limit,omitempty"` + PublicPoint int `json:"public_point,omitempty"` + Type string `json:"type,omitempty"` + UsableDuration string `json:"usable_duration,omitempty"` + UsablePlanID int `json:"usable_plan_id,omitempty"` + Value any `json:"value,omitempty"` + ProductType string `json:"product_type,omitempty"` + ProductSubtype string `json:"product_subtype,omitempty"` + DurationSeconds int `json:"duration_seconds,omitempty"` + ProductConfig PointsMallProductConfig `json:"product_config,omitempty"` + Desc string `json:"desc,omitempty"` + ImgURL string `json:"img_url,omitempty"` + DescURL string `json:"desc_url,omitempty"` +} + +// PointsMallProductConfig 积分商城物品的产品配置 +type PointsMallProductConfig struct { + OsID int `json:"os_id"` + PlanID int `json:"plan_id"` + Subtype string `json:"subtype"` + Duration int `json:"duration"` + PayMode string `json:"pay_mode"` + PanelUser string `json:"panel_user"` + EggTypeID int `json:"egg_type_id"` + WithCoupon int `json:"with_coupon"` + CPULimitMode bool `json:"cpu_limit_mode"` + Config PointsMallItemConfig `json:"config"` +} + +// PointsMallItemConfig 积分商城物品配置 +type PointsMallItemConfig struct { + CPU int `json:"cpu"` + Backup int `json:"backup"` + Memory int `json:"memory"` + NetIn int `json:"net_in"` + NetOut int `json:"net_out"` + Database int `json:"database"` + BaseDisk int `json:"base_disk"` + DataDisk int `json:"data_disk"` + Allocation int `json:"allocation"` +} + +// 获取积分商城商品列表 +func (s *UserService) GetPointsMallItems() (*GetPointsMallItemsResponse, error) { + path := "/user/reward/items" + + var resp GetPointsMallItemsResponse + err := s.client.Do(constant.HTTPMethod_GET, path, nil, nil, &resp) + + return &resp, err +} + +// 兑换积分物品 +type RedeemPointsForItemRequest struct { + ItemID int `json:"item_id"` +} + +// 兑换积分物品 +func (s *UserService) RedeemPointsForItem(id int) (*common.BasicOperationResponse, error) { + path := "/user/reward/items" + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_POST, path, nil, RedeemPointsForItemRequest{ItemID: id}, &resp) + + return &resp, err +} diff --git a/apis/user/user.go b/apis/user/user.go new file mode 100644 index 0000000..0e43e5e --- /dev/null +++ b/apis/user/user.go @@ -0,0 +1,123 @@ +package user + +import ( + "github.com/XingfenD/rainyun_api_go_sdk/apis/common" + "github.com/XingfenD/rainyun_api_go_sdk/constant" +) + +type GetUserInfoResponse struct { + Code int `json:"code"` + Data UserInfo `json:"data"` +} + +// UserInfo 用户信息 +type UserInfo struct { + ID int `json:"ID"` + Name string `json:"Name"` + Email string `json:"Email"` + Phone string `json:"Phone"` + Money float64 `json:"Money"` + RegisterTime int `json:"RegisterTime"` + QQOpenID string `json:"QQOpenID"` + QQ any `json:"QQ"` + WechatOpenID string `json:"WechatOpenID"` + CardCode any `json:"CardCode"` + IconURL string `json:"IconUrl"` + Points int `json:"Points"` + MoneyFromPoint int `json:"MoneyFromPoint"` + Inviter int `json:"Inviter"` + APIKey string `json:"APIKey"` + LastIP string `json:"LastIP"` + BanReason string `json:"BanReason"` + UnsubscribeCount int `json:"UnsubscribeCount"` + AlipayAccount string `json:"AlipayAccount"` + AlipayName string `json:"AlipayName"` + LastLogin string `json:"LastLogin"` + LastLoginArea string `json:"LastLoginArea"` + LoginCount int `json:"LoginCount"` + DLWallet int `json:"DLWallet"` + DLLevel int `json:"DLLevel"` + AdminGroup string `json:"AdminGroup"` + TOTPSecret string `json:"TOTPSecret"` + IsLoginEnableTFA bool `json:"IsLoginEnableTFA"` + IsAllowPointUse int `json:"IsAllowPointUse"` + ShareCode string `json:"ShareCode"` + VipLevel int `json:"VipLevel"` + IsAgent bool `json:"IsAgent"` + Valid bool `json:"Valid"` + Source string `json:"Source"` + ConsumeMonthly int `json:"ConsumeMonthly"` + ConsumeAll int `json:"ConsumeAll"` + ConsumeQuarter int `json:"ConsumeQuarter"` + ResellDaily int `json:"ResellDaily"` + ResellMonthly int `json:"ResellMonthly"` + ResellBeforeMonth float64 `json:"ResellBeforeMonth"` + ResellQuarter float64 `json:"ResellQuarter"` + ResellAll float64 `json:"ResellAll"` + StockDaily int `json:"StockDaily"` + StockMonthly int `json:"StockMonthly"` + StockQuarter float64 `json:"StockQuarter"` + StockAll float64 `json:"StockAll"` + SecondStockQuarter int `json:"SecondStockQuarter"` + SecondStockAll int `json:"SecondStockAll"` + SubUserMonthly int `json:"SubUserMonthly"` + SubUserAll int `json:"SubUserAll"` + ResellPointsMonthly int `json:"ResellPointsMonthly"` + ResellPointsAll int `json:"ResellPointsAll"` + Vip UserVipInfo `json:"VIP"` + Certify int `json:"Certify"` + LockPoints int `json:"LockPoints"` + CertifyStatus string `json:"CertifyStatus"` + CertifyType string `json:"CertifyType"` + CertifyAuditNote string `json:"CertifyAuditNote"` +} + +// UserVipInfo 用户 VIP 等级信息 +type UserVipInfo struct { + Title string `json:"Title"` + SaleRequire int `json:"SaleRequire"` + ResellRequire int `json:"ResellRequire"` + CertifyRequired bool `json:"CertifyRequired"` + SaleProfit float64 `json:"SaleProfit"` + ResellProfit float64 `json:"ResellProfit"` + SecondResellProfit float64 `json:"SecondResellProfit"` + CanSendCoupons bool `json:"CanSendCoupons"` + CanCustomCode bool `json:"CanCustomCode"` + CanSendMsg bool `json:"CanSendMsg"` + CanTryUsual bool `json:"CanTryUsual"` + FreeDomainCount int `json:"FreeDomainCount"` + FreeSSLCount int `json:"FreeSSLCount"` + CanBeAgent bool `json:"CanBeAgent"` + AgentTitle string `json:"AgentTitle"` + StockRequire int `json:"StockRequire"` + SecondStockRequire int `json:"SecondStockRequire"` + StockDiscount float64 `json:"StockDiscount"` + SecondStockProfit float64 `json:"SecondStockProfit"` +} + +// 获取用户信息. +func (s *UserService) GetUserInfo() (*GetUserInfoResponse, error) { + path := "/user/" + + var resp GetUserInfoResponse + err := s.client.Do(constant.HTTPMethod_GET, path, nil, nil, &resp) + + return &resp, err +} + +// RefreshApikeyRequest 刷新 API 密钥请求 +type RefreshApikeyRequest struct { + Option string `json:"option"` +} + +// 刷新 api 密钥. +// +// ⚠️不要轻易使用此方法 +func (s *UserService) RefreshApikey() (*common.BasicOperationResponse, error) { + path := "/user/" + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_PATCH, path, nil, RefreshApikeyRequest{Option: "apikey"}, &resp) + + return &resp, err +} diff --git a/apis/workorder/client.go b/apis/workorder/client.go new file mode 100644 index 0000000..fb349c7 --- /dev/null +++ b/apis/workorder/client.go @@ -0,0 +1,11 @@ +package workorder + +import "github.com/XingfenD/rainyun_api_go_sdk/apis" + +type WorkorderService struct { + client *apis.RyClient +} + +func NewWorkorderService(c *apis.RyClient) *WorkorderService { + return &WorkorderService{client: c} +} diff --git a/apis/workorder/model.go b/apis/workorder/model.go new file mode 100644 index 0000000..8c3be08 --- /dev/null +++ b/apis/workorder/model.go @@ -0,0 +1,152 @@ +package workorder + +import "github.com/XingfenD/rainyun_api_go_sdk/apis/common" + +// 获取工单列表请求 +type GetWorkOrderListRequest struct { + Options common.StandQueryParameters `json:"options"` +} + +// 获取工单列表响应 +type GetWorkOrderListResponse struct { + Code int `json:"code"` + Data WorkorderListData `json:"data"` +} + +// 工单列表数据 +type WorkorderListData struct { + TotalRecords int `json:"TotalRecords"` + Records []WorkorderRecord `json:"Records"` +} + +// 工单 +type WorkorderRecord struct { + ID int `json:"ID"` // 工单ID + UID int `json:"UID"` // 用户ID + ExtUserInfo string `json:"ExtUserInfo"` + UserName string `json:"UserName"` // 用户名 + UserEmail string `json:"UserEmail"` + UserVip string `json:"UserVip"` // 用户vip等级 + UserIcon string `json:"UserIcon"` // 用户头像 + Title string `json:"Title"` // 工单标题 + Type string `json:"Type"` // 工单类型 + RelatedProductType string `json:"RelatedProductType"` // 关联产品类型 + RelatedProductID int `json:"RelatedProductID"` // 关联产品id + IsUrgent int `json:"IsUrgent"` // 是否为紧急工单 + Status string `json:"Status"` // 状态(finished/answered/waiting) + Time int `json:"Time"` // 工单创建时间 + LastTime int `json:"LastTime"` + WaitBeginTime int `json:"WaitBeginTime"` + AssistID int `json:"AssistID"` // 客服id + AuthStatus string `json:"AuthStatus"` + AuthTime int `json:"AuthTime"` + AuthID int `json:"AuthID"` +} + +// 工单回复 +type WorkorderDiscuss struct { + ID int `json:"ID"` + IsAssist bool `json:"IsAssist"` + UID int `json:"UID"` + UserName string `json:"UserName"` + UserEmail string `json:"UserEmail"` + UserVip string `json:"UserVip"` + UserIcon string `json:"UserIcon"` + Content string `json:"Content"` + Time int `json:"Time"` + WaitTime int `json:"WaitTime"` + LastEditedTime int `json:"LastEditedTime"` + IsScored bool `json:"IsScored"` +} + +// 工单详情数据 +type WorkorderDetailData struct { + WorkorderRecord + Content string `json:"Content"` + Discuss []WorkorderDiscuss `json:"Discuss"` +} + +// 获取工单详情响应 +type GetWorkOrderDetailResponse struct { + Code int `json:"code"` + Data WorkorderDetailData `json:"data"` +} + +// 创建工单 +type CreateWorkerorderRequest struct { + Content string `json:"content"` + IsAuthed bool `json:"is_authed"` // 是否需要授权(可选) + IsUrgent int `json:"is_urgent"` // 是否为紧急工单 + RelatedProductID int `json:"related_product_id"` // 关联产品类型(可选) + RelatedProductType string `json:"related_product_type"` // 关联产品id(可选) + Title string `json:"title"` + Type string `json:"type"` // 工单类型 +} + +// 创建工单数据 +type CreateWorkorderData struct { + WorkorderRecord + Content string `json:"Content"` +} + +// 创建工单响应 +type CreateWorkerorderResponse struct { + Code int `json:"code"` + Data CreateWorkorderData `json:"data"` +} + +// 产品授权请求 +type ProductAuthRequest struct { + ProductID int `json:"product_id"` // 产品ID + ProductType string `json:"product_type"` // 产品类型(rvh/rcs/rgs/rbm/ros) +} + +// 回复工单请求 +type ReplyWorkerorderRequest struct { + Content string `json:"content"` // 回复内容 +} + +// 工单打分 +type ScoreWorkerorderRequest struct { + Score int `json:"score"` // 分数(1-5) + Reason string `json:"reason"` // (可选) + IsSolved bool `json:"is_solved"` // 是否解决(可选) + DiscussID int `json:"discuss_id"` // 回复ID(可选) + Aid int `json:"aid"` // 客服id(可选) +} + +// 工单打分详情数据 +type ScoreWorkorderData struct { + UID int `json:"uid"` + Aid int `json:"aid"` + OrderID int `json:"order_id"` + DiscussID int `json:"discuss_id"` + Score int `json:"score"` + Reason string `json:"reason"` + IsSolved bool `json:"is_solved"` + DiscussTime int `json:"DiscussTime"` + ScoreTime int `json:"score_time"` +} + +// 获取工单打分响应 +type GetScoreWorkorderResponse struct { + Code int `json:"code"` + Data ScoreWorkorderData `json:"data"` +} + +// 工单状态数据 +type WorkorderStatusData struct { + LastTime int `json:"LastTime"` + Status string `json:"Status"` +} + +// 获取工单状态响应 +type GetWorkorderStatusResponse struct { + Code int `json:"code"` + Data WorkorderStatusData `json:"data"` +} + +// 设置工单状态请求 +type SetWorkorderStatusRequest struct { + Status string `json:"status"` +} diff --git a/apis/workorder/score.go b/apis/workorder/score.go new file mode 100644 index 0000000..f6b57d2 --- /dev/null +++ b/apis/workorder/score.go @@ -0,0 +1,43 @@ +package workorder + +import ( + "fmt" + + "github.com/XingfenD/rainyun_api_go_sdk/apis/common" + "github.com/XingfenD/rainyun_api_go_sdk/constant" +) + +// 工单打分 +// +// id: 工单ID +func (s *WorkorderService) ScoreWorkorder(id int, req *ScoreWorkerorderRequest) (*common.BasicOperationResponse, error) { + path := fmt.Sprintf("/workorder/%d/score", id) + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_POST, path, nil, req, &resp) + return &resp, err +} + +// 编辑工单打分 +// +// id: 工单ID +func (s *WorkorderService) EditScoreWorkorder(id int, req *ScoreWorkerorderRequest) (*common.BasicOperationResponse, error) { + path := fmt.Sprintf("/workorder/%d/score", id) + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_PATCH, path, nil, req, &resp) + return &resp, err +} + +// 获取工单打分 +// +// id: 工单ID +// +// discussID: 客服回复ID +func (s *WorkorderService) GetScoreWorkorder(id int, discussID int) (*GetScoreWorkorderResponse, error) { + path := fmt.Sprintf("/workorder/%d/score/%d", id, discussID) + + var resp GetScoreWorkorderResponse + err := s.client.Do(constant.HTTPMethod_GET, path, nil, nil, &resp) + return &resp, err +} diff --git a/apis/workorder/workorder.go b/apis/workorder/workorder.go new file mode 100644 index 0000000..50f8167 --- /dev/null +++ b/apis/workorder/workorder.go @@ -0,0 +1,110 @@ +package workorder + +import ( + "fmt" + + "github.com/XingfenD/rainyun_api_go_sdk/apis/common" + "github.com/XingfenD/rainyun_api_go_sdk/constant" +) + +// 获取工单列表 +// +// req.Options 为分页查询参数, 可用 common.StandQueryParameters 构造 +func (s *WorkorderService) GetWorkOrderList(req *GetWorkOrderListRequest) (*GetWorkOrderListResponse, error) { + path := "/workorder/" + + var resp GetWorkOrderListResponse + querys, err := common.MarshalQueryParams(req) + if err != nil { + return nil, err + } + err = s.client.Do(constant.HTTPMethod_GET, path, querys, nil, &resp) + return &resp, err +} + +// 获取工单详情 +// +// id: 工单ID +func (s *WorkorderService) GetWorkOrderDetail(id int) (*GetWorkOrderDetailResponse, error) { + path := fmt.Sprintf("/workorder/%d", id) + + var resp GetWorkOrderDetailResponse + err := s.client.Do(constant.HTTPMethod_GET, path, nil, nil, &resp) + return &resp, err +} + +// 创建工单 +func (s *WorkorderService) CreateWorkOrder(req *CreateWorkerorderRequest) (*CreateWorkerorderResponse, error) { + path := "/workorder/" + + var resp CreateWorkerorderResponse + err := s.client.Do(constant.HTTPMethod_POST, path, nil, req, &resp) + return &resp, err +} + +// 产品授权 +// +// id:工单ID +// +// productID:产品ID +// +// productType:产品类型(rvh/rcs/rgs/rbm/ros) +func (s *WorkorderService) ProductAuth(id int, productID int, productType string) (*common.BasicOperationResponse, error) { + path := fmt.Sprintf("/workorder/%d/auth", id) + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_POST, path, nil, ProductAuthRequest{ProductID: productID, ProductType: productType}, &resp) + return &resp, err +} + +// 回复工单 +// +// id: 工单ID +// +// content: 回复内容 +func (s *WorkorderService) ReplyWorkorder(id int, content string) (*common.BasicOperationResponse, error) { + path := fmt.Sprintf("/workorder/%d/reply_order", id) + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_POST, path, nil, ReplyWorkerorderRequest{Content: content}, &resp) + return &resp, err +} + +// 编辑回复工单 +// +// id: 工单ID +// +// replyID: 回复ID +// +// content: 编辑后的内容 +func (s *WorkorderService) EditWorkorderReply(id int, replyID int, content string) (*common.BasicOperationResponse, error) { + path := fmt.Sprintf("/workorder/%d/reply_order/%d", id, replyID) + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_PATCH, path, nil, ReplyWorkerorderRequest{Content: content}, &resp) + return &resp, err +} + +// 获取工单状态 +// +// id: 工单ID +func (s *WorkorderService) GetWorkorderStatus(id int) (*GetWorkorderStatusResponse, error) { + path := fmt.Sprintf("/workorder/%d/status", id) + + var resp GetWorkorderStatusResponse + err := s.client.Do(constant.HTTPMethod_GET, path, nil, nil, &resp) + return &resp, err +} + +// 设置工单状态 +// +// id: 工单ID +// +// status: 目标状态 +func (s *WorkorderService) SetWorkorderStatus(id int, status string) (*common.BasicOperationResponse, error) { + path := fmt.Sprintf("/workorder/%d/status", id) + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_PATCH, path, nil, SetWorkorderStatusRequest{Status: status}, &resp) + return &resp, err +} diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index ff0b6f2..28a5f09 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -6,6 +6,18 @@ All notable changes to this template should be documented in this file. The format loosely follows Keep a Changelog and can be adapted to the team's habits. 本文档参考了 Keep a Changelog 的思路,也可以根据团队习惯调整。 +## [0.2.0] - 2026-08-05 + +### Added / 新增 + +- 迁移剩余全部模块:domain(24)、product(8)、rbm(10)、rca(21)、rgs(38)、ros(19)、ssl(5)、user(10)、workorder(11),并补全 public 剩余 5 个接口。 +- 全部响应结构体嵌套拆分命名复用;rgs 复用 rcs 的请求/响应类型。 +- `sdk.New` 注册全部 11 个服务。 + +### Fixed / 修复 + +- 修正源 SDK 中的路径错误(`{id}` 占位符、缺少 `/`、`/product/rcs/` 误写为 rgs 路径等)与参数传递错误(`resp` vs `&resp`、漏传 body)。 + ## [0.1.0] - 2026-08-05 ### Added / 新增 diff --git a/sdk/sdk.go b/sdk/sdk.go index b499c04..06998ed 100644 --- a/sdk/sdk.go +++ b/sdk/sdk.go @@ -2,19 +2,46 @@ package sdk import ( "github.com/XingfenD/rainyun_api_go_sdk/apis" + "github.com/XingfenD/rainyun_api_go_sdk/apis/domain" + "github.com/XingfenD/rainyun_api_go_sdk/apis/product" "github.com/XingfenD/rainyun_api_go_sdk/apis/public" + "github.com/XingfenD/rainyun_api_go_sdk/apis/rbm" + "github.com/XingfenD/rainyun_api_go_sdk/apis/rca" "github.com/XingfenD/rainyun_api_go_sdk/apis/rcs" + "github.com/XingfenD/rainyun_api_go_sdk/apis/rgs" + "github.com/XingfenD/rainyun_api_go_sdk/apis/ros" + "github.com/XingfenD/rainyun_api_go_sdk/apis/ssl" + "github.com/XingfenD/rainyun_api_go_sdk/apis/user" + "github.com/XingfenD/rainyun_api_go_sdk/apis/workorder" ) type RainyunSDK struct { public.PublicService + domain.DomainService + product.ProductService + rbm.RbmService + rca.RcaService rcs.RcsService + rgs.RgsService + ros.RosService + ssl.SslService + user.UserService + workorder.WorkorderService } func New(apiKey string) *RainyunSDK { c := apis.NewRyClient(apiKey) return &RainyunSDK{ - PublicService: *public.NewPublicService(c), - RcsService: *rcs.NewRcsService(c), + PublicService: *public.NewPublicService(c), + DomainService: *domain.NewDomainService(c), + ProductService: *product.NewProductService(c), + RbmService: *rbm.NewRbmService(c), + RcaService: *rca.NewRcaService(c), + RcsService: *rcs.NewRcsService(c), + RgsService: *rgs.NewRgsService(c), + RosService: *ros.NewRosService(c), + SslService: *ssl.NewSslService(c), + UserService: *user.NewUserService(c), + WorkorderService: *workorder.NewWorkorderService(c), } }