Merge remote-tracking branch 'origin/master' into test
This commit is contained in:
commit
9d9c65242c
|
|
@ -161,7 +161,7 @@ qywx:
|
|||
app_secret: "uYqtdwdtdH4Uv_P4is2AChuGzBCoB6cQDyRvpbW0Vmk"
|
||||
token: "zJdukry6"
|
||||
aes_key: "4VLH47qRGUogc2d3QLWuUhvJlk8Y0YuRjXzeBquBq8B"
|
||||
init_account: "les."
|
||||
init_account: "les.,FuZhongYun"
|
||||
chat_id_len: 16
|
||||
default_config_id: 1
|
||||
bot_group_id:
|
||||
|
|
|
|||
|
|
@ -156,16 +156,11 @@ qywx:
|
|||
app_secret: "uYqtdwdtdH4Uv_P4is2AChuGzBCoB6cQDyRvpbW0Vmk"
|
||||
token: "zJdukry6"
|
||||
aes_key: "4VLH47qRGUogc2d3QLWuUhvJlk8Y0YuRjXzeBquBq8B"
|
||||
#
|
||||
# corp_id: "wx5823bf96d3bd56c7"
|
||||
# token: "QDG6eK"
|
||||
# aes_key: "jWmYm7qr5nMoAUwZRjGtBxmz3KA1tkAj3ykkR6q2B2C"
|
||||
# app_secret: "uYqtdwdtdH4Uv_P4is2AChuGzBCoB6cQDyRvpbW0Vmk"
|
||||
init_account: "les."
|
||||
init_account: "les.,FuZhongYun"
|
||||
chat_id_len: 16
|
||||
default_config_id: 1
|
||||
bot_group_id:
|
||||
bbxt: 23
|
||||
bbxt: 35
|
||||
|
||||
default_prompt:
|
||||
img_recognize:
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@ func (g *GroupConfigBiz) GetReportLists(ctx context.Context, groupConfig *model.
|
|||
if err != nil {
|
||||
return
|
||||
}
|
||||
//product = []string{"优酷周卡", "优酷季卡", "优酷年卡", "爱奇艺黄金会员天卡"}
|
||||
|
||||
//追加电商充值系统统计 - 返回统一使用[]*bbxt.ReportRes
|
||||
rechargeReports, err := g.rechargeDailyReport(ctx, time.Now(), nil, g.ossClient)
|
||||
if err != nil || len(rechargeReports) == 0 {
|
||||
|
|
|
|||
|
|
@ -80,3 +80,11 @@ func (a *Auth) getNewAccessToken(ctx context.Context, corpid string, corpsecret
|
|||
}
|
||||
return
|
||||
}
|
||||
|
||||
type UploadMediaRes struct {
|
||||
Errcode int `json:"errcode"`
|
||||
Errmsg string `json:"errmsg"`
|
||||
Type string `json:"type"`
|
||||
MediaId string `json:"media_id"`
|
||||
CreatedAt string `json:"created_at"`
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,19 +33,17 @@ func NewGroup(groupImpl *impl.BotGroupQywxImpl, auth *Auth) *Group {
|
|||
// - GroupCreateResp: 创建群聊的响应结果
|
||||
// - error: 错误信息,如果请求失败则返回错误
|
||||
func (g *Group) Create(ctx context.Context, req GroupCreateReq, corpid string, corpsecret string) (GroupCreateResp, error) {
|
||||
// 声明一个GroupCreateResp结构体变量res,用于存储响应结果
|
||||
|
||||
var res GroupCreateResp
|
||||
// 将请求结构体req转换为map类型的参数param
|
||||
// 如果转换失败,忽略错误
|
||||
|
||||
param, _ := util.StructToMap(req)
|
||||
// 发送HTTP请求到企业微信API创建群聊
|
||||
// 参数依次为:上下文、请求参数、请求URL、响应结果存储指针、企业ID、应用密钥
|
||||
|
||||
_, err := g.request(ctx, param, "https://qyapi.weixin.qq.com/cgi-bin/appchat/create", &res, corpid, corpsecret)
|
||||
// 如果请求过程中发生错误,返回响应结果和错误
|
||||
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
// 请求成功,返回响应结果和nil错误
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
|
|
@ -60,18 +58,76 @@ func (g *Group) Create(ctx context.Context, req GroupCreateReq, corpid string, c
|
|||
// - error: 操作过程中发生的错误,如果成功则为nil
|
||||
func (g *Group) SendMarkDown(ctx context.Context, req GroupSendMarkDownReq, corpid string, corpsecret string) error {
|
||||
|
||||
// 设置消息类型为Markdown
|
||||
req.Msgtype = "markdown"
|
||||
// 将请求结构体转换为map类型,便于后续的HTTP请求参数处理
|
||||
req.Msgtype = "markdown_v2"
|
||||
|
||||
param, _ := util.StructToMap(req)
|
||||
// 调用request方法发送HTTP请求到企业微信API
|
||||
// 参数依次为:上下文、请求参数、API URL、额外请求头、corpid、corpsecret
|
||||
_, err := g.request(ctx, param, " https://qyapi.weixin.qq.com/cgi-bin/appchat/send", nil, corpid, corpsecret)
|
||||
// 如果请求过程中发生错误,直接返回错误
|
||||
|
||||
_, err := g.request(ctx, param, "https://qyapi.weixin.qq.com/cgi-bin/appchat/send", nil, corpid, corpsecret)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// 请求成功,返回nil
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g *Group) SendNews(ctx context.Context, req GroupSendNewsReq, corpid string, corpsecret string) error {
|
||||
|
||||
req.Msgtype = "news"
|
||||
|
||||
param, _ := util.StructToMap(req)
|
||||
|
||||
_, err := g.request(ctx, param, "https://qyapi.weixin.qq.com/cgi-bin/appchat/send", nil, corpid, corpsecret)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g *Group) SendImg(ctx context.Context, req GroupSendImgReq, corpid string, corpsecret string) error {
|
||||
|
||||
req.Msgtype = "image"
|
||||
|
||||
param, _ := util.StructToMap(req)
|
||||
|
||||
_, err := g.request(ctx, param, "https://qyapi.weixin.qq.com/cgi-bin/appchat/send", nil, corpid, corpsecret)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g *Group) SendMpNews(ctx context.Context, req GroupSendMpNewsReq, corpid string, corpsecret string) error {
|
||||
|
||||
req.Msgtype = "mpnews"
|
||||
|
||||
param, _ := util.StructToMap(req)
|
||||
|
||||
_, err := g.request(ctx, param, "https://qyapi.weixin.qq.com/cgi-bin/appchat/send", nil, corpid, corpsecret)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g *Group) SendText(ctx context.Context, req GroupSendTextReq, corpid string, corpsecret string) error {
|
||||
|
||||
req.Msgtype = "text"
|
||||
|
||||
param, _ := util.StructToMap(req)
|
||||
|
||||
_, err := g.request(ctx, param, "https://qyapi.weixin.qq.com/cgi-bin/appchat/send", nil, corpid, corpsecret)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,103 @@
|
|||
package qywx
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"mime/multipart"
|
||||
"net/http"
|
||||
"path"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Other struct {
|
||||
auth *Auth
|
||||
}
|
||||
|
||||
func NewOther(auth *Auth) *Other {
|
||||
return &Other{
|
||||
|
||||
auth: auth,
|
||||
}
|
||||
}
|
||||
|
||||
func (g *Other) UploadMediaWithUrl(ctx context.Context, fileUrl, mediaType, corpid, corpsecret string) (uploadRes *UploadMediaRes, err error) {
|
||||
// 1. 获取AccessToken
|
||||
auth, err := g.auth.GetAccessToken(ctx, corpid, corpsecret)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("获取AccessToken失败: %v", err)
|
||||
}
|
||||
|
||||
// 2. 下载文件
|
||||
client := &http.Client{Timeout: 10 * time.Second}
|
||||
resp, err := client.Get(fileUrl)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("下载文件失败: %v", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
// 检查响应状态
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return nil, fmt.Errorf("下载文件状态码错误: %d", resp.StatusCode)
|
||||
}
|
||||
|
||||
// 3. 准备上传请求(修正点:使用正确的上传API)
|
||||
uploadUrl := fmt.Sprintf("https://qyapi.weixin.qq.com/cgi-bin/media/upload?access_token=%s&type=%s",
|
||||
auth.AccessToken, mediaType)
|
||||
|
||||
// 4. 创建multipart表单
|
||||
body := &bytes.Buffer{}
|
||||
writer := multipart.NewWriter(body)
|
||||
|
||||
// 从URL提取文件名(或使用默认名)
|
||||
filename := path.Base(fileUrl)
|
||||
if filename == "/" || filename == "." {
|
||||
filename = fmt.Sprintf("file_%d.dat", time.Now().Unix())
|
||||
}
|
||||
|
||||
part, err := writer.CreateFormFile("media", filename)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("创建表单文件失败: %v", err)
|
||||
}
|
||||
|
||||
// 5. 流式传输文件内容
|
||||
if _, err = io.Copy(part, resp.Body); err != nil {
|
||||
return nil, fmt.Errorf("写入文件内容失败: %v", err)
|
||||
}
|
||||
|
||||
// 6. 关闭writer
|
||||
if err = writer.Close(); err != nil {
|
||||
return nil, fmt.Errorf("关闭writer失败: %v", err)
|
||||
}
|
||||
|
||||
// 7. 发送上传请求
|
||||
req, err := http.NewRequest("POST", uploadUrl, body)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("创建请求失败: %v", err)
|
||||
}
|
||||
req.Header.Set("Content-Type", writer.FormDataContentType())
|
||||
|
||||
uploadResp, err := client.Do(req)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("上传请求失败: %v", err)
|
||||
}
|
||||
defer uploadResp.Body.Close()
|
||||
|
||||
// 8. 解析响应
|
||||
respBody, err := io.ReadAll(uploadResp.Body)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("读取响应失败: %v", err)
|
||||
}
|
||||
|
||||
if err = json.Unmarshal(respBody, &uploadRes); err != nil {
|
||||
return nil, fmt.Errorf("解析响应失败: %v", err)
|
||||
}
|
||||
|
||||
if uploadRes.Errcode != 0 {
|
||||
return nil, fmt.Errorf("上传失败 [code=%d]: %s", uploadRes.Errcode, uploadRes.Errmsg)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
|
@ -7,4 +7,5 @@ import (
|
|||
var ProviderSetQywx = wire.NewSet(
|
||||
NewAuth,
|
||||
NewGroup,
|
||||
NewOther,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -37,9 +37,66 @@ type commonResp struct {
|
|||
type GroupSendMarkDownReq struct {
|
||||
Chatid string `json:"chatid"`
|
||||
Msgtype string `json:"msgtype"`
|
||||
Markdown MarkDown `json:"markdown"`
|
||||
Markdown MarkDown `json:"markdown_v2"`
|
||||
}
|
||||
|
||||
type MarkDown struct {
|
||||
Content string `json:"content"`
|
||||
}
|
||||
|
||||
type GroupSendNewsReq struct {
|
||||
Chatid string `json:"chatid"`
|
||||
Msgtype string `json:"msgtype"`
|
||||
News News `json:"news"`
|
||||
Safe int `json:"safe"`
|
||||
}
|
||||
|
||||
type News struct {
|
||||
Articles []Articles `json:"articles"`
|
||||
}
|
||||
type Articles struct {
|
||||
Title string `json:"title"`
|
||||
Description string `json:"description"`
|
||||
Url string `json:"url"`
|
||||
Picurl string `json:"picurl"`
|
||||
}
|
||||
|
||||
type GroupSendImgReq struct {
|
||||
Chatid string `json:"chatid"`
|
||||
Msgtype string `json:"msgtype"`
|
||||
Image Image `json:"image"`
|
||||
Safe int `json:"safe"`
|
||||
}
|
||||
type Image struct {
|
||||
MediaId string `json:"media_id"`
|
||||
}
|
||||
|
||||
type GroupSendMpNewsReq struct {
|
||||
Chatid string `json:"chatid"`
|
||||
Msgtype string `json:"msgtype"`
|
||||
Mpnews Mpnews `json:"mpnews"`
|
||||
Safe int `json:"safe"`
|
||||
}
|
||||
|
||||
type Mpnews struct {
|
||||
Articles []ArticlesMpnews `json:"articles"`
|
||||
}
|
||||
type ArticlesMpnews struct {
|
||||
Title string `json:"title"`
|
||||
ThumbMediaId string `json:"thumb_media_id"`
|
||||
Author string `json:"author"`
|
||||
ContentSourceUrl string `json:"content_source_url"`
|
||||
Content string `json:"content"`
|
||||
Digest string `json:"digest"`
|
||||
}
|
||||
|
||||
type GroupSendTextReq struct {
|
||||
Chatid string `json:"chatid"`
|
||||
Msgtype string `json:"msgtype"`
|
||||
Text Text `json:"text"`
|
||||
Safe int `json:"safe"`
|
||||
}
|
||||
|
||||
type Text struct {
|
||||
Content string `json:"content"`
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import (
|
|||
"ai_scheduler/internal/pkg"
|
||||
"ai_scheduler/internal/tools/bbxt"
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"ai_scheduler/internal/config"
|
||||
|
|
@ -21,6 +21,7 @@ type QywxAppBiz struct {
|
|||
conf *config.Config
|
||||
botGroupQywxImpl *impl.BotGroupQywxImpl
|
||||
qywxGroupHandle *qywx.Group
|
||||
qywxOtherHandle *qywx.Other
|
||||
}
|
||||
|
||||
// NewDingTalkBotBiz
|
||||
|
|
@ -28,11 +29,13 @@ func NewQywxAppBiz(
|
|||
conf *config.Config,
|
||||
botGroupQywxImpl *impl.BotGroupQywxImpl,
|
||||
qywxGroupHandle *qywx.Group,
|
||||
qywxOtherHandle *qywx.Other,
|
||||
) *QywxAppBiz {
|
||||
return &QywxAppBiz{
|
||||
conf: conf,
|
||||
botGroupQywxImpl: botGroupQywxImpl,
|
||||
qywxGroupHandle: qywxGroupHandle,
|
||||
qywxOtherHandle: qywxOtherHandle,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -51,11 +54,9 @@ func (q *QywxAppBiz) InitGroup(ctx context.Context) (string, error) {
|
|||
resp, err := q.qywxGroupHandle.Create(
|
||||
ctx,
|
||||
qywx.GroupCreateReq{
|
||||
Name: GroupInfo.Title,
|
||||
Chatid: GroupInfo.ChatID,
|
||||
Userlist: []string{
|
||||
q.conf.Qywx.InitAccount,
|
||||
},
|
||||
Name: GroupInfo.Title,
|
||||
Chatid: GroupInfo.ChatID,
|
||||
Userlist: strings.Split(q.conf.Qywx.InitAccount, ","),
|
||||
},
|
||||
q.conf.Qywx.CorpId,
|
||||
GroupInfo.AppSecret,
|
||||
|
|
@ -77,12 +78,30 @@ func (q *QywxAppBiz) GetGroupInfo(ctx context.Context, groupId int) (group model
|
|||
}
|
||||
|
||||
func (q *QywxAppBiz) SendReport(ctx context.Context, groupInfo *model.AiBotGroupQywx, report *bbxt.ReportRes) (err error) {
|
||||
confitent := fmt.Sprintf("%s\n%s", report.Title, fmt.Sprintf("", report.Url))
|
||||
err = q.qywxGroupHandle.SendMarkDown(ctx, qywx.GroupSendMarkDownReq{
|
||||
//confitent := fmt.Sprintf("%s\n%s", report.Title, fmt.Sprintf("", report.Url))
|
||||
|
||||
upload, err := q.qywxOtherHandle.UploadMediaWithUrl(ctx, report.Url, "image", q.conf.Qywx.CorpId, groupInfo.AppSecret)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
err = q.qywxGroupHandle.SendText(ctx, qywx.GroupSendTextReq{
|
||||
Chatid: groupInfo.ChatID,
|
||||
Markdown: qywx.MarkDown{
|
||||
Content: confitent,
|
||||
Text: qywx.Text{
|
||||
Content: report.ReportName + "\n" + report.Title,
|
||||
},
|
||||
}, q.conf.Qywx.CorpId, groupInfo.AppSecret)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = q.qywxGroupHandle.SendImg(ctx, qywx.GroupSendImgReq{
|
||||
Chatid: groupInfo.ChatID,
|
||||
Image: qywx.Image{
|
||||
MediaId: upload.MediaId,
|
||||
},
|
||||
}, q.conf.Qywx.CorpId, groupInfo.AppSecret)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,8 @@ import (
|
|||
"net/url"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/go-kratos/kratos/v2/log"
|
||||
)
|
||||
|
||||
// 请求结构体
|
||||
|
|
@ -108,7 +110,11 @@ func (r *Request) prepare() *http.Request {
|
|||
Method := r.getMethod()
|
||||
Url := r.getUrl()
|
||||
Data := r.getData()
|
||||
req, _ := http.NewRequest(Method, Url, Data)
|
||||
req, err := http.NewRequest(Method, Url, Data)
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
return nil
|
||||
}
|
||||
r.addHeaders(req)
|
||||
return req
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,6 +44,11 @@ func (c *CronServer) InitJobs(ctx context.Context) {
|
|||
Name: "直连天下报表推送",
|
||||
Schedule: "0 12,18,23 * * *",
|
||||
},
|
||||
{
|
||||
Func: c.cronService.CronReportSendQywx,
|
||||
Name: "直连天下报表推送",
|
||||
Schedule: "0 12,18,23 * * *",
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -35,10 +35,16 @@ func (d *CronService) CronReportSendDingTalk(ctx context.Context) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if groupInfo.GroupID == 0 {
|
||||
return nil
|
||||
}
|
||||
groupConfig, err := d.groupConfigBiz.GetGroupConfig(ctx, groupInfo.ConfigID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if groupConfig.ConfigID == 0 {
|
||||
return nil
|
||||
}
|
||||
reports, err := d.groupConfigBiz.GetReportLists(ctx, groupConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
@ -60,10 +66,16 @@ func (d *CronService) CronReportSendQywx(ctx context.Context) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if groupInfo.GroupID == 0 {
|
||||
return nil
|
||||
}
|
||||
groupConfig, err := d.groupConfigBiz.GetGroupConfig(ctx, groupInfo.ConfigID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if groupConfig.ConfigID == 0 {
|
||||
return nil
|
||||
}
|
||||
reports, err := d.groupConfigBiz.GetReportLists(ctx, groupConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
|
|||
|
|
@ -117,7 +117,8 @@ func run() {
|
|||
botGroupQywxImpl := impl.NewBotGroupQywxImpl(db)
|
||||
qywxAuth := qywx.NewAuth(configConfig, rdb)
|
||||
group := qywx.NewGroup(botGroupQywxImpl, qywxAuth)
|
||||
qywxAppBiz := biz.NewQywxAppBiz(configConfig, botGroupQywxImpl, group)
|
||||
other := qywx.NewOther(qywxAuth)
|
||||
qywxAppBiz := biz.NewQywxAppBiz(configConfig, botGroupQywxImpl, group, other)
|
||||
groupConfigBiz := biz.NewGroupConfigBiz(toolRegis, utils_ossClient, botGroupConfigImpl, registry, configConfig)
|
||||
dingTalkBotBiz := biz.NewDingTalkBotBiz(doDo, handle, botConfigImpl, botGroupImpl, user, botChatHisImpl, manager, configConfig, sendCardClient, groupConfigBiz)
|
||||
// 初始化钉钉机器人服务
|
||||
|
|
|
|||
Loading…
Reference in New Issue