545 lines
16 KiB
Go
545 lines
16 KiB
Go
package feishu
|
||
|
||
import (
|
||
"backend/Type"
|
||
"backend/common"
|
||
"backend/middleware/feishu/client"
|
||
"backend/util"
|
||
"bytes"
|
||
"encoding/json"
|
||
"fmt"
|
||
"log"
|
||
"net/http"
|
||
"strings"
|
||
"time"
|
||
)
|
||
|
||
var NOTIFY_TITLE_COLOR = map[string]string{
|
||
"Not classified": "grey",
|
||
"Information": "blue",
|
||
"Warning": "yellow",
|
||
"Average": "orange",
|
||
"High": "red",
|
||
"Disaster": "carmine",
|
||
}
|
||
|
||
func SendFeishuMsg(msg string) error {
|
||
// 创建请求体
|
||
payload := map[string]interface{}{
|
||
"msg_type": "text",
|
||
"content": map[string]string{
|
||
"text": msg,
|
||
},
|
||
}
|
||
payloadBytes, err := json.Marshal(payload)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
|
||
// 创建HTTP请求
|
||
req, err := http.NewRequest("POST", common.GetFeishuUrl(), bytes.NewBuffer(payloadBytes))
|
||
if err != nil {
|
||
return err
|
||
}
|
||
req.Header.Set("Content-Type", "application/json")
|
||
|
||
// 发送请求
|
||
client := &http.Client{}
|
||
resp, err := client.Do(req)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
defer resp.Body.Close()
|
||
|
||
// 检查响应状态码
|
||
if resp.StatusCode != http.StatusOK {
|
||
return fmt.Errorf("failed to send message, status code: %d", resp.StatusCode)
|
||
}
|
||
|
||
return nil
|
||
}
|
||
|
||
func SendNoticeMsg(AppName, ServerName, notice string) error {
|
||
str := fmt.Sprintf(`
|
||
## **游戏数据监控异常**
|
||
- 项目名称: %s
|
||
- 监控项名称: %s
|
||
- 异常信息: %s
|
||
<at id="all"></at>
|
||
`, AppName, ServerName, notice)
|
||
// 创建请求体
|
||
payload := map[string]interface{}{
|
||
"msg_type": "interactive",
|
||
"card": map[string]interface{}{
|
||
"type": "template",
|
||
"data": map[string]interface{}{
|
||
"template_id": "AAqBcOkbPmfUZ",
|
||
"template_version_name": "1.0.3",
|
||
"template_variable": map[string]interface{}{
|
||
"appName": AppName,
|
||
"msg": str,
|
||
},
|
||
},
|
||
},
|
||
}
|
||
payloadBytes, err := json.Marshal(payload)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
|
||
// 创建HTTP请求
|
||
req, err := http.NewRequest("POST", common.GetNoticeUrl(), bytes.NewBuffer(payloadBytes))
|
||
if err != nil {
|
||
return err
|
||
}
|
||
req.Header.Set("Content-Type", "application/json")
|
||
|
||
// 发送请求
|
||
client := &http.Client{}
|
||
resp, err := client.Do(req)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
defer resp.Body.Close()
|
||
|
||
// 检查响应状态码
|
||
if resp.StatusCode != http.StatusOK {
|
||
return fmt.Errorf("failed to send message, status code: %d", resp.StatusCode)
|
||
}
|
||
|
||
return nil
|
||
}
|
||
|
||
// table_raw_array_1
|
||
func SendOperationMsg(Operation *Type.Operation) error {
|
||
// retainStr := ""
|
||
// for _, v := range data.Retain {
|
||
// retainStr += fmt.Sprintf("| %s | %d | %d | %.2f | %.2f%% | %.2f%% | %.2f%% | %.2f%% |\n", v.Date, v.Register, v.Login, v.Recharge, 100*float64(v.SecondRemain)/float64(v.Register), 100*float64(v.ThirdRemain)/float64(v.Register), 100*float64(v.SeventhRemain)/float64(v.Register), 100*float64(v.ThirtiethRemain)/float64(v.Register))
|
||
// }
|
||
RetainData := make([]map[string]interface{}, 0)
|
||
for _, v := range Operation.Retain {
|
||
var retain2, retain3, retain7 string
|
||
if v.Register == 0 {
|
||
retain2 = "0.00%"
|
||
retain3 = "0.00%"
|
||
retain7 = "0.00%"
|
||
} else {
|
||
retain2 = fmt.Sprintf("%.2f%%", 100*float64(v.SecondRemain)/float64(v.Register))
|
||
retain3 = fmt.Sprintf("%.2f%%", 100*float64(v.ThirdRemain)/float64(v.Register))
|
||
retain7 = fmt.Sprintf("%.2f%%", 100*float64(v.SeventhRemain)/float64(v.Register))
|
||
}
|
||
RetainData = append(RetainData, map[string]interface{}{
|
||
"Date": v.Date,
|
||
"Reg": v.Register,
|
||
"Login": v.Login,
|
||
"Pay": v.Recharge,
|
||
"Retain2": retain2,
|
||
"Retain3": retain3,
|
||
"Retain7": retain7,
|
||
// "Retain14": fmt.Sprintf("%.2f%%", 100*float64(v.ThirtiethRemain)/float64(v.Register)),
|
||
})
|
||
}
|
||
var c1, c2 string
|
||
if Operation.Retain[0].PerOnlineTime > Operation.Retain[1].PerOnlineTime {
|
||
c1 = common.FONT_COLOR_UP
|
||
} else {
|
||
c1 = common.FONT_COLOR_DOWN
|
||
}
|
||
if Operation.Retain[0].PerOrderNum > Operation.Retain[1].PerOrderNum {
|
||
c2 = common.FONT_COLOR_UP
|
||
} else {
|
||
c2 = common.FONT_COLOR_DOWN
|
||
}
|
||
str := fmt.Sprintf(`
|
||
# 日期 %s
|
||
-----------------------------
|
||
## 总体数据
|
||
|
||
- **注册**:%d
|
||
- **充值**:%.2f
|
||
- **流失率**:%.2f%%
|
||
> 超过7天未登录视为流失
|
||
|
||
## 昨日数据
|
||
|
||
- **注册**:%d
|
||
- **充值**:%.2f
|
||
- **登录**:%d
|
||
- **平均在线时长**:<font color="%s">%.2f</font>分钟
|
||
- **平均完成订单数**:<font color="%s">%.2f</font>
|
||
----------------------
|
||
|
||
## 留存数据
|
||
|
||
`, time.Now().In(time.UTC).Format("2006-01-02"),
|
||
Operation.Register, Operation.Recharge, Operation.ChurnRate, Operation.Retain[0].Register, Operation.Retain[0].Recharge, Operation.Retain[0].Login,
|
||
c1, Operation.Retain[0].PerOnlineTime, c2, Operation.Retain[0].PerOrderNum)
|
||
// 创建请求体
|
||
payload := map[string]interface{}{
|
||
"msg_type": "interactive",
|
||
"card": map[string]interface{}{
|
||
"type": "template",
|
||
"data": map[string]interface{}{
|
||
"template_id": "AAqBcfmUwQya1",
|
||
"template_version_name": "1.0.10",
|
||
"template_variable": map[string]interface{}{
|
||
"msg": str,
|
||
"appName": "merge_pet_london",
|
||
"table_raw_array_1": RetainData,
|
||
},
|
||
},
|
||
},
|
||
}
|
||
payloadBytes, err := json.Marshal(payload)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
|
||
// 创建HTTP请求
|
||
req, err := http.NewRequest("POST", common.GetOperationUrl(), bytes.NewBuffer(payloadBytes))
|
||
if err != nil {
|
||
return err
|
||
}
|
||
req.Header.Set("Content-Type", "application/json")
|
||
|
||
// 发送请求
|
||
client := &http.Client{}
|
||
resp, err := client.Do(req)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
defer resp.Body.Close()
|
||
|
||
// 检查响应状态码
|
||
if resp.StatusCode != http.StatusOK {
|
||
return fmt.Errorf("failed to send message, status code: %d", resp.StatusCode)
|
||
}
|
||
|
||
return nil
|
||
}
|
||
|
||
func SendUpdateCard() error {
|
||
payload := map[string]interface{}{
|
||
"msg_type": "interactive",
|
||
"card": map[string]interface{}{
|
||
"type": "template",
|
||
"data": map[string]interface{}{
|
||
"template_id": "AAqBmWrjPeHVp",
|
||
"template_version_name": "1.0.3",
|
||
// "template_variable": map[string]interface{}{},
|
||
},
|
||
},
|
||
}
|
||
payloadBytes, err := json.Marshal(payload)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
|
||
// 创建HTTP请求
|
||
req, err := http.NewRequest("POST", common.GetOperationUrl(), bytes.NewBuffer(payloadBytes))
|
||
if err != nil {
|
||
return err
|
||
}
|
||
req.Header.Set("Content-Type", "application/json")
|
||
|
||
// 发送请求
|
||
client := &http.Client{}
|
||
resp, err := client.Do(req)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
defer resp.Body.Close()
|
||
|
||
// 检查响应状态码
|
||
if resp.StatusCode != http.StatusOK {
|
||
return fmt.Errorf("failed to send message, status code: %d", resp.StatusCode)
|
||
}
|
||
|
||
return nil
|
||
}
|
||
|
||
func SendServerInfoCard(data *Type.ServerInfo) error {
|
||
|
||
return nil
|
||
}
|
||
|
||
// table_raw_array_1
|
||
func SendWeekOperationMsg(data *Type.Operation) error {
|
||
// retainStr := ""
|
||
// for _, v := range data.Retain {
|
||
// retainStr += fmt.Sprintf("| %s | %d | %d | %.2f | %.2f%% | %.2f%% | %.2f%% | %.2f%% |\n", v.Date, v.Register, v.Login, v.Recharge, 100*float64(v.SecondRemain)/float64(v.Register), 100*float64(v.ThirdRemain)/float64(v.Register), 100*float64(v.SeventhRemain)/float64(v.Register), 100*float64(v.ThirtiethRemain)/float64(v.Register))
|
||
// }
|
||
RetainData := make([]map[string]interface{}, 0)
|
||
for _, v := range data.Retain {
|
||
RetainData = append(RetainData, map[string]interface{}{
|
||
"Date": v.Date,
|
||
"Reg": v.Register,
|
||
"Login": v.Login,
|
||
"Pay": v.Recharge,
|
||
"Retain2": fmt.Sprintf("%.2f%%", 100*float64(v.SecondRemain)/float64(v.Register)),
|
||
"Retain3": fmt.Sprintf("%.2f%%", 100*float64(v.ThirdRemain)/float64(v.Register)),
|
||
"Retain7": fmt.Sprintf("%.2f%%", 100*float64(v.SeventhRemain)/float64(v.Register)),
|
||
// "Retain14": fmt.Sprintf("%.2f%%", 100*float64(v.ThirtiethRemain)/float64(v.Register)),
|
||
})
|
||
}
|
||
str := fmt.Sprintf(`
|
||
# 日期 %s
|
||
-----------------------------
|
||
## 总体数据
|
||
|
||
- **注册**:%d
|
||
- **充值**:%.2f
|
||
- **流失率**:%.2f%%
|
||
> 超过7天未登录视为流失
|
||
|
||
## 昨日数据
|
||
|
||
- **注册**:%d
|
||
- **充值**:%.2f
|
||
- **登录**:%d
|
||
- **平均在线时长**:%.2f分钟
|
||
- **平均完成订单数**:%.2f
|
||
----------------------
|
||
|
||
## 留存数据
|
||
|
||
`, time.Now().In(time.UTC).Format("2006-01-02"), data.Register, data.Recharge, data.ChurnRate, data.Retain[0].Register, data.Retain[0].Recharge, data.Retain[0].Login, data.Retain[0].PerOnlineTime, data.Retain[0].PerOrderNum)
|
||
// 创建请求体
|
||
payload := map[string]interface{}{
|
||
"msg_type": "interactive",
|
||
"card": map[string]interface{}{
|
||
"type": "template",
|
||
"data": map[string]interface{}{
|
||
"template_id": "AAqBcfmUwQya1",
|
||
"template_version_name": "1.0.5",
|
||
"template_variable": map[string]interface{}{
|
||
"msg": str,
|
||
"appName": "merge_pet_london",
|
||
"table_raw_array_1": RetainData,
|
||
},
|
||
},
|
||
},
|
||
}
|
||
payloadBytes, err := json.Marshal(payload)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
|
||
// 创建HTTP请求
|
||
req, err := http.NewRequest("POST", common.GetOperationUrl(), bytes.NewBuffer(payloadBytes))
|
||
if err != nil {
|
||
return err
|
||
}
|
||
req.Header.Set("Content-Type", "application/json")
|
||
|
||
// 发送请求
|
||
client := &http.Client{}
|
||
resp, err := client.Do(req)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
defer resp.Body.Close()
|
||
|
||
// 检查响应状态码
|
||
if resp.StatusCode != http.StatusOK {
|
||
return fmt.Errorf("failed to send message, status code: %d", resp.StatusCode)
|
||
}
|
||
|
||
return nil
|
||
}
|
||
|
||
func SendOperationMsg2(AppId int) error {
|
||
App, _ := util.GetAppConfig(AppId)
|
||
Operation, err := util.GetOperation(App)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
register := 0
|
||
remain := 0
|
||
for i := 1; i <= 7; i++ {
|
||
register += Operation.Retain[i].Register
|
||
remain += Operation.Retain[i].SecondRemain
|
||
}
|
||
card_md_data := Type.CardMdData{
|
||
Date: Operation.Date,
|
||
Register: Operation.Register,
|
||
Recharge: Operation.Recharge,
|
||
RechargeUserNum: Operation.RechargeUserNum,
|
||
ChurnRate: Operation.ChurnRate,
|
||
ARPU: Operation.ARPU,
|
||
YRegister: Operation.Retain[0].Register,
|
||
YRecharge: Operation.Retain[0].Recharge,
|
||
YLogin: Operation.Retain[0].Login,
|
||
PerOnlineTime: Operation.Retain[0].PerOnlineTime,
|
||
PerOrderNum: Operation.Retain[0].PerOrderNum,
|
||
C1: util.Ternary(Operation.Retain[0].PerOnlineTime > Operation.Retain[1].PerOnlineTime, common.FONT_COLOR_UP, common.FONT_COLOR_DOWN).(string),
|
||
C2: util.Ternary(Operation.Retain[0].PerOrderNum > Operation.Retain[1].PerOrderNum, common.FONT_COLOR_UP, common.FONT_COLOR_DOWN).(string),
|
||
RemainRate: fmt.Sprintf("%.2f", float64(remain)/float64(register)),
|
||
}
|
||
data1 := Type.MarkDown{
|
||
Markdown: util.ToTmplStr(util.ParseTmpl("./template/card_md_1.tmpl", card_md_data)),
|
||
}
|
||
MarkDown := util.ParseTmpl("./template/card_md.tmpl", data1)
|
||
|
||
var table_tmpl string
|
||
var table_tmpl_rows []string
|
||
for _, v := range Operation.Retain {
|
||
row_data := Type.RowData{
|
||
Date: v.Date,
|
||
Login: v.Login,
|
||
Register: v.Register,
|
||
Recharge: v.Recharge,
|
||
SecondRemain: fmt.Sprintf("%.2f%%", 100*util.FloatDiv(v.SecondRemain, v.Register, 5)),
|
||
ThirdRemain: fmt.Sprintf("%.2f%%", 100*util.FloatDiv(v.ThirdRemain, v.Register, 5)),
|
||
SeventhRemain: fmt.Sprintf("%.2f%%", 100*util.FloatDiv(v.SeventhRemain, v.Register, 5)),
|
||
}
|
||
table_tmpl_rows = append(table_tmpl_rows, util.ParseTmpl("./template/card_table_row.tmpl", row_data))
|
||
}
|
||
|
||
table_tmpl_data := Type.CardTable{
|
||
Rows: strings.Join(table_tmpl_rows, ","),
|
||
}
|
||
table_tmpl = util.ParseTmpl("./template/card_table.tmpl", table_tmpl_data)
|
||
|
||
HeatArr := make([]string, 0)
|
||
statisticsData, err := util.GetDailyHeat(AppId)
|
||
for k, v := range statisticsData.Key {
|
||
HeatArr = append(HeatArr, fmt.Sprintf(`{"time":"%s","value":%d}`, v, statisticsData.Value[k]))
|
||
}
|
||
if err != nil {
|
||
log.Printf("failed to get statistics data: %v", err)
|
||
}
|
||
VchartArea := util.ParseTmpl("./template/card_vchart_area.tmpl", Type.CardVchartData{Values: strings.Join(HeatArr, ",")})
|
||
|
||
LevelArr := make([]string, 0)
|
||
levelData, _ := util.GetLevelData(AppId)
|
||
for k, v := range levelData.Key {
|
||
LevelArr = append(LevelArr, fmt.Sprintf(`{"level":"%s","value":%d, "type":"all"}`, v, levelData.Value[k]))
|
||
LevelArr = append(LevelArr, fmt.Sprintf(`{"level":"%s","value":%d, "type":"churn"}`, v, levelData.Value2[k]))
|
||
}
|
||
VchartBar := util.ParseTmpl("./template/card_vchart_bar.tmpl", Type.CardVchartData{Values: strings.Join(LevelArr, ",")})
|
||
|
||
DecoArr := make([]string, 0)
|
||
decoData, _ := util.GetDecorateData(AppId)
|
||
for k, v := range decoData.Key {
|
||
DecoArr = append(DecoArr, fmt.Sprintf(`{"deco_step":"%s","value":%d, "type":"all"}`, v, decoData.Value[k]))
|
||
DecoArr = append(DecoArr, fmt.Sprintf(`{"deco_step":"%s","value":%d, "type":"churn"}`, v, decoData.Value2[k]))
|
||
}
|
||
VchartBarDeco := util.ParseTmpl("./template/card_vchart_bar_d.tmpl", Type.CardVchartData{Values: strings.Join(DecoArr, ",")})
|
||
|
||
hr := util.ParseTmpl("./template/card_hr.tmpl", nil)
|
||
elements := []string{
|
||
MarkDown,
|
||
table_tmpl,
|
||
hr,
|
||
VchartArea,
|
||
hr,
|
||
VchartBar,
|
||
hr,
|
||
VchartBarDeco,
|
||
}
|
||
elementsStr := strings.Join(elements, ",")
|
||
data := Type.Card{
|
||
Title: "运营周报",
|
||
Elements: elementsStr,
|
||
Tag1: "US",
|
||
}
|
||
|
||
s := util.ParseTmpl("./template/card.tmpl", data)
|
||
if !json.Valid([]byte(s)) {
|
||
fmt.Println(s)
|
||
return fmt.Errorf("invalid JSON format")
|
||
}
|
||
c := client.GetClient()
|
||
c.SendGroupMsg(common.GetUSOperationChatId(), common.FEISHU_CART_TYPE, s)
|
||
return nil
|
||
}
|
||
|
||
func SendNotifyMsg(data *Type.NotifyData) error {
|
||
TitleColor := NOTIFY_TITLE_COLOR[data.Severity]
|
||
payload := map[string]interface{}{
|
||
"type": "template",
|
||
"data": map[string]interface{}{
|
||
"template_id": "AAqB4RTngW8Wt",
|
||
"template_version_name": "1.0.7",
|
||
|
||
"template_variable": map[string]interface{}{
|
||
"Title": "待处理",
|
||
"TitleColor": TitleColor,
|
||
"InputMsg": "处理情况说明,选填",
|
||
"HostName": data.Host,
|
||
"EventName": data.EventName,
|
||
"EventSeverity": data.Severity,
|
||
"alarm_time": data.AlarmTime,
|
||
"NotifyMsg": data.NotifyMsg,
|
||
},
|
||
},
|
||
}
|
||
payloadBytes, err := json.Marshal(payload)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
c := client.GetClient()
|
||
err = c.SendGroupMsg(common.GetOperationChatId(), common.FEISHU_CART_TYPE, string(payloadBytes))
|
||
if err != nil {
|
||
log.Printf("sendNotifyMsg error %v", err)
|
||
}
|
||
return nil
|
||
}
|
||
|
||
// AAq9lf37SuuDP
|
||
func SendNotifyOrderMsg(data *Type.OrderData) error {
|
||
payload := map[string]interface{}{
|
||
"type": "template",
|
||
"data": map[string]interface{}{
|
||
"template_id": "AAq9lf37SuuDP",
|
||
"template_version_name": "1.0.1",
|
||
"template_variable": map[string]interface{}{
|
||
"UID": data.UID,
|
||
"OrderId": data.OrderId,
|
||
"Product": data.Product,
|
||
"ProductName": data.ProductName,
|
||
"EventRecovery": data.EventRecovery,
|
||
"EventAge": data.EventAge,
|
||
},
|
||
},
|
||
}
|
||
payloadBytes, err := json.Marshal(payload)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
c := client.GetClient()
|
||
err = c.SendGroupMsg(common.GetUSOperationChatId(), common.FEISHU_CART_TYPE, string(payloadBytes))
|
||
if err != nil {
|
||
log.Printf("sendNotifyMsg error %v", err)
|
||
}
|
||
return nil
|
||
}
|
||
func SendNotifyClientMsg(data *Type.NotifyClientData) error {
|
||
payload := map[string]interface{}{
|
||
"type": "template",
|
||
"data": map[string]interface{}{
|
||
"template_id": "AAqR0eWBmiN6z",
|
||
"template_version_name": "1.0.7",
|
||
"template_variable": map[string]interface{}{
|
||
"log": data.Log,
|
||
"stackTrace": data.StackTrace,
|
||
"deviceModel": data.DeviceModel,
|
||
"operatingSystem": data.OperatingSystem,
|
||
"AlarmTime": data.AlarmTime,
|
||
"deviceUniqueIdentifier": data.DeviceUniqueIdentifier,
|
||
},
|
||
},
|
||
}
|
||
payloadBytes, err := json.Marshal(payload)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
c := client.GetClient()
|
||
err = c.SendGroupMsg(common.GetClientChatId(), common.FEISHU_CART_TYPE, string(payloadBytes))
|
||
if err != nil {
|
||
log.Printf("sendNotifyMsg error %v", err)
|
||
}
|
||
return nil
|
||
}
|