diff --git a/handler/tool.go b/handler/tool.go index 9ec9f2b..811170c 100644 --- a/handler/tool.go +++ b/handler/tool.go @@ -5,6 +5,7 @@ import ( "StuAcaWorksAI/proto" "StuAcaWorksAI/service" "StuAcaWorksAI/worker" + "encoding/json" "fmt" "github.com/gin-gonic/gin" "io" @@ -54,6 +55,7 @@ func SetUpToolGroup(router *gin.Engine) { //发送邮件 toolGroup.POST("/send_mail", SendMailTool) toolGroup.POST("/dashboard", DashBoardStatistics) + toolGroup.POST("/spark_ppt_theme_list", GetSparkPPTThemeList) } func SetDeviceStatusV2(c *gin.Context) { @@ -413,3 +415,39 @@ func DashBoardStatistics(c *gin.Context) { c.JSON(http.StatusOK, gin.H{"code": proto.SuccessCode, "message": "success", "data": resp}) return } + +func GetSparkPPTThemeList(c *gin.Context) { + var req proto.GetSparkPPTThemeReq + if err := c.ShouldBind(&req); err == nil { + if req.Style == "" || req.Color == "" || req.Industry == "" { + c.JSON(http.StatusOK, gin.H{"error": "parameter error,request parameter is null", "code": proto.ParameterError, "message": "failed"}) + return + } + var modelParam proto.ModelParam + //获取模型 + models, funcs, mferr := service.FindFuncModelListByFunctionV2(req.Function) + if mferr != nil { + c.JSON(http.StatusOK, gin.H{"error": "function not exist", "code": proto.ParameterError, "message": "failed"}) + return + } + if len(funcs) == 0 || len(models) == 0 { + c.JSON(http.StatusOK, gin.H{"error": "function or model not exist", "code": proto.ParameterError, "message": "failed"}) + return + } + model := models[0] + + err = json.Unmarshal([]byte(model.Parameter), &modelParam) + if err != nil { + c.JSON(http.StatusOK, gin.H{"error": "model parameter decode error", "code": proto.ParameterError, "message": "failed"}) + return + } + modelParam.Url = model.Url + modelParam.System = funcs[0].Info //系统功能 + //获取主题列表 + themeList, err := service.SparkPPTThemeList(&modelParam, req) + + } else { + c.JSON(http.StatusOK, gin.H{"error": "parameter error", "code": proto.ParameterError, "message": "failed"}) + return + } +} diff --git a/proto/spark.go b/proto/spark.go new file mode 100644 index 0000000..40d76cf --- /dev/null +++ b/proto/spark.go @@ -0,0 +1,157 @@ +package proto + +type PPTThemeRequest struct { + Style string `json:"style"` + Color string `json:"color"` + Industry string `json:"industry"` + PageNum int `json:"pageNum"` + PageSize int `json:"pageSize"` +} + +// Response 定义响应结构体 +type PPTThemeResponse struct { + Flag bool `json:"flag"` + Code int `json:"code"` + Desc string `json:"desc"` + Count interface{} `json:"count"` + Data PPTThemeData `json:"data"` +} + +// Data 定义数据结构体 +type PPTThemeData struct { + Total int `json:"total"` + Records []PPTThemeRecord `json:"records"` + PageNum int `json:"pageNum"` +} + +// Record 定义记录结构体 +type PPTThemeRecord struct { + TemplateIndexId string `json:"templateIndexId"` + PageCount int `json:"pageCount"` + Type string `json:"type"` + Color string `json:"color"` + Industry string `json:"industry"` + Style string `json:"style"` + DetailImage PPTThemeDetailImage `json:"detailImage"` +} + +// DetailImage 定义详细图片结构体 +type PPTThemeDetailImage struct { + TitleCoverImageLarge string `json:"titleCoverImageLarge"` + TitleCoverImage string `json:"titleCoverImage"` + CatalogueCoverImage string `json:"catalogueCoverImage"` + ChapterCoverImage string `json:"chapterCoverImage"` + ContentCoverImage string `json:"contentCoverImage"` + EndCoverImage string `json:"endCoverImage"` +} + +type GetSparkPPTThemeReq struct { + Function string `json:"function" form:"function"` // 功能 + Style string `json:"style" form:"style"` // 风格 + Color string `json:"color" form:"color"` // 颜色 + Industry string `json:"industry" form:"industry"` // 行业 + PageNum int `json:"pageNum" form:"pageNum"` // 页码 + PageSize int `json:"pageSize" form:"pageSize"` // 每页数量 +} + +type FileParamContext struct { + UserID int `json:"user_id"` //用户id + SessionID int `json:"session_id"` //会话id + FunctionID int `json:"function_id"` //功能id + ModelID int `json:"model_id"` //模型id + Channel string `json:"channel"` //消息队列 + FileID int `json:"file_id"` //文件id + FileName string `json:"file_name"` //文件名 + FileUrl string `json:"file_url"` //文件url +} + +type SparkCreateOutlineByDocRequest struct { + Query string `json:"query" form:"query" binding:"required,min=1,max=8000,nefield= "` // 查询内容 + FileUrl string `json:"fileUrl" form:"fileUrl"` + FileName string `json:"fileName" form:"fileName"` + BusinessId string `json:"businessId,omitempty" form:"businessId,omitempty"` + Language string `json:"language,omitempty" form:"language,omitempty" default:"cn"` + Search bool `json:"search,omitempty" form:"search,omitempty" default:"false"` +} + +// 创建大纲响应内容 +type SparkCreateOutlineResponse struct { + Flag bool `json:"flag"` + Code int `json:"code"` + Desc string `json:"desc"` + Count int `json:"count"` + Data SparkCreateOutlineResponseData `json:"data"` +} + +// Data 定义响应中 data 字段的结构体 +type SparkCreateOutlineResponseData struct { + Sid string `json:"sid"` + Outline SparkCreateOutlineResponseOutline `json:"outline"` +} + +// Outline 定义大纲数据的结构体 +type SparkCreateOutlineResponseOutline struct { + Title string `json:"title"` + SubTitle string `json:"subTitle"` + Chapters []SparkCreateOutlineResponseChapter `json:"chapters"` +} + +// Chapter 定义章节数据的结构体 +type SparkCreateOutlineResponseChapter struct { + ChapterTitle string `json:"chapterTitle"` + ChapterContents []SparkCreateOutlineResponseChapterContent `json:"chapterContents"` +} + +type SparkCreateOutlineResponseChapterContent struct { + ChapterTitle string `json:"chapterTitle"` +} + +type SparkCreateOutlineRequest struct { + Function string `json:"function" form:"function"` // 功能 + Query string `json:"query" form:"query"` // 查询内容 + FileUrl string `json:"fileUrl" form:"fileUrl"` // 文件url + FileName string `json:"fileName" form:"fileName"` // 文件名 +} + +type SparkCreatePPTByOutlineUserRequest struct { + Function string `json:"function" form:"function"` // 功能 + Sid string `json:"sid" form:"sid"` // 会话id,spark提供 + Query string `json:"query" form:"query"` // 查询内容 + FileUrl string `json:"fileUrl" form:"fileUrl"` // 文件url + FileName string `json:"fileName" form:"fileName"` // 文件名 + Outline SparkCreateOutlineResponseOutline `json:"outline" form:"outline"` // 大纲 +} + +type SparkCreatePptByOutlineRequest struct { + Query string `json:"query" form:"query" binding:"required,min=1,max=8000,nefield= "` + OutlineSid string `json:"outlineSid" form:"outlineSid"` + Outline SparkCreateOutlineResponseOutline `json:"outline" form:"outline" binding:"required"` + TemplateId string `json:"templateId" form:"templateId"` + BusinessId string `json:"businessId" form:"businessId"` + Author string `json:"author" form:"author" default:"讯飞智文"` + IsCardNote bool `json:"isCardNote" form:"isCardNote" default:"false"` + Search bool `json:"search" form:"search" default:"false"` + Language string `json:"language" form:"language" default:"cn"` + FileUrl string `json:"fileUrl" form:"fileUrl"` + FileName string `json:"fileName" form:"fileName" binding:"required_with=FileUrl"` + IsFigure bool `json:"isFigure" form:"isFigure" default:"false"` + AiImage string `json:"aiImage" form:"aiImage" binding:"omitempty,oneof=normal advanced"` +} + +type SparkCreatePPTByOutlineResponse struct { + Flag bool `json:"flag"` + Code int `json:"code"` + Desc string `json:"desc"` + Count interface{} `json:"count"` + Data SparkCreatePPTByOutlineData `json:"data"` +} + +type SparkCreatePPTByOutlineData struct { + PptStatus string `json:"pptStatus"` + AiImageStatus string `json:"aiImageStatus"` + CardNoteStatus string `json:"cardNoteStatus"` + PptUrl string `json:"pptUrl"` + ErrMsg interface{} `json:"errMsg"` + TotalPages int `json:"totalPages"` + DonePages int `json:"donePages"` +} diff --git a/service/doubao.go b/service/doubao.go index 1f04a34..d14871e 100644 --- a/service/doubao.go +++ b/service/doubao.go @@ -125,13 +125,13 @@ func DouBaoV2(modelParam proto.ModelParam, imCtx *proto.IMParamContext) { fmt.Printf("doubao Stream chat error: %v\n", err) return } - aiStream_id, err3 := CreateAIStreamMsg(imCtx.UserID, imCtx.ModelID, imCtx.SessionID, recv, modelParam.Model) + aistreamId, err3 := CreateAIStreamMsg(imCtx.UserID, imCtx.ModelID, imCtx.SessionID, recv, modelParam.Model) if err3 != nil { log.Println("create ai stream message error:", err3) } doubaoToGeneralMassageAndSendMsgQueue(&recv, imCtx.Channel, imCtx.SessionID, imCtx.UserID) if recv.Choices == nil { - log.Println("doubao stream recv choices is nil:", recv, "\t aiStream_id:", aiStream_id) + log.Println("doubao stream recv choices is nil:", recv, "\t aiStream_id:", aistreamId) continue } choices := recv.Choices[0] diff --git a/service/spark/spark-auth.go b/service/spark/spark-auth.go new file mode 100644 index 0000000..cdd6d62 --- /dev/null +++ b/service/spark/spark-auth.go @@ -0,0 +1,46 @@ +package spark + +import ( + "crypto/hmac" + "crypto/md5" + "crypto/sha1" + "encoding/base64" + "strconv" +) + +// spark 接口签名计算 +// MD5_TABLE 定义 MD5 转换表 +var MD5_TABLE = []rune{ + '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', +} + +// ApiAuthAlgorithm 定义 API 认证算法结构体 +type ApiAuthAlgorithm struct{} + +// GetSignature 获取签名 +func (a *ApiAuthAlgorithm) GetSignature(appId, secret string, ts int64) string { + auth := a.md5(appId + strconv.FormatInt(ts, 10)) + if auth == "" { + return "" + } + return a.hmacSHA1Encrypt(auth, secret) +} + +// hmacSHA1Encrypt sha1 加密 +func (a *ApiAuthAlgorithm) hmacSHA1Encrypt(encryptText, encryptKey string) string { + h := hmac.New(sha1.New, []byte(encryptKey)) + h.Write([]byte(encryptText)) + return base64.StdEncoding.EncodeToString(h.Sum(nil)) +} + +// md5 MD5 加密 +func (a *ApiAuthAlgorithm) md5(cipherText string) string { + hash := md5.Sum([]byte(cipherText)) + result := make([]rune, 32) + for i, v := range hash { + result[i*2] = MD5_TABLE[v>>4&0xf] + result[i*2+1] = MD5_TABLE[v&0xf] + } + return string(result) +} diff --git a/service/spark/spark-file.go b/service/spark/spark-file.go new file mode 100644 index 0000000..bc8d2eb --- /dev/null +++ b/service/spark/spark-file.go @@ -0,0 +1 @@ +package spark diff --git a/service/spark/spark-image.go b/service/spark/spark-image.go new file mode 100644 index 0000000..0883be2 --- /dev/null +++ b/service/spark/spark-image.go @@ -0,0 +1,171 @@ +package spark + +import ( + "crypto/hmac" + "crypto/sha256" + "encoding/base64" + "encoding/json" + "fmt" + "io" + "net/http" + "net/url" + "os" + "strings" + "time" + + "github.com/gorilla/websocket" +) + +var ( + hostUrl = "wss://spark-api.cn-huabei-1.xf-yun.com/v2.1/image" + appid = "XXXXXXXX" + apiKey = "XXXXXXXXXXXXXXXXXXXXXXXX" + apiSecret = "XXXXXXXXXXXXXXXXXXXXXXXX" +) + +func sparkImage() { + + d := websocket.Dialer{ + HandshakeTimeout: 5 * time.Second, + } + //鎻℃墜骞跺缓绔媤ebsocket 杩炴帴 + conn, resp, err := d.Dial(assembleAuthUrl(hostUrl, apiKey, apiSecret), nil) + if err != nil { + panic(readResp(resp) + err.Error()) + return + } else if resp.StatusCode != 101 { + panic(readResp(resp) + err.Error()) + } + + //璇诲彇鍥剧墖 + image, err := os.ReadFile("./1.png") + + messages := []Message{ + {Role: "user", Content: base64.StdEncoding.EncodeToString(image), ContentType: "image"}, // 棣栨潯蹇呴』鏄浘鐗� + {Role: "user", Content: "鍥剧墖鏈夊嚑涓汉", ContentType: "text"}, + {Role: "assistant", Content: "鍥剧墖閲岄潰鏈変竴涓汉", ContentType: "text"}, + {Role: "user", Content: "杩欎釜浜虹┛浠€涔堣。鏈�", ContentType: "text"}, + } + + data := map[string]interface{}{ + "header": map[string]interface{}{ + "app_id": appid, + }, + "parameter": map[string]interface{}{ + "chat": map[string]interface{}{ + "domain": "imagev3", + }, + }, + "payload": map[string]interface{}{ // 鏍规嵁瀹為檯鎯呭喌淇敼杩斿洖鐨勬暟鎹粨鏋勫拰瀛楁鍚� + "message": map[string]interface{}{ // 鏍规嵁瀹為檯鎯呭喌淇敼杩斿洖鐨勬暟鎹粨鏋勫拰瀛楁鍚� + "text": messages, // 鏍规嵁瀹為檯鎯呭喌淇敼杩斿洖鐨勬暟鎹粨鏋勫拰瀛楁鍚� + }, + }, + } + conn.WriteJSON(data) + + var answer = "" + //鑾峰彇杩斿洖鐨勬暟鎹� + for { + _, msg, err := conn.ReadMessage() + if err != nil { + fmt.Println("read message error:", err) + break + } + + var data map[string]interface{} + err1 := json.Unmarshal(msg, &data) + if err1 != nil { + fmt.Println("Error parsing JSON:", err) + return + } + fmt.Println(string(msg)) + //瑙f瀽鏁版嵁 + payload := data["payload"].(map[string]interface{}) + choices := payload["choices"].(map[string]interface{}) + header := data["header"].(map[string]interface{}) + code := header["code"].(float64) + + if code != 0 { + fmt.Println(data["payload"]) + return + } + status := choices["status"].(float64) + fmt.Println(status) + text := choices["text"].([]interface{}) + content := text[0].(map[string]interface{})["content"].(string) + if status != 2 { + answer += content + } else { + fmt.Println("鏀跺埌鏈€缁堢粨鏋�") + answer += content + usage := payload["usage"].(map[string]interface{}) + temp := usage["text"].(map[string]interface{}) + totalTokens := temp["total_tokens"].(float64) + fmt.Println("total_tokens:", totalTokens) + conn.Close() + break + } + + } + //杈撳嚭杩斿洖缁撴灉 + fmt.Println(answer) + + time.Sleep(1 * time.Second) +} + +// 鍒涘缓閴存潈url apikey 鍗� hmac username +func assembleAuthUrl(hosturl string, apiKey, apiSecret string) string { + ul, err := url.Parse(hosturl) + if err != nil { + fmt.Println(err) + } + //绛惧悕鏃堕棿 + date := time.Now().UTC().Format(time.RFC1123) + //date = "Tue, 28 May 2019 09:10:42 MST" + //鍙備笌绛惧悕鐨勫瓧娈� host ,date, request-line + signString := []string{"host: " + ul.Host, "date: " + date, "GET " + ul.Path + " HTTP/1.1"} + //鎷兼帴绛惧悕瀛楃涓� + sgin := strings.Join(signString, "\n") + // fmt.Println(sgin) + //绛惧悕缁撴灉 + sha := HmacWithShaTobase64("hmac-sha256", sgin, apiSecret) + // fmt.Println(sha) + //鏋勫缓璇锋眰鍙傛暟 姝ゆ椂涓嶉渶瑕乽rlencoding + authUrl := fmt.Sprintf("hmac username=\"%s\", algorithm=\"%s\", headers=\"%s\", signature=\"%s\"", apiKey, + "hmac-sha256", "host date request-line", sha) + //灏嗚姹傚弬鏁颁娇鐢╞ase64缂栫爜 + authorization := base64.StdEncoding.EncodeToString([]byte(authUrl)) + + v := url.Values{} + v.Add("host", ul.Host) + v.Add("date", date) + v.Add("authorization", authorization) + //灏嗙紪鐮佸悗鐨勫瓧绗︿覆url encode鍚庢坊鍔犲埌url鍚庨潰 + callurl := hosturl + "?" + v.Encode() + return callurl +} + +func HmacWithShaTobase64(algorithm, data, key string) string { + mac := hmac.New(sha256.New, []byte(key)) + mac.Write([]byte(data)) + encodeData := mac.Sum(nil) + return base64.StdEncoding.EncodeToString(encodeData) +} + +func readResp(resp *http.Response) string { + if resp == nil { + return "" + } + b, err := io.ReadAll(resp.Body) + if err != nil { + panic(err) + } + return fmt.Sprintf("code=%d,body=%s", resp.StatusCode, string(b)) +} + +type Message struct { + Role string `json:"role"` + Content string `json:"content"` + ContentType string `json:"content_type"` +} diff --git a/service/spark/spark-ppt.go b/service/spark/spark-ppt.go new file mode 100644 index 0000000..bcc463a --- /dev/null +++ b/service/spark/spark-ppt.go @@ -0,0 +1,193 @@ +package spark + +import ( + "StuAcaWorksAI/proto" + "StuAcaWorksAI/worker" + "encoding/json" + "log" + "strconv" + "time" +) + +func SparkPPTThemeList(model *proto.ModelParam, req proto.GetSparkPPTThemeReq) (proto.PPTThemeResponse, error) { + url := "https://zwapi.xfyun.cn/api/ppt/v2/template/list" + headers, err := getSparkRequestHeaders(model.APPID, model.APISecret) + if err != nil { + log.Println("Spark PPT Theme Error getting headers:", err) + return proto.PPTThemeResponse{}, err + } + //log.Println("Spark PPT Theme headers:", headers) + + req_ := proto.PPTThemeRequest{ + Style: req.Style, + Color: req.Color, + Industry: req.Industry, + PageNum: 1, + PageSize: 10, + } + + reqStr, err := json.Marshal(req_) + if err != nil { + log.Println("Spark PPT Theme Error encoding request:", err) + return proto.PPTThemeResponse{}, err + } + log.Println("Spark PPT Theme req:", string(reqStr)) + + err, resp := worker.DoPostRequestJSON(url, reqStr, headers) + var response proto.PPTThemeResponse + if err != nil { + log.Println("Spark PPT Theme Error:", err) + } else { + err = json.Unmarshal(resp, &response) + if err != nil { + log.Println("Spark PPT Theme Error decoding response:", err) + } + } + log.Println("Spark PPT Theme Response:", string(resp)) + //log.Println("Spark PPT Theme Response:", response) + return response, err +} + +func getSparkRequestHeaders(appId, apiSecret string) (map[string]string, error) { + headers := map[string]string{ + "appId": "d3a4647c", + "timestamp": strconv.FormatInt(time.Now().Unix(), 10), + } + algorithm := ApiAuthAlgorithm{} + signature := algorithm.GetSignature(appId, apiSecret, time.Now().Unix()) + headers["signature"] = signature + return headers, nil +} + +// 根据用户输入及文档生成大纲,文档可以是docx、doc、txt、pdf格式 +func SparkCreateOutlineByDoc(model *proto.ModelParam, userReq *proto.SparkCreateOutlineRequest) (proto.SparkCreateOutlineResponse, error) { + url := "https://zwapi.xfyun.cn/api/ppt/v2/createOutlineByDoc" + headers, err := getSparkRequestHeaders(model.APPID, model.APISecret) + if err != nil { + log.Println("Spark PPT Theme Error getting headers:", err) + return proto.SparkCreateOutlineResponse{}, err + } + log.Println("Spark create outline by doc headers:", headers) + + req := proto.SparkCreateOutlineByDocRequest{ + Query: userReq.Query, + FileUrl: userReq.FileUrl, + FileName: userReq.FileName, + } + + reqStr, err := json.Marshal(req) + if err != nil { + log.Println("Spark create outline by doc Error encoding request:", err) + } + log.Println("Spark create outline by doc req:", string(reqStr)) + + err, resp := worker.DoPostRequestForm(url, reqStr, headers) + //log.Println("Spark create outline by doc Response:", string(resp)) + var response proto.SparkCreateOutlineResponse + if err != nil { + log.Println("Spark create outline by doc Error:", err) + } else { + err = json.Unmarshal(resp, &response) + if err != nil { + log.Println("Spark create outline by doc Error decoding response:", err) + } + } + log.Println("Spark create outline by doc Response struct:", response) + return response, err +} + +// 根据query生成大纲 +func SparkCreateOutline(model *proto.ModelParam, userReq *proto.SparkCreateOutlineRequest) (proto.SparkCreateOutlineResponse, error) { + url := "https://zwapi.xfyun.cn/api/ppt/v2/createOutline" + headers, err := getSparkRequestHeaders(model.APPID, model.APISecret) + if err != nil { + log.Println("Spark PPT Theme Error getting headers:", err) + return proto.SparkCreateOutlineResponse{}, err + } + log.Println("Spark create outline by doc headers:", headers) + + //自定义内容 + req := proto.SparkCreateOutlineByDocRequest{ + Query: userReq.Query, + } + reqStr, err := json.Marshal(req) + if err != nil { + log.Println("Spark create PPT Error encoding request:", err) + } + log.Println("Spark create PPT req:", string(reqStr)) + + err, resp := worker.DoPostRequestForm(url, reqStr, headers) + log.Println("Spark create PPT Response:", string(resp)) + var response proto.SparkCreateOutlineResponse + if err != nil { + log.Println("Spark create PPT Error:", err) + } else { + err = json.Unmarshal(resp, &response) + if err != nil { + log.Println("Spark create PPT Error decoding response:", err) + } + } + log.Println("Spark create PPT Response struct:", response) + return response, err +} + +func SparkCreatePPTByOutline(model *proto.ModelParam, userReq *proto.SparkCreatePPTByOutlineUserRequest) (proto.SparkCreatePPTByOutlineResponse, error) { + url := "https://zwapi.xfyun.cn/api/ppt/v2/createPptByOutline" + headers, err := getSparkRequestHeaders(model.APPID, model.APISecret) + if err != nil { + log.Println("Spark create ppt by outline Error encoding request:", err) + return proto.SparkCreatePPTByOutlineResponse{}, err + } + log.Println("Spark create ppt by outline headers:", headers) + + req := proto.SparkCreatePptByOutlineRequest{ + Query: userReq.Query, + FileUrl: userReq.FileUrl, + FileName: userReq.FileName, + Outline: userReq.Outline, + } + + reqStr, err := json.Marshal(req) + if err != nil { + log.Println("Spark create ppt by outline Error encoding request:", err) + } + log.Println("Spark create ppt by outline req:", string(reqStr)) + + err, resp := worker.DoPostRequestJSON(url, reqStr, headers) + log.Println("Spark create ppt by outline Response:", string(resp)) + var response proto.SparkCreatePPTByOutlineResponse + if err != nil { + log.Println("Spark create ppt by outline Error:", err) + } else { + err = json.Unmarshal(resp, &response) + if err != nil { + log.Println("Spark create ppt by outline Error decoding response:", err) + } + } + log.Println("Spark create ppt by outline Response struct:", response) + return response, err +} + +func SparkGetPPTInfoBySID(model *proto.ModelParam, userReq *proto.SparkCreatePPTByOutlineUserRequest) (proto.SparkCreatePPTByOutlineResponse, error) { + url := "https://zwapi.xfyun.cn/api/ppt/v2/progress?sid=" + userReq.Sid + headers, err := getSparkRequestHeaders(model.APPID, model.APISecret) + if err != nil { + log.Println("Spark create ppt by outline Error encoding request:", err) + return proto.SparkCreatePPTByOutlineResponse{}, err + } + log.Println("Spark create ppt by outline headers:", headers) + + err, resp := worker.DoGetRequest(url, headers) + log.Println("Spark create ppt by outline Response:", string(resp)) + var response proto.SparkCreatePPTByOutlineResponse + if err != nil { + log.Println("Spark create ppt by outline Error:", err) + } else { + err = json.Unmarshal(resp, &response) + if err != nil { + log.Println("Spark create ppt by outline Error decoding response:", err) + } + } + log.Println("Spark create ppt by outline Response struct:", response) + return response, err +} diff --git a/worker/req.go b/worker/req.go index c2bd4d5..409a6d8 100644 --- a/worker/req.go +++ b/worker/req.go @@ -7,7 +7,10 @@ import ( "fmt" "io" "io/ioutil" + "log" + "mime/multipart" "net/http" + "strconv" "strings" ) @@ -178,3 +181,149 @@ func SyncDataFromMasterReq2(url string, data proto.SyncUserReq) (proto.UserSync, fmt.Println("SyncDataFromMasterReq2 result add data:", len(res.Add), "update data:", len(res.Update), "delete data:", len(res.Delete)) return res, nil } + +func DoPostRequestJSON(url string, jsonData []byte, headers map[string]string) (error, []byte) { + httpClient := &http.Client{} + defer func() { + if r := recover(); r != nil { + fmt.Println("SyncDataFromMasterReq2 error:", r) + } + }() + + //从接口获取数据 + req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonData)) + if err != nil { + return err, nil + } + req.Header.Set("Content-Type", "application/json") + //设置header + for k, v := range headers { + req.Header.Set(k, v) + } + //传输数据 + if httpClient == nil { + httpClient = &http.Client{} + } + //获取数据 + resp, err := httpClient.Do(req) + if err != nil { + return err, nil + } + defer resp.Body.Close() + //解析数据 + responseBod, err := io.ReadAll(resp.Body) + if err != nil { + return err, nil + } + return err, responseBod +} + +func DoPostRequestForm(url string, jsonData []byte, headers map[string]string) (error, []byte) { + httpClient := &http.Client{} + defer func() { + if r := recover(); r != nil { + fmt.Println("SyncDataFromMasterReq2 error:", r) + } + }() + + // 创建一个新的 buffer 用于存储 multipart/form-data 请求体 + body := &bytes.Buffer{} + writer := multipart.NewWriter(body) + // 修改 data 类型为 map[string]interface{} 以支持不同类型的值 + var data map[string]interface{} + err2 := json.Unmarshal(jsonData, &data) + if err2 != nil { + log.Println("do post json unmarshal error:", err2) + return err2, nil + } + + var err error + for k, v := range data { + switch val := v.(type) { + case bool: + // 处理布尔类型的值 + err = writer.WriteField(k, strconv.FormatBool(val)) + case string: + // 处理字符串类型的值 + err = writer.WriteField(k, val) + default: + // 其他类型可以根据需要扩展处理逻辑 + log.Printf("Unsupported type for field %s: %T\n", k, v) + continue + } + if err != nil { + log.Println("write field error:", err) + return err, nil + } + } + + // 关闭 writer 以完成请求体的构建 + err = writer.Close() + if err != nil { + return err, nil + } + + // 创建 POST 请求 + req, err := http.NewRequest("POST", url, body) + if err != nil { + return err, nil + } + + // 设置 Content-Type 为 multipart/form-data,并带上 boundary + req.Header.Set("Content-Type", writer.FormDataContentType()) + + // 设置其他自定义请求头 + for k, v := range headers { + req.Header.Set(k, v) + } + + // 发送请求 + resp, err := httpClient.Do(req) + if err != nil { + return err, nil + } + defer resp.Body.Close() + + // 读取响应体 + responseBod, err := io.ReadAll(resp.Body) + if err != nil { + return err, nil + } + + return nil, responseBod +} + +func DoGetRequest(url string, headers map[string]string) (error, []byte) { + httpClient := &http.Client{} + defer func() { + if r := recover(); r != nil { + fmt.Println("SyncDataFromMasterReq2 error:", r) + } + }() + + //从接口获取数据 + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return err, nil + } + //设置header + for k, v := range headers { + req.Header.Set(k, v) + } + //传输数据 + if httpClient == nil { + httpClient = &http.Client{} + } + //获取数据 + resp, err := httpClient.Do(req) + if err != nil { + return err, nil + } + defer resp.Body.Close() + //解析数据 + responseBod, err := io.ReadAll(resp.Body) + if err != nil { + return err, nil + } + return err, responseBod +}