first commit
This commit is contained in:
118
pkg/common/CmdTools/AliyunCloudClient.go
Normal file
118
pkg/common/CmdTools/AliyunCloudClient.go
Normal file
@ -0,0 +1,118 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
|
||||
"github.com/aliyun/alibaba-cloud-sdk-go/services/slb"
|
||||
)
|
||||
|
||||
// LTAI5tCB8SmJcwfO
|
||||
// dX4kgF4VcblsbCVdKvtCGCmvNbLkZK
|
||||
// ./AliyunCloudClient -t b -o update -key LTAI5tCB8SmJcwfO -sec dX4kgF4VcblsbCVdKvtCGCmvNbLkZK -reg cn-hangzhou -lb "[{"ServerId":"ServerId","Weight":"0"}]
|
||||
func main() {
|
||||
var target string
|
||||
flag.StringVar(&target, "t", "b", "target: b=backendServer")
|
||||
var operation string
|
||||
flag.StringVar(&operation, "o", "update", "operation: add、update、remove")
|
||||
var accessKeyId string
|
||||
flag.StringVar(&accessKeyId, "key", "accessKeyId", "accessKeyId")
|
||||
var accessSecret string
|
||||
flag.StringVar(&accessSecret, "sec", "accessSecret", "accessSecret")
|
||||
var regionId string
|
||||
flag.StringVar(®ionId, "reg", "regionId", "regionId: cn-hangzhou")
|
||||
var loadBalancerId string
|
||||
flag.StringVar(&loadBalancerId, "lb", "loadBalancerId", "loadBalancerId")
|
||||
var params string
|
||||
flag.StringVar(¶ms, "params", "", `SetBackendServers: [{"ServerId":"ServerId","Weight":"0"}]
|
||||
AddBackendServers: [{"ServerId":"ServerId","Weight":"100","Type":"eni","ServerIp":"192.168.11.1"}]
|
||||
RemoveBackendServers: [{"ServerId":"ServerId","Weight":"100"}]
|
||||
`)
|
||||
flag.Parse()
|
||||
flag.Usage()
|
||||
fmt.Printf("target=%s,operation=%s,accessKeyId=%s,accessSecret=%s,regionId=%s,loadBalancerId=%s,params=%s", target, operation, accessKeyId, accessSecret, regionId, loadBalancerId, params)
|
||||
if target == "b" {
|
||||
switch operation {
|
||||
case "update":
|
||||
SetBackendServers(regionId, accessKeyId, accessSecret, loadBalancerId, params)
|
||||
break
|
||||
case "add":
|
||||
AddBackendServers(regionId, accessKeyId, accessSecret, loadBalancerId, params)
|
||||
break
|
||||
case "remove":
|
||||
RemoveBackendServers(regionId, accessKeyId, accessSecret, loadBalancerId, params)
|
||||
break
|
||||
default:
|
||||
fmt.Println("operation: " + operation + " not support")
|
||||
}
|
||||
} else {
|
||||
fmt.Println("target: " + target + " not support")
|
||||
}
|
||||
}
|
||||
|
||||
func SetBackendServers(regionId, accessKeyId, accessSecret, loadBalancerId, params string) {
|
||||
// client, err := slb.NewClientWithAccessKey(regionId, accessKeyId, accessSecret)
|
||||
// if nil != err {
|
||||
// fmt.Println("get client error:")
|
||||
// fmt.Println(err.Error())
|
||||
// }
|
||||
|
||||
// request := slb.CreateSetBackendServersRequest()
|
||||
// request.Scheme = "https"
|
||||
|
||||
// request.LoadBalancerId = loadBalancerId
|
||||
// request.BackendServers = params
|
||||
|
||||
// if nil == client {
|
||||
// fmt.Println("error: client is nil")
|
||||
// return
|
||||
// }
|
||||
// response, err := client.SetBackendServers(request)
|
||||
// if err != nil {
|
||||
// fmt.Print(err.Error())
|
||||
// }
|
||||
// fmt.Printf("response is %#v\n", response)
|
||||
}
|
||||
|
||||
func AddBackendServers(regionId, accessKeyId, accessSecret, loadBalancerId, params string) {
|
||||
client, err := slb.NewClientWithAccessKey(regionId, accessKeyId, accessSecret)
|
||||
|
||||
request := slb.CreateAddBackendServersRequest()
|
||||
request.Scheme = "https"
|
||||
|
||||
request.LoadBalancerId = loadBalancerId
|
||||
request.BackendServers = params
|
||||
|
||||
if nil == client {
|
||||
fmt.Println("error: client is nil")
|
||||
return
|
||||
}
|
||||
|
||||
response, err := client.AddBackendServers(request)
|
||||
if err != nil {
|
||||
fmt.Print(err.Error())
|
||||
}
|
||||
fmt.Printf("response is %#v\n", response)
|
||||
}
|
||||
|
||||
func RemoveBackendServers(regionId, accessKeyId, accessSecret, loadBalancerId, params string) {
|
||||
|
||||
client, err := slb.NewClientWithAccessKey(regionId, accessKeyId, accessSecret)
|
||||
|
||||
request := slb.CreateRemoveBackendServersRequest()
|
||||
request.Scheme = "https"
|
||||
|
||||
request.LoadBalancerId = loadBalancerId
|
||||
request.BackendServers = params
|
||||
|
||||
if nil == client {
|
||||
fmt.Println("error: client is nil")
|
||||
return
|
||||
}
|
||||
|
||||
response, err := client.RemoveBackendServers(request)
|
||||
if err != nil {
|
||||
fmt.Print(err.Error())
|
||||
}
|
||||
fmt.Printf("response is %#v\n", response)
|
||||
}
|
||||
70
pkg/common/CmdTools/ExcelTool.go
Normal file
70
pkg/common/CmdTools/ExcelTool.go
Normal file
@ -0,0 +1,70 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
"github.com/tealeg/xlsx"
|
||||
)
|
||||
|
||||
func main02() {
|
||||
data := ReadSheet("./CmdTools/星钻VIP体系.xlsx", 0)
|
||||
fmt.Println(json.Marshal(data))
|
||||
for index, item := range data {
|
||||
if index > 0 {
|
||||
level, _ := strconv.Atoi(item[0])
|
||||
exp, _ := strconv.Atoi(item[1])
|
||||
fmt.Printf("insert into t_vip_config (id,vip_level,min_exp,vip_name,vip_icon,create_time) values (%d,%d,%d,'v%d','https://xz-static.10909.com/XingZuanCommon/Img/Vip/%d@2x.png',now());\n", level, level, exp, level, level)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func ReadSheet(file string, sheet int) [][]string {
|
||||
var result [][]string
|
||||
xlFile, err := xlsx.OpenFile(file)
|
||||
if err != nil {
|
||||
fmt.Println(err.Error())
|
||||
return result
|
||||
}
|
||||
for index, row := range xlFile.Sheets[sheet].Rows {
|
||||
if index > 60 {
|
||||
break
|
||||
}
|
||||
var data []string
|
||||
for index, cell := range row.Cells {
|
||||
if index > 1 {
|
||||
break
|
||||
}
|
||||
text := cell.String()
|
||||
println(text)
|
||||
data = append(data, text)
|
||||
}
|
||||
result = append(result, data)
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func ReadAll(file string) {
|
||||
// 打开文件
|
||||
xlFile, err := xlsx.OpenFile(file)
|
||||
if err != nil {
|
||||
fmt.Println(err.Error())
|
||||
return
|
||||
}
|
||||
// 遍历sheet页读取
|
||||
for _, sheet := range xlFile.Sheets {
|
||||
fmt.Println("sheet name: ", sheet.Name)
|
||||
//遍历行读取
|
||||
for _, row := range sheet.Rows {
|
||||
// 遍历每行的列读取
|
||||
for _, cell := range row.Cells {
|
||||
text := cell.String()
|
||||
fmt.Printf("%20s", text)
|
||||
}
|
||||
fmt.Print("\n")
|
||||
}
|
||||
}
|
||||
fmt.Println("\n\nimport success")
|
||||
}
|
||||
94
pkg/common/CmdTools/TencentCloudClient.go
Normal file
94
pkg/common/CmdTools/TencentCloudClient.go
Normal file
@ -0,0 +1,94 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
|
||||
clb "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/clb/v20180317"
|
||||
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common"
|
||||
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/errors"
|
||||
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/profile"
|
||||
)
|
||||
|
||||
// ./TencentCloudClient -t b -o add -key AKIDSoxxjI5tukPr9ECsQmwthKhroaCZlldI -sec b1FG2b3JMrESVLxjJdhYDgx12qPiplXB -reg ap-shanghai -params "{\"LoadBalancerId\":\"lb-jip7505r\",\"Targets\":[{\"InstanceId\":\"ins-n2i7x483\",\"Weight\":20}]}"
|
||||
// ./TencentCloudClient -t b -o remove -key AKIDSoxxjI5tukPr9ECsQmwthKhroaCZlldI -sec b1FG2b3JMrESVLxjJdhYDgx12qPiplXB -reg ap-shanghai -params "{\"LoadBalancerId\":\"lb-jip7505r\",\"InstanceIds\":[\"ins-n2i7x483\"]}"
|
||||
func main03() {
|
||||
|
||||
var target string
|
||||
flag.StringVar(&target, "t", "b", "target: b=backendServer")
|
||||
var operation string
|
||||
flag.StringVar(&operation, "o", "add", "operation: add、remove")
|
||||
var accessKeyId string
|
||||
flag.StringVar(&accessKeyId, "key", "secretId", "accessKeyId")
|
||||
var accessSecret string
|
||||
flag.StringVar(&accessSecret, "sec", "secretKey", "accessSecret")
|
||||
var regionId string
|
||||
flag.StringVar(®ionId, "reg", "regionId", "regionId: cn-hangzhou")
|
||||
var params string
|
||||
flag.StringVar(¶ms, "params", "params", `
|
||||
AddBackendServers: [{"ServerId":"ServerId","Weight":"100","Type":"eni","ServerIp":"192.168.11.1"}]
|
||||
RemoveBackendServers: [{"ServerId":"ServerId","Weight":"100"}]
|
||||
`)
|
||||
flag.Parse()
|
||||
flag.Usage()
|
||||
fmt.Printf("target=%s,operation=%s,accessKeyId=%s,accessSecret=%s,regionId=%s,params=%s\n", target, operation, accessKeyId, accessSecret, regionId, params)
|
||||
if target == "b" {
|
||||
switch operation {
|
||||
case "add":
|
||||
ClassicBind(regionId, accessKeyId, accessSecret, params)
|
||||
break
|
||||
case "remove":
|
||||
ClassicRemove(regionId, accessKeyId, accessSecret, params)
|
||||
break
|
||||
default:
|
||||
fmt.Println("operation: " + operation + " not support")
|
||||
}
|
||||
} else {
|
||||
fmt.Println("target: " + target + " not support")
|
||||
}
|
||||
}
|
||||
|
||||
func ClassicBind(regionId, accessKeyId, accessSecret, params string) {
|
||||
credential := common.NewCredential(accessKeyId, accessSecret)
|
||||
cpf := profile.NewClientProfile()
|
||||
cpf.HttpProfile.Endpoint = "clb.tencentcloudapi.com"
|
||||
client, _ := clb.NewClient(credential, regionId, cpf)
|
||||
|
||||
request := clb.NewRegisterTargetsWithClassicalLBRequest()
|
||||
|
||||
err := request.FromJsonString(params)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
response, err := client.RegisterTargetsWithClassicalLB(request)
|
||||
if _, ok := err.(*errors.TencentCloudSDKError); ok {
|
||||
fmt.Printf("An API error has returned: %s", err)
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
fmt.Printf("%s", response.ToJsonString())
|
||||
}
|
||||
|
||||
func ClassicRemove(regionId, accessKeyId, accessSecret, params string) {
|
||||
credential := common.NewCredential(accessKeyId, accessSecret)
|
||||
cpf := profile.NewClientProfile()
|
||||
cpf.HttpProfile.Endpoint = "clb.tencentcloudapi.com"
|
||||
client, _ := clb.NewClient(credential, regionId, cpf)
|
||||
|
||||
request := clb.NewDeregisterTargetsFromClassicalLBRequest()
|
||||
err := request.FromJsonString(params)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
response, err := client.DeregisterTargetsFromClassicalLB(request)
|
||||
if _, ok := err.(*errors.TencentCloudSDKError); ok {
|
||||
fmt.Printf("An API error has returned: %s", err)
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
fmt.Printf("%s", response.ToJsonString())
|
||||
}
|
||||
57
pkg/common/CmdTools/readme.md
Normal file
57
pkg/common/CmdTools/readme.md
Normal file
@ -0,0 +1,57 @@
|
||||
# CMD 工具
|
||||
|
||||
## 阿里云SLB后端服务器client工具
|
||||
|
||||
### Usage
|
||||
|
||||
Example: SlbClient.exe -t lb -o update -reg cn-hangzhou -key LTAI5tCB8SmJcwfO -sec dX4kgF4VcblsbCVdKvtCGCmvNbLkZK -lb lb-bp1nz8xl5q8kiqfv0iumf -params "[{\"ServerId\":\"i-bp1hcv8qx0677hv9pr0s\",\"Weight\":\"100\"}]"
|
||||
|
||||
```
|
||||
Usage of SlbClient.exe:
|
||||
-key string
|
||||
accessKeyId (default "accessKeyId")
|
||||
-lb string
|
||||
loadBalancerId (default "loadBalancerId")
|
||||
-o string
|
||||
operation: add、update、remove (default "update")
|
||||
-params string
|
||||
SetBackendServers: [{"ServerId":"ServerId","Weight":"0"}]
|
||||
AddBackendServers: [{"ServerId":"ServerId","Weight":"100","Type":"eni","ServerIp":"192.168.11.1"}]
|
||||
RemoveBackendServers: [{"ServerId":"ServerId","Weight":"100"}]
|
||||
(default "params")
|
||||
-reg string
|
||||
regionId: cn-hangzhou (default "regionId")
|
||||
-sec string
|
||||
accessSecret (default "accessSecret")
|
||||
-t string
|
||||
target: lb (default "lb")
|
||||
```
|
||||
|
||||
|
||||
## 腾讯云CLB后端服务器client工具
|
||||
|
||||
### Usage
|
||||
|
||||
Example1: ./TencentCloudClient -t b -o add -key AKIDSoxxjI5tukPr9ECsQmwthKhroaCZlldI -sec b1FG2b3JMrESVLxjJdhYDgx12qPiplXB -reg ap-shanghai -params "{\"LoadBalancerId\":\"lb-jip7505r\",\"Targets\":[{\"InstanceId\":\"ins-n2i7x483\",\"Weight\":20}]}"
|
||||
Example2: ./TencentCloudClient -t b -o remove -key AKIDSoxxjI5tukPr9ECsQmwthKhroaCZlldI -sec b1FG2b3JMrESVLxjJdhYDgx12qPiplXB -reg ap-shanghai -params "{\"LoadBalancerId\":\"lb-jip7505r\",\"InstanceIds\":[\"ins-n2i7x483\"]}"
|
||||
|
||||
```
|
||||
Usage of ./TencentCloudClient:
|
||||
-key string
|
||||
accessKeyId (default "secretId")
|
||||
-o string
|
||||
operation: add、remove (default "add")
|
||||
-params string
|
||||
|
||||
AddBackendServers: [{"ServerId":"ServerId","Weight":"100","Type":"eni","ServerIp":"192.168.11.1"}]
|
||||
RemoveBackendServers: [{"ServerId":"ServerId","Weight":"100"}]
|
||||
(default "params")
|
||||
-reg string
|
||||
regionId: cn-hangzhou (default "regionId")
|
||||
-sec string
|
||||
accessSecret (default "secretKey")
|
||||
-t string
|
||||
target: b=backendServer (default "b")
|
||||
|
||||
```
|
||||
|
||||
146
pkg/common/ConstVar.go
Normal file
146
pkg/common/ConstVar.go
Normal file
@ -0,0 +1,146 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/anxpp/beego/logs"
|
||||
)
|
||||
|
||||
const (
|
||||
|
||||
//公用
|
||||
|
||||
//API版本号
|
||||
// API_V_NUM = "1"
|
||||
|
||||
//API密钥
|
||||
// API_SECRECT = "x63363eacf804b4394a120aea240fd9a"
|
||||
|
||||
//图片域名
|
||||
|
||||
PHOTO_URL_PREV = "https://photo-app.ddegame.cn/"
|
||||
|
||||
MEDIA_URL_PREV = "https://media-qiniu-app.ddegame.cn/"
|
||||
|
||||
//====== 三方key =======
|
||||
//NETEASE_IM_APPKEY = "a0671ecde01ef03928ccfd460c62d203"
|
||||
//NETEASE_IM_SECRET = "eb88916031ca"
|
||||
|
||||
//用户认证申请状态
|
||||
USER_CERTIFY_STATUS_INIT = "1" //已提交
|
||||
USER_CERTIFY_STATUS_SUCCESS = "2" //成功
|
||||
USER_CERTIFY_STATUS_INIT_FAIL = "3" //初始化失败
|
||||
USER_CERTIFY_STATUS_AUTH_FAIL = "4" //认证失败
|
||||
USER_CERTIFY_STATUS_REFUSE = "5" //拒绝
|
||||
|
||||
// 模块和页面ID
|
||||
|
||||
//用户管理
|
||||
MODULE_ID_USER_MANAGE = "1"
|
||||
//基础数据
|
||||
MODULE_ID_BASE_DATA = "4"
|
||||
//财务管理
|
||||
MODULE_ID_FIN_MANAGE = "7"
|
||||
//数据报表
|
||||
MODULE_ID_DATA_REPORT = "14"
|
||||
//聊天室管理
|
||||
MODULE_ID_ROOM_MANAGE = "20"
|
||||
//付款管理
|
||||
MODULE_ID_PAY_MANAGE = "100"
|
||||
//抽奖管理
|
||||
MODULE_ID_LUCK_MANAGE = "200"
|
||||
//技能管理
|
||||
MODULE_ID_SKILL_MANAGE = "300"
|
||||
//技能订单管理
|
||||
MODULE_ID_SKILL_ORDER_MANAGE = "400"
|
||||
//技能订单列表
|
||||
PAGE_ID_FIN_SKILL_ORDER_LIST = "401"
|
||||
|
||||
//用户列表
|
||||
PAGE_ID_USER_LIST = "2"
|
||||
//用户认证列表
|
||||
PAGE_ID_USER_AUTH_LIST = "3"
|
||||
//礼物列表
|
||||
PAGE_ID_GIFT_LIST = "5"
|
||||
//首页分类列表
|
||||
PAGE_ID_HOME_TAB_LIST = "6"
|
||||
//充值列表
|
||||
PAGE_ID_FIN_RECHARGE_LIST = "8"
|
||||
//提现列表
|
||||
PAGE_ID_FIN_WITHDRAW_LIST = "9"
|
||||
//兑换列表
|
||||
PAGE_ID_FIN_EXCHANGE_LIST = "10"
|
||||
//表情列表
|
||||
PAGE_ID_FIN_EMOJI_ORDER_LIST = "11"
|
||||
//守护订单列表
|
||||
PAGE_ID_FIN_GUARD_ORDER_LIST = "12"
|
||||
//打赏列表
|
||||
PAGE_ID_FIN_PRESENT_GIFT_LIST = "13"
|
||||
|
||||
//日报表
|
||||
PAGE_ID_DAY_REPORT = "15"
|
||||
//厅日流水报表
|
||||
PAGE_ID_DAY_ROOM_SALE_REPORT = "142"
|
||||
//实时厅流水报表
|
||||
PAGE_ID_TODAY_ROOM_SALE_RANK = "143"
|
||||
//厅费用排行
|
||||
PAGE_ID_TODAY_ROOM_MARKET_FEE_RANK = "144"
|
||||
|
||||
//聊天室列表
|
||||
PAGE_ID_CHATROOM_LIST = "21"
|
||||
//房主列表
|
||||
PAGE_ID_CHATROOM_OWNER_LIST = "22"
|
||||
//打赏列表
|
||||
PAGE_ID_FIN_OPERATION_DIAMOND_LIST = "24"
|
||||
//
|
||||
PAGE_ID_FILTER_USER_NO = "25"
|
||||
//付款单列表
|
||||
PAGE_ID_PAY_ORDER_LIST = "101"
|
||||
//客户列表
|
||||
PAGE_ID_PAY_CUSTOMER_LIST = "102"
|
||||
|
||||
//砸蛋列表
|
||||
PAGE_ID_HIT_EGG_LIST = "201"
|
||||
//方案列表
|
||||
PAGE_ID_SOLUTION_LIST_LIST = "202"
|
||||
//权益列表
|
||||
PAGE_ID_QUANYI_LIST_LIST = "203"
|
||||
//用户砸蛋汇总
|
||||
PAGE_ID_USER_HITEGG_SUMMARY = "204"
|
||||
|
||||
//技能申请列表
|
||||
PAGE_ID_SKILL_APPLY_LIST_LIST = "301"
|
||||
|
||||
//技能列表
|
||||
PAGE_ID_SKILL_LIST = "302"
|
||||
|
||||
//卖家列表
|
||||
PAGE_ID_SELLER_LIST = "303"
|
||||
|
||||
//SKU列表
|
||||
PAGE_ID_SKILL_SKU_LIST = "304"
|
||||
|
||||
//技能修改申请列表
|
||||
PAGE_ID_SKILL_EDIT_LIST = "305"
|
||||
|
||||
//技能价格列表
|
||||
PAGE_ID_SKILL_PRICE_LIST = "306"
|
||||
//技能订单列表
|
||||
PAGE_ID_SKILL_ORDER_LIST = "401"
|
||||
|
||||
// 代理订单类型 后台充值
|
||||
AGENT_DIAMOND_ORDER_TYPE_ADMIN_RECHARGE = "1"
|
||||
// 代理订单类型 上级转账
|
||||
AGENT_DIAMOND_ORDER_TYPE_UPER_TRANSFER = "2"
|
||||
|
||||
// 文本反垃圾类型 - 昵称检测
|
||||
RISK_TYPE_TEXT_NICKNAME = "nickname_detection"
|
||||
RISK_TYPE_TEXT_COMMENT = "comment_detection" //评论检测
|
||||
)
|
||||
|
||||
func LogJson(v interface{}) {
|
||||
b, _ := json.Marshal(v)
|
||||
logs.Info(string(b))
|
||||
}
|
||||
|
||||
const photoDomainUrl = "https://ddphoto.youkeya.cn"
|
||||
96
pkg/common/HyTools/HttpClient.go
Normal file
96
pkg/common/HyTools/HttpClient.go
Normal file
@ -0,0 +1,96 @@
|
||||
package HyTools
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// 调用POST请求
|
||||
func HttpPost(url string, body string) (remoteResponse string, err error) {
|
||||
|
||||
bodyReader := strings.NewReader(body)
|
||||
//application/x-www-form-urlencoded
|
||||
//application/json
|
||||
response, err1 := http.Post(url, "application/x-www-form-urlencoded", bodyReader)
|
||||
|
||||
if err1 != nil {
|
||||
err = err1
|
||||
return
|
||||
}
|
||||
defer response.Body.Close()
|
||||
|
||||
resBody, err2 := ioutil.ReadAll(response.Body)
|
||||
|
||||
if err2 != nil {
|
||||
err = err2
|
||||
return
|
||||
}
|
||||
|
||||
remoteResponse = string(resBody)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// 复杂http请求
|
||||
func HttpDo(httpMethod string, url string, headerMap map[string]string, rawBody string) (remoteResponse string, err error) {
|
||||
|
||||
client := &http.Client{}
|
||||
|
||||
req, err0 := http.NewRequest(httpMethod, url, strings.NewReader(rawBody))
|
||||
|
||||
if err0 != nil {
|
||||
err = err0
|
||||
return
|
||||
}
|
||||
|
||||
if len(headerMap) > 0 {
|
||||
for k, v := range headerMap {
|
||||
req.Header.Set(k, v)
|
||||
}
|
||||
}
|
||||
|
||||
resp, err1 := client.Do(req)
|
||||
|
||||
if err1 != nil {
|
||||
err = err1
|
||||
return
|
||||
}
|
||||
|
||||
defer resp.Body.Close()
|
||||
|
||||
body, err2 := ioutil.ReadAll(resp.Body)
|
||||
if err2 != nil {
|
||||
err = err2
|
||||
return
|
||||
}
|
||||
|
||||
remoteResponse = string(body)
|
||||
return
|
||||
|
||||
}
|
||||
|
||||
func HttpPostJson(url string, body string) (remoteResponse string, err error) {
|
||||
|
||||
bodyReader := strings.NewReader(body)
|
||||
//application/x-www-form-urlencoded
|
||||
//application/json
|
||||
response, err1 := http.Post(url, "application/json", bodyReader)
|
||||
|
||||
if err1 != nil {
|
||||
err = err1
|
||||
return
|
||||
}
|
||||
defer response.Body.Close()
|
||||
|
||||
resBody, err2 := ioutil.ReadAll(response.Body)
|
||||
|
||||
if err2 != nil {
|
||||
err = err2
|
||||
return
|
||||
}
|
||||
|
||||
remoteResponse = string(resBody)
|
||||
|
||||
return
|
||||
}
|
||||
40
pkg/common/HyTools/RandTools.go
Normal file
40
pkg/common/HyTools/RandTools.go
Normal file
@ -0,0 +1,40 @@
|
||||
package HyTools
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
"time"
|
||||
)
|
||||
|
||||
func RandInt64(min, max int64) int64 {
|
||||
if min >= max || min == 0 || max == 0 {
|
||||
return max
|
||||
}
|
||||
return rand.Int63n(max-min) + min
|
||||
}
|
||||
|
||||
// 获取随机数字字符串
|
||||
func GetRandNumber(l int) string {
|
||||
|
||||
str := "0123456789"
|
||||
bytes := []byte(str)
|
||||
result := []byte{}
|
||||
r := rand.New(rand.NewSource(time.Now().UnixNano()))
|
||||
for i := 0; i < l; i++ {
|
||||
result = append(result, bytes[r.Intn(len(bytes))])
|
||||
}
|
||||
return string(result)
|
||||
|
||||
}
|
||||
|
||||
// 生成随机字符串
|
||||
func GetRandomString(l int) string {
|
||||
|
||||
str := "0123456789abcdefghijklmnopqrstuvwxyz"
|
||||
bytes := []byte(str)
|
||||
result := []byte{}
|
||||
r := rand.New(rand.NewSource(time.Now().UnixNano()))
|
||||
for i := 0; i < l; i++ {
|
||||
result = append(result, bytes[r.Intn(len(bytes))])
|
||||
}
|
||||
return string(result)
|
||||
}
|
||||
146
pkg/common/HyTools/RsaUtil.go
Normal file
146
pkg/common/HyTools/RsaUtil.go
Normal file
@ -0,0 +1,146 @@
|
||||
package HyTools
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto"
|
||||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
"crypto/sha1"
|
||||
"crypto/x509"
|
||||
"encoding/base64"
|
||||
"encoding/pem"
|
||||
"errors"
|
||||
)
|
||||
|
||||
// RSA加密
|
||||
func RsaEncrypt(origData string, publicKey string) (string, error) {
|
||||
|
||||
block, _ := pem.Decode([]byte(publicKey)) //将密钥解析成公钥实例
|
||||
if block == nil {
|
||||
return "", errors.New("public key error")
|
||||
}
|
||||
|
||||
pubInterface, err := x509.ParsePKIXPublicKey(block.Bytes) //解析pem.Decode()返回的Block指针实例
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
pub := pubInterface.(*rsa.PublicKey)
|
||||
|
||||
partLen := pub.N.BitLen()/8 - 11
|
||||
|
||||
chunks := ByteSplit([]byte(origData), partLen)
|
||||
|
||||
buffer := bytes.NewBufferString("")
|
||||
|
||||
for _, chunk := range chunks {
|
||||
|
||||
bytes, err := rsa.EncryptPKCS1v15(rand.Reader, pub, chunk)
|
||||
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
buffer.Write(bytes)
|
||||
}
|
||||
|
||||
return base64.StdEncoding.EncodeToString(buffer.Bytes()), nil
|
||||
|
||||
}
|
||||
|
||||
// RSA解密
|
||||
func RsaDecrypt(ciphertext string, privateKey string) (string, error) {
|
||||
|
||||
block, _ := pem.Decode([]byte(privateKey))
|
||||
|
||||
if block == nil {
|
||||
|
||||
return "", errors.New("private key error!")
|
||||
}
|
||||
priv, err := x509.ParsePKCS1PrivateKey(block.Bytes)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
partLen := priv.N.BitLen() / 8
|
||||
|
||||
raw, err := base64.StdEncoding.DecodeString(ciphertext)
|
||||
|
||||
chunks := ByteSplit([]byte(raw), partLen)
|
||||
|
||||
buffer := bytes.NewBufferString("")
|
||||
|
||||
for _, chunk := range chunks {
|
||||
|
||||
decrypted, err := rsa.DecryptPKCS1v15(rand.Reader, priv, chunk)
|
||||
|
||||
if err != nil {
|
||||
|
||||
return "", err
|
||||
|
||||
}
|
||||
|
||||
buffer.Write(decrypted)
|
||||
|
||||
}
|
||||
|
||||
return buffer.String(), err
|
||||
}
|
||||
|
||||
// RSA SHA1加签
|
||||
func RsaSHA1Sign(data string, privateKey string) (string, error) {
|
||||
|
||||
block, _ := pem.Decode([]byte(privateKey))
|
||||
if block == nil {
|
||||
return "", errors.New("Sign private key decode error")
|
||||
}
|
||||
|
||||
prk8, err := x509.ParsePKCS1PrivateKey(block.Bytes)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
h := sha1.New()
|
||||
h.Write([]byte(data))
|
||||
hashed := h.Sum(nil)
|
||||
|
||||
sign, err := rsa.SignPKCS1v15(rand.Reader, prk8, crypto.SHA1, hashed)
|
||||
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return base64.StdEncoding.EncodeToString(sign), err
|
||||
|
||||
}
|
||||
|
||||
// RSA SHA1验签
|
||||
func RsaSHA1Verify(data string, sign string, publicKey string) error {
|
||||
|
||||
h := sha1.New()
|
||||
h.Write([]byte(data))
|
||||
hashed := h.Sum(nil)
|
||||
|
||||
decodedSign, err := base64.StdEncoding.DecodeString(sign)
|
||||
|
||||
if err != nil {
|
||||
|
||||
return err
|
||||
|
||||
}
|
||||
|
||||
block, _ := pem.Decode([]byte(publicKey))
|
||||
if block == nil {
|
||||
return errors.New("Sign public key decode error")
|
||||
}
|
||||
|
||||
pubInterface, err := x509.ParsePKIXPublicKey(block.Bytes) //解析pem.Decode()返回的Block指针实例
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
pub := pubInterface.(*rsa.PublicKey)
|
||||
|
||||
return rsa.VerifyPKCS1v15(pub, crypto.SHA1, hashed, decodedSign)
|
||||
|
||||
}
|
||||
30
pkg/common/HyTools/StringBuilder.go
Normal file
30
pkg/common/HyTools/StringBuilder.go
Normal file
@ -0,0 +1,30 @@
|
||||
package HyTools
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type StringBuilder struct {
|
||||
buf bytes.Buffer
|
||||
}
|
||||
|
||||
func NewStringBuilder() *StringBuilder {
|
||||
return &StringBuilder{buf: bytes.Buffer{}}
|
||||
}
|
||||
|
||||
func (this *StringBuilder) Append(obj interface{}) *StringBuilder {
|
||||
this.buf.WriteString(fmt.Sprintf("%v", obj))
|
||||
return this
|
||||
}
|
||||
|
||||
func (this *StringBuilder) ToString() string {
|
||||
return this.buf.String()
|
||||
}
|
||||
|
||||
// 字符串转int32
|
||||
func JsonStr(v interface{}) string {
|
||||
bys, _ := json.Marshal(v)
|
||||
return string(bys)
|
||||
}
|
||||
243
pkg/common/HyTools/TypeTools.go
Normal file
243
pkg/common/HyTools/TypeTools.go
Normal file
@ -0,0 +1,243 @@
|
||||
package HyTools
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/md5"
|
||||
"crypto/sha1"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"math"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// MD5加密
|
||||
func StringToMD5(waitMD5string string) string {
|
||||
|
||||
h := md5.New()
|
||||
h.Write([]byte(waitMD5string))
|
||||
cipherStr := h.Sum(nil)
|
||||
|
||||
result := hex.EncodeToString(cipherStr)
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// SHA1加密
|
||||
func StringToSHA1(waitMD5string string) string {
|
||||
|
||||
h := sha1.New()
|
||||
h.Write([]byte(waitMD5string))
|
||||
cipherStr := h.Sum(nil)
|
||||
|
||||
result := hex.EncodeToString(cipherStr)
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// 字符串转int64
|
||||
func StringToInt64(waitString string) int64 {
|
||||
|
||||
stringInt64, err := strconv.ParseInt(waitString, 10, 64)
|
||||
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
return stringInt64
|
||||
}
|
||||
|
||||
// 字符串转int32
|
||||
func StringToInt(waitString string) int {
|
||||
|
||||
stringInt, err := strconv.Atoi(waitString)
|
||||
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
return stringInt
|
||||
}
|
||||
|
||||
// 字符串转float64
|
||||
func StringToFloat64(waitString string) float64 {
|
||||
|
||||
stringInt64, err := strconv.ParseFloat(waitString, 64)
|
||||
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
return stringInt64
|
||||
}
|
||||
|
||||
// strconv.FormatFloat(float64, 'E', -1, 64)
|
||||
// float64转字符串
|
||||
func Float64ToString(waitFloat64 float64) string {
|
||||
|
||||
stringInt64 := strconv.FormatFloat(waitFloat64, 'f', -1, 64)
|
||||
|
||||
return stringInt64
|
||||
}
|
||||
|
||||
// 截取字符串
|
||||
func Substr(str string, start int, length int) string {
|
||||
rs := []rune(str)
|
||||
rl := len(rs)
|
||||
end := 0
|
||||
|
||||
if start < 0 {
|
||||
start = rl - 1 + start
|
||||
}
|
||||
end = start + length
|
||||
|
||||
if start > end {
|
||||
start, end = end, start
|
||||
}
|
||||
|
||||
if start < 0 {
|
||||
start = 0
|
||||
}
|
||||
if start > rl {
|
||||
start = rl
|
||||
}
|
||||
if end < 0 {
|
||||
end = 0
|
||||
}
|
||||
if end > rl {
|
||||
end = rl
|
||||
}
|
||||
|
||||
return string(rs[start:end])
|
||||
}
|
||||
|
||||
// map转html
|
||||
func MapToXML(mapData map[string]string) string {
|
||||
|
||||
if len(mapData) == 0 {
|
||||
return ""
|
||||
}
|
||||
sb := NewStringBuilder()
|
||||
sb.Append("<xml>")
|
||||
for key, val := range mapData {
|
||||
sb.Append("<" + key + ">")
|
||||
sb.Append(val)
|
||||
sb.Append("</" + key + ">")
|
||||
|
||||
}
|
||||
sb.Append("</xml>")
|
||||
|
||||
return sb.ToString()
|
||||
}
|
||||
|
||||
// 获取当前年周
|
||||
func GetCurrentYearWeek() string {
|
||||
|
||||
year, week := time.Now().ISOWeek()
|
||||
|
||||
return strconv.Itoa(year) + strconv.Itoa(week)
|
||||
}
|
||||
|
||||
// 字符串转time类型
|
||||
func StringToTime(dateString string) time.Time {
|
||||
|
||||
//获取本地location
|
||||
toBeCharge := dateString //待转化为时间戳的字符串 注意 这里的小时和分钟还要秒必须写 因为是跟着模板走的 修改模板的话也可以不写
|
||||
timeLayout := "2006-01-02 15:04:05" //转化所需模板
|
||||
loc, _ := time.LoadLocation("Local") //重要:获取时区
|
||||
theTime, _ := time.ParseInLocation(timeLayout, toBeCharge, loc) //使用模板在对应时区转化为time.time类型
|
||||
//sr := theTime.Unix() //转化为时间戳 类型是int64
|
||||
|
||||
//时间戳转日期
|
||||
//dataTimeStr := time.Unix(sr, 0).Format(timeLayout) //设置时间戳 使用模板格式化为日期字符串
|
||||
|
||||
return theTime
|
||||
}
|
||||
|
||||
// 判断数组是否包含某个元素
|
||||
func CheckStringIsInArray(arrayList []string, element string) bool {
|
||||
|
||||
if len(arrayList) == 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
isInArray := false
|
||||
for _, data := range arrayList {
|
||||
|
||||
if data == element {
|
||||
isInArray = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return isInArray
|
||||
}
|
||||
|
||||
// slice to 字符串
|
||||
func StringListToString(stringList []string, split string) string {
|
||||
if len(split) == 0 {
|
||||
split = ","
|
||||
}
|
||||
return strings.Replace(strings.Trim(fmt.Sprint(stringList), "[]"), " ", split, -1)
|
||||
}
|
||||
|
||||
// map 转 url参数
|
||||
func MapToUrlParams(mapData map[string]string) string {
|
||||
|
||||
mapLen := len(mapData)
|
||||
if mapLen == 0 {
|
||||
return ""
|
||||
}
|
||||
sb := NewStringBuilder()
|
||||
|
||||
i := 0
|
||||
for k, v := range mapData {
|
||||
|
||||
sb.Append(k + "=" + v)
|
||||
if i < mapLen-1 {
|
||||
sb.Append("&")
|
||||
}
|
||||
|
||||
i++
|
||||
}
|
||||
return sb.ToString()
|
||||
}
|
||||
|
||||
// []byte 合并
|
||||
func BytesCombine(pBytes ...[]byte) []byte {
|
||||
return bytes.Join(pBytes, []byte(""))
|
||||
}
|
||||
|
||||
// 获取当前UTC时间 秒数
|
||||
func GetCurrentUtcTimeSecond() int64 {
|
||||
return time.Now().UTC().Unix()
|
||||
}
|
||||
|
||||
// byte数组分组
|
||||
func ByteSplit(buf []byte, lim int) [][]byte {
|
||||
|
||||
var chunk []byte
|
||||
|
||||
chunks := make([][]byte, 0, len(buf)/lim+1)
|
||||
|
||||
for len(buf) >= lim {
|
||||
|
||||
chunk, buf = buf[:lim], buf[lim:]
|
||||
|
||||
chunks = append(chunks, chunk)
|
||||
|
||||
}
|
||||
|
||||
bufLen := len(buf)
|
||||
if bufLen > 0 {
|
||||
|
||||
chunks = append(chunks, buf[:bufLen])
|
||||
|
||||
}
|
||||
|
||||
return chunks
|
||||
|
||||
}
|
||||
|
||||
func Float64ToIntRound(f float64) int {
|
||||
return int(math.Round(f))
|
||||
}
|
||||
111
pkg/common/HyTools/Uuid.go
Normal file
111
pkg/common/HyTools/Uuid.go
Normal file
@ -0,0 +1,111 @@
|
||||
package HyTools
|
||||
|
||||
import (
|
||||
crand "crypto/rand"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
mrand "math/rand"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
// seeded indicates if math/rand has been seeded
|
||||
var seeded bool = false
|
||||
|
||||
// uuidRegex matches the UUID string
|
||||
var uuidRegex *regexp.Regexp = regexp.MustCompile(`^\{?([a-fA-F0-9]{8})-?([a-fA-F0-9]{4})-?([a-fA-F0-9]{4})-?([a-fA-F0-9]{4})-?([a-fA-F0-9]{12})\}?$`)
|
||||
|
||||
// UUID type.
|
||||
type UUID [16]byte
|
||||
|
||||
// Hex returns a hex string representation of the UUID in xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx format.
|
||||
func (this UUID) Hex() string {
|
||||
|
||||
x := [16]byte(this)
|
||||
|
||||
return fmt.Sprintf("%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
|
||||
x[0], x[1], x[2], x[3], x[4],
|
||||
x[5], x[6],
|
||||
x[7], x[8],
|
||||
x[9], x[10], x[11], x[12], x[13], x[14], x[15])
|
||||
}
|
||||
|
||||
// Rand generates a new version 4 UUID.
|
||||
func Rand() UUID {
|
||||
var x [16]byte
|
||||
randBytes(x[:])
|
||||
x[6] = (x[6] & 0x0F) | 0x40
|
||||
x[8] = (x[8] & 0x3F) | 0x80
|
||||
return x
|
||||
}
|
||||
|
||||
// FromStr returns a UUID based on a string.
|
||||
// The string could be in the following format:
|
||||
//
|
||||
// xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
|
||||
//
|
||||
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
//
|
||||
// {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}
|
||||
//
|
||||
// If the string is not in one of these formats, it'll return an error.
|
||||
func FromStr(s string) (id UUID, err error) {
|
||||
if s == "" {
|
||||
err = errors.New("Empty string")
|
||||
return
|
||||
}
|
||||
|
||||
parts := uuidRegex.FindStringSubmatch(s)
|
||||
if parts == nil {
|
||||
err = errors.New("Invalid string format")
|
||||
return
|
||||
}
|
||||
|
||||
var array [16]byte
|
||||
slice, _ := hex.DecodeString(strings.Join(parts[1:], ""))
|
||||
copy(array[:], slice)
|
||||
id = array
|
||||
return
|
||||
}
|
||||
|
||||
// MustFromStr behaves similarly to FromStr except that it'll panic instead of
|
||||
// returning an error.
|
||||
func MustFromStr(s string) UUID {
|
||||
id, err := FromStr(s)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return id
|
||||
}
|
||||
|
||||
// randBytes uses crypto random to get random numbers. If fails then it uses math random.
|
||||
func randBytes(x []byte) {
|
||||
|
||||
length := len(x)
|
||||
n, err := crand.Read(x)
|
||||
|
||||
if n != length || err != nil {
|
||||
if !seeded {
|
||||
mrand.Seed(time.Now().UnixNano())
|
||||
}
|
||||
|
||||
for length > 0 {
|
||||
length--
|
||||
x[length] = byte(mrand.Int31n(256))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func GetUUID() string {
|
||||
|
||||
u7, _ := uuid.NewV7()
|
||||
return strings.ReplaceAll(u7.String(), "-", "")
|
||||
// var uuid UUID = Rand()
|
||||
|
||||
// return uuid.Hex()
|
||||
|
||||
}
|
||||
1352
pkg/common/app_const.go
Normal file
1352
pkg/common/app_const.go
Normal file
File diff suppressed because it is too large
Load Diff
94
pkg/common/es/document/user.go
Normal file
94
pkg/common/es/document/user.go
Normal file
@ -0,0 +1,94 @@
|
||||
package document
|
||||
|
||||
type User struct {
|
||||
Id string
|
||||
Mobile string
|
||||
RegionCode string
|
||||
NickName string
|
||||
Salt string
|
||||
Password string
|
||||
Status string
|
||||
Avatar string
|
||||
Gender string
|
||||
Birthday string
|
||||
WxUnionId string
|
||||
QqOpenId string
|
||||
MarketChannel string
|
||||
CreateTime string
|
||||
IsActive string
|
||||
ActiveTime string
|
||||
SignupSource string
|
||||
SignupDevicePlatform string
|
||||
SignupDeviceUdid string
|
||||
IdNo string
|
||||
IsAuth string
|
||||
TrueName string
|
||||
Sign string
|
||||
ViewFlag string
|
||||
VideoUrl string
|
||||
School string
|
||||
UserNo string
|
||||
BankName string
|
||||
BankUserName string
|
||||
BankBranchName string
|
||||
BankCardNo string
|
||||
AuthFailReason string
|
||||
AlipayAccount string
|
||||
WellNoIcon string
|
||||
}
|
||||
|
||||
//字符串: text keyword
|
||||
//整数 : byte, short, integer, long
|
||||
//浮点数: float, double
|
||||
//布尔型: boolean
|
||||
//日期: date
|
||||
var UserIndex = map[string]interface{}{
|
||||
"settings": map[string]interface{}{"number_of_shards": 5, "number_of_replicas": 1},
|
||||
"mappings": map[string]interface{}{
|
||||
"properties": map[string]interface{}{
|
||||
"ActiveTime": map[string]string{"type": "date", "format": "yyyy-MM-dd HH:mm:ssZ||yyyy-MM-dd HH:mm:ss.SSSZ||yyyy-MM-ddZ||epoch_millis||epoch_second"},
|
||||
"AlipayAccount": map[string]string{"type": "keyword"},
|
||||
"AuthFailReason": map[string]string{"type": "text", "analyzer": "ik_max_word"},
|
||||
"Avatar": map[string]string{"type": "text", "analyzer": "ik_max_word"},
|
||||
"BankBranchName": map[string]string{"type": "keyword"},
|
||||
"BankCardNo": map[string]string{"type": "keyword"},
|
||||
"BankName": map[string]string{"type": "text"},
|
||||
"BankUserName": map[string]string{"type": "text"},
|
||||
"Birthday": map[string]string{"type": "date", "format": "yyyy-MM-dd HH:mm:ssZ||yyyy-MM-dd HH:mm:ss.SSSZ||yyyy-MM-ddZ||epoch_millis||epoch_second"},
|
||||
"CreateTime": map[string]string{"type": "date", "format": "yyyy-MM-dd HH:mm:ssZ||yyyy-MM-dd HH:mm:ss.SSSZ||yyyy-MM-ddZ||epoch_millis||epoch_second"},
|
||||
"Gender": map[string]string{"type": "keyword"},
|
||||
"Id": map[string]string{"type": "keyword"},
|
||||
"IdNo": map[string]string{"type": "keyword"},
|
||||
"IsActive": map[string]string{"type": "keyword"},
|
||||
"IsAuth": map[string]string{"type": "keyword"},
|
||||
"MarketChannel": map[string]string{"type": "keyword"},
|
||||
"Mobile": map[string]string{"type": "keyword"},
|
||||
"NickName": map[string]string{"type": "text", "analyzer": "ik_max_word"},
|
||||
"QqOpenId": map[string]string{"type": "keyword"},
|
||||
"RegionCode": map[string]string{"type": "keyword"},
|
||||
"Salt": map[string]string{"type": "keyword"},
|
||||
"School": map[string]string{"type": "text", "analyzer": "ik_max_word"},
|
||||
"Sign": map[string]string{"type": "text", "analyzer": "ik_max_word"},
|
||||
"SignupDevicePlatform": map[string]string{"type": "text", "analyzer": "ik_max_word"},
|
||||
"SignupDeviceUdid": map[string]string{"type": "keyword"},
|
||||
"SignupSource": map[string]string{"type": "text", "analyzer": "ik_max_word"},
|
||||
"Status": map[string]string{"type": "keyword"},
|
||||
"TrueName": map[string]string{"type": "text", "analyzer": "ik_max_word"},
|
||||
"UserNo": map[string]string{"type": "keyword"},
|
||||
"VideoUrl": map[string]string{"type": "text", "analyzer": "ik_max_word"},
|
||||
"ViewFlag": map[string]string{"type": "keyword"},
|
||||
"WellNoIcon": map[string]string{"type": "keyword"},
|
||||
"WxUnionId": map[string]string{"type": "keyword"},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
var MessageIndex = map[string]interface{}{
|
||||
"settings": map[string]interface{}{"number_of_shards": 5, "number_of_replicas": 1},
|
||||
"mappings": map[string]interface{}{
|
||||
"properties": map[string]interface{}{
|
||||
"id": map[string]string{"type": "keyword"},
|
||||
"curTime": map[string]string{"type": "date", "format": "yyyy-MM-dd HH:mm:ssZ||yyyy-MM-dd HH:mm:ss.SSSZ||yyyy-MM-ddZ||epoch_millis||epoch_second"},
|
||||
},
|
||||
},
|
||||
}
|
||||
261
pkg/common/es/es_client.go
Normal file
261
pkg/common/es/es_client.go
Normal file
@ -0,0 +1,261 @@
|
||||
package ess
|
||||
|
||||
import (
|
||||
"servicebase/pkg/common/es/document"
|
||||
"servicebase/pkg/common/messages"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"reflect"
|
||||
"time"
|
||||
|
||||
"github.com/anxpp/beego/logs"
|
||||
"github.com/olivere/elastic/v7"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
var client *elastic.Client
|
||||
|
||||
type EsClient struct {
|
||||
}
|
||||
|
||||
func Init() {
|
||||
index := messages.TagIndex(string(messages.EventTagUser))
|
||||
client = _connect()
|
||||
exists, e := client.IndexExists(index).Do(context.Background())
|
||||
if e != nil {
|
||||
logs.Error("IndexExists ", index, " error: ", e.Error())
|
||||
return
|
||||
}
|
||||
if !exists {
|
||||
logs.Info("es user not exist")
|
||||
createIndex, e := client.CreateIndex(index).BodyJson(document.UserIndex).Do(context.Background())
|
||||
if e != nil {
|
||||
logs.Error("IndexCreate ", index, " error: ", e.Error())
|
||||
return
|
||||
}
|
||||
if !createIndex.Acknowledged {
|
||||
}
|
||||
}
|
||||
indexMessage := messages.TagIndex(string(messages.EventTagMessage))
|
||||
existsMessage, e := client.IndexExists(indexMessage).Do(context.Background())
|
||||
if e != nil {
|
||||
logs.Error("IndexExists indexMessage", index, " error: ", e.Error())
|
||||
return
|
||||
}
|
||||
if !existsMessage {
|
||||
logs.Info("es indexMessage not exist")
|
||||
createIndex, e := client.CreateIndex(indexMessage).BodyJson(document.MessageIndex).Do(context.Background())
|
||||
if e != nil {
|
||||
logs.Error("IndexCreate ", indexMessage, " error: ", e.Error())
|
||||
return
|
||||
}
|
||||
if !createIndex.Acknowledged {
|
||||
}
|
||||
}
|
||||
logs.Info("init elasticsearch finish")
|
||||
}
|
||||
|
||||
func _connect() (c *elastic.Client) {
|
||||
c, e := elastic.NewSimpleClient(
|
||||
elastic.SetHealthcheck(true),
|
||||
elastic.SetHealthcheckInterval(10*time.Second),
|
||||
elastic.SetURL(viper.GetString("es.default.addr")),
|
||||
// elastic.SetBasicAuth(beego.AppConfig.String("es_username"), beego.AppConfig.String("es_password")),
|
||||
)
|
||||
if e != nil {
|
||||
logs.Error("NewClient_error: ", e.Error())
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
// 创建记录
|
||||
func (*EsClient) Create(index, id string, model interface{}) (body string, success bool, msg string) {
|
||||
client := _connect()
|
||||
_, e := client.Index().Index(index).Id(id).BodyJson(model).Do(context.Background())
|
||||
if e != nil {
|
||||
success = false
|
||||
msg = e.Error()
|
||||
b, _ := json.Marshal(model)
|
||||
logs.Error("Document Create Error: ", e.Error(), " document: ", string(b), index, id)
|
||||
return
|
||||
}
|
||||
success = true
|
||||
return
|
||||
}
|
||||
|
||||
// 判断存在
|
||||
func (*EsClient) Exists(index, id string) (exists, success bool, msg string, e error) {
|
||||
client := _connect()
|
||||
exists, e = client.Exists().Index(index).Type("_doc").Id(id).Do(context.Background())
|
||||
if e != nil {
|
||||
success = false
|
||||
msg = e.Error()
|
||||
logs.Error("Id Exists Error: ", e.Error(), " id: ", id)
|
||||
return
|
||||
}
|
||||
success = true
|
||||
return
|
||||
}
|
||||
|
||||
// 更新记录
|
||||
func (*EsClient) Update(index, id string, model interface{}) (body string, success bool, msg string) {
|
||||
client := _connect()
|
||||
_, e := client.Update().Index(index).Id(id).Doc(model).Do(context.Background())
|
||||
if e != nil {
|
||||
success = false
|
||||
msg = e.Error()
|
||||
return
|
||||
}
|
||||
success = true
|
||||
return
|
||||
}
|
||||
|
||||
// 搜索
|
||||
func (*EsClient) Search(index string, key string, fields ...string) (body []interface{}, success bool, msg string) {
|
||||
client := _connect()
|
||||
logs.Info("ES Search index =", index, " key =", key, " fields =", fields)
|
||||
var list []*elastic.WildcardQuery
|
||||
for _, field := range fields {
|
||||
list = append(list, elastic.NewWildcardQuery(field, key))
|
||||
}
|
||||
s := client.Search().Index(index)
|
||||
for _, query := range list {
|
||||
s = s.Query(query)
|
||||
}
|
||||
res, e := s.From(0).Size(20).Pretty(true).Do(context.Background())
|
||||
if e != nil {
|
||||
success = false
|
||||
msg = e.Error()
|
||||
return
|
||||
}
|
||||
logs.Info(res.Status)
|
||||
logs.Info(res.Hits.TotalHits)
|
||||
var item document.User
|
||||
for _, item := range res.Each(reflect.TypeOf(item)) {
|
||||
if t, ok := item.(document.User); ok {
|
||||
body = append(body, t)
|
||||
}
|
||||
}
|
||||
//if res.Hits.TotalHits.Value > 0 {
|
||||
// for _, hit := range res.Hits.Hits {
|
||||
// var t document.User
|
||||
// _ := json.Unmarshal(hit.Source, &t)
|
||||
// body = append(body, t)
|
||||
// }
|
||||
//}
|
||||
return
|
||||
}
|
||||
|
||||
type ESFilter struct {
|
||||
Queries []ESQuery
|
||||
BoolMustInShouldQueries [][]ESQuery
|
||||
Sort ESSort
|
||||
}
|
||||
|
||||
type ESQuery struct {
|
||||
Key string
|
||||
Value string
|
||||
Type string
|
||||
}
|
||||
|
||||
type ESSort struct {
|
||||
Field string
|
||||
Ascending bool
|
||||
}
|
||||
|
||||
// 搜索消息
|
||||
func (*EsClient) SearchMulti(index string, filter ESFilter, page, size int) (result interface{}, success bool, msg string) {
|
||||
client := _connect()
|
||||
var list []elastic.Query
|
||||
for _, item := range filter.Queries {
|
||||
switch item.Type {
|
||||
case "match":
|
||||
list = append(list, elastic.NewMatchQuery(item.Key, item.Value))
|
||||
case "multi_match":
|
||||
list = append(list, elastic.NewMultiMatchQuery(item.Value).Type("best_fields").Lenient(true))
|
||||
case "range_gte":
|
||||
list = append(list, elastic.NewRangeQuery(item.Key).Gte(item.Value))
|
||||
case "range_lte":
|
||||
list = append(list, elastic.NewRangeQuery(item.Key).Lte(item.Value))
|
||||
}
|
||||
}
|
||||
if len(filter.BoolMustInShouldQueries) > 0 {
|
||||
BQ := elastic.NewBoolQuery()
|
||||
var bqList []elastic.Query
|
||||
for _, bq := range filter.BoolMustInShouldQueries {
|
||||
var listBq []elastic.Query
|
||||
boolQuery := elastic.NewBoolQuery()
|
||||
for _, item := range bq {
|
||||
switch item.Type {
|
||||
case "match":
|
||||
listBq = append(listBq, elastic.NewMatchQuery(item.Key, item.Value))
|
||||
case "multi_match":
|
||||
listBq = append(listBq, elastic.NewMultiMatchQuery(item.Value).Type("best_fields").Lenient(true))
|
||||
case "range_gte":
|
||||
listBq = append(listBq, elastic.NewRangeQuery(item.Key).Gte(item.Value))
|
||||
case "range_lte":
|
||||
listBq = append(listBq, elastic.NewRangeQuery(item.Key).Lte(item.Value))
|
||||
}
|
||||
}
|
||||
boolQuery.Must(listBq...)
|
||||
bqList = append(bqList, boolQuery)
|
||||
}
|
||||
BQ.Should(bqList...)
|
||||
list = append(list, BQ)
|
||||
}
|
||||
query := elastic.NewBoolQuery().Filter(list...)
|
||||
//logs.Info(len(list))
|
||||
//a1, _ := query.Source()
|
||||
//a2, _ := json.MarshalIndent(a1, "", " ")
|
||||
//logs.Info(string(a2))
|
||||
s := client.Search().Index(index).Query(query)
|
||||
if len(filter.Sort.Field) > 0 {
|
||||
s = s.Sort(filter.Sort.Field, filter.Sort.Ascending)
|
||||
}
|
||||
res, e := s.From(page * size).Size(size).Pretty(false).Do(context.Background())
|
||||
if e != nil {
|
||||
return
|
||||
}
|
||||
var body []interface{}
|
||||
for _, item := range res.Hits.Hits {
|
||||
b, _ := item.Source.MarshalJSON()
|
||||
m := make(map[string]interface{})
|
||||
_ = json.Unmarshal(b, &m)
|
||||
body = append(body, m)
|
||||
}
|
||||
result = map[string]interface{}{
|
||||
"Status": res.Status,
|
||||
"Total": res.Hits.TotalHits,
|
||||
"List": body,
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// 搜索
|
||||
func (*EsClient) QueryString(page, size int, index string, key string, fields ...string) (list []document.User, count int64, success bool, msg string) {
|
||||
client := _connect()
|
||||
logs.Info("ES QueryString index =", index, " key =", key, " fields =", fields)
|
||||
query := elastic.NewQueryStringQuery(key)
|
||||
for _, field := range fields {
|
||||
query.Field(field)
|
||||
}
|
||||
query.AnalyzeWildcard(false)
|
||||
s := client.Search().Index(index)
|
||||
s = s.Query(query)
|
||||
s = s.Sort("_score", false)
|
||||
res, e := s.From(page * size).Size(size).Pretty(true).Do(context.Background())
|
||||
if e != nil {
|
||||
success = false
|
||||
msg = e.Error()
|
||||
return
|
||||
}
|
||||
count = res.TotalHits()
|
||||
var user document.User
|
||||
for _, item := range res.Each(reflect.TypeOf(user)) {
|
||||
if t, ok := item.(document.User); ok {
|
||||
list = append(list, t)
|
||||
}
|
||||
}
|
||||
success = true
|
||||
return
|
||||
}
|
||||
81
pkg/common/es/es_client_test.go
Normal file
81
pkg/common/es/es_client_test.go
Normal file
@ -0,0 +1,81 @@
|
||||
package ess
|
||||
|
||||
import (
|
||||
"servicebase/pkg/common/messages"
|
||||
"context"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/anxpp/beego/logs"
|
||||
"github.com/olivere/elastic/v7"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
func TestClient(t *testing.T) {
|
||||
Init()
|
||||
}
|
||||
|
||||
func TestClientCreateUser(t *testing.T) {
|
||||
//for _, item := range models.LogUserRegisterAll() {
|
||||
// cli := EsClient{}
|
||||
// _, success, msg := cli.Create("test_user_register", item.Id, item)
|
||||
// if !success {
|
||||
// logs.Error(msg)
|
||||
// }
|
||||
//}
|
||||
}
|
||||
|
||||
func TestClientSearch(t *testing.T) {
|
||||
}
|
||||
|
||||
func _testConnect() (c *elastic.Client) {
|
||||
c, e := elastic.NewSimpleClient(
|
||||
elastic.SetHealthcheck(true),
|
||||
elastic.SetHealthcheckInterval(10*time.Second),
|
||||
// elastic.SetURL("http://47.97.157.234:9200"),
|
||||
elastic.SetURL(viper.GetString("es.default.addr")),
|
||||
// elastic.SetBasicAuth(beego.AppConfig.String("es_username"), beego.AppConfig.String("es_password")),
|
||||
)
|
||||
if e != nil {
|
||||
logs.Error("NewClient_error: ", e.Error())
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
func TestClientNew(t *testing.T) {
|
||||
var client EsClient
|
||||
client.Create("es_index_message", "003", map[string]interface{}{
|
||||
"id": "003",
|
||||
"curTime": 1440570500855,
|
||||
"f1": 1234,
|
||||
"f2": "22222",
|
||||
"f3": "22222",
|
||||
"f4": "22222",
|
||||
"f5": "22222",
|
||||
"f6": "2020-08-09 23:37:00",
|
||||
})
|
||||
}
|
||||
|
||||
func TestSearchMessage(t *testing.T) {
|
||||
index := messages.TagIndex(string(messages.EventTagMessage))
|
||||
client := _testConnect()
|
||||
var list []elastic.Query
|
||||
list = append(list, elastic.NewWildcardQuery("eventType", "1"))
|
||||
list = append(list, elastic.NewMatchQuery("msgType", "TEXT"))
|
||||
s := client.Search().Index(index)
|
||||
for _, query := range list {
|
||||
s = s.Query(query)
|
||||
}
|
||||
res, e := s.From(0).Size(20).Pretty(true).Do(context.Background())
|
||||
if e != nil {
|
||||
return
|
||||
}
|
||||
logs.Info(res.Status)
|
||||
logs.Info(res.Hits.TotalHits)
|
||||
logs.Info(len(res.Hits.Hits))
|
||||
for i, item := range res.Hits.Hits {
|
||||
b, _ := item.Source.MarshalJSON()
|
||||
logs.Info(i, string(b))
|
||||
}
|
||||
time.Sleep(time.Second * 3)
|
||||
}
|
||||
25
pkg/common/http/dto/ChatRoomDTO.go
Normal file
25
pkg/common/http/dto/ChatRoomDTO.go
Normal file
@ -0,0 +1,25 @@
|
||||
package dto
|
||||
|
||||
type ChatRoomModelDTO struct {
|
||||
Id string
|
||||
OwnerUserId string
|
||||
RoomNo string
|
||||
RoomName string
|
||||
MessageRoomId string
|
||||
TabId string //分类ID
|
||||
TemplateId string
|
||||
CreateTime string
|
||||
Status string
|
||||
OpenTime string
|
||||
RoomPwd string
|
||||
MaxMemberCount string
|
||||
IsHot string
|
||||
RobotCount string
|
||||
RoomTagIcon string
|
||||
GuestCanUseEmoji string
|
||||
SendMessageTimeGap string //发送消息间隔
|
||||
UpSeatType string //1=排麦 2=自由麦
|
||||
AudioQualityLevel string //音质等级 1=正常 2=高音质 3=超高音质
|
||||
ViewSkewer string //是否显示福签 1=显示 0=不显示
|
||||
IsViewHitegg string // 是否显示砸蛋
|
||||
}
|
||||
5
pkg/common/http/dto/RequestDTO.go
Normal file
5
pkg/common/http/dto/RequestDTO.go
Normal file
@ -0,0 +1,5 @@
|
||||
package dto
|
||||
|
||||
type RequestDTO struct {
|
||||
Token string
|
||||
}
|
||||
17
pkg/common/http/dto/UserDTO.go
Normal file
17
pkg/common/http/dto/UserDTO.go
Normal file
@ -0,0 +1,17 @@
|
||||
package dto
|
||||
|
||||
type UserDTO struct {
|
||||
UserId string
|
||||
UserNo string
|
||||
NickName string
|
||||
Avatar string
|
||||
Gender string
|
||||
BirthDay string
|
||||
VipLevel string
|
||||
VipExp string
|
||||
IsAuth string
|
||||
Status string
|
||||
TrueName string
|
||||
Mobile string
|
||||
AvatarDecoration string //头饰
|
||||
}
|
||||
7
pkg/common/http/dto/UserInviteSummaryDTO.go
Normal file
7
pkg/common/http/dto/UserInviteSummaryDTO.go
Normal file
@ -0,0 +1,7 @@
|
||||
package dto
|
||||
|
||||
type UserInviteSummaryDTO struct {
|
||||
UserId string
|
||||
InviteDiamond string
|
||||
InviteUserCount string
|
||||
}
|
||||
51
pkg/common/http/response/Activity.go
Normal file
51
pkg/common/http/response/Activity.go
Normal file
@ -0,0 +1,51 @@
|
||||
package response
|
||||
|
||||
import "servicebase/pkg/common/http/dto"
|
||||
|
||||
type CommonResponse struct {
|
||||
Code string
|
||||
Result interface{}
|
||||
Msg string
|
||||
}
|
||||
|
||||
// 用户信息
|
||||
type UserInfoResponse struct {
|
||||
Code string
|
||||
Result dto.UserDTO
|
||||
Msg string
|
||||
}
|
||||
|
||||
//获取用户邀请汇总数据返回
|
||||
type UserInviteSummaryResponse struct {
|
||||
Code string
|
||||
Result dto.UserInviteSummaryDTO
|
||||
Msg string
|
||||
}
|
||||
|
||||
func Success(data interface{}) (res CommonResponse) {
|
||||
res.Code = "6000"
|
||||
res.Result = data
|
||||
return
|
||||
}
|
||||
|
||||
func Page(data interface{}, count int64) (res CommonResponse) {
|
||||
res.Code = "6000"
|
||||
res.Result = map[string]interface{}{
|
||||
"list": data,
|
||||
"count": count,
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func Failed(msg string) (res CommonResponse) {
|
||||
res.Code = "8020"
|
||||
res.Msg = msg
|
||||
return
|
||||
}
|
||||
|
||||
func Gen(code, msg string, result interface{}) (res CommonResponse) {
|
||||
res.Code = code
|
||||
res.Msg = msg
|
||||
res.Result = result
|
||||
return
|
||||
}
|
||||
12
pkg/common/messages/active_message.go
Normal file
12
pkg/common/messages/active_message.go
Normal file
@ -0,0 +1,12 @@
|
||||
package messages
|
||||
|
||||
// 活跃消息
|
||||
type Active struct {
|
||||
MessageId string
|
||||
UserId string //用户ID
|
||||
DeviceId string //设备ID
|
||||
ActiveTime string //活跃的平台
|
||||
ActivePlatform string //活跃的平台
|
||||
ActiveDeviceModel string //活跃的设备型号
|
||||
ActiveIp string //活跃的IP
|
||||
}
|
||||
26
pkg/common/messages/error_message.go
Normal file
26
pkg/common/messages/error_message.go
Normal file
@ -0,0 +1,26 @@
|
||||
package messages
|
||||
|
||||
// 错误消息(补偿)
|
||||
type Error struct {
|
||||
MessageId string
|
||||
Code string // 错误代码
|
||||
Content string // 错误内容(json)
|
||||
Tag ErrorTag // 消息标签:auto=自动处理 manual=手动处理 auto_to_manual=自动转手动
|
||||
}
|
||||
|
||||
type ErrorTag string
|
||||
|
||||
const (
|
||||
Auto ErrorTag = "AUTO"
|
||||
Manual ErrorTag = "MANUAL"
|
||||
AutoToManual ErrorTag = "AUTO_TO_MANUAL"
|
||||
)
|
||||
|
||||
type ErrorState string
|
||||
|
||||
const (
|
||||
ErrorCreate ErrorState = "CREATED"
|
||||
ErrorSuccess ErrorState = "SUCCESS"
|
||||
ErrorFailed ErrorState = "FAILED"
|
||||
ErrorReSuccess ErrorState = "RE_SUCCESS"
|
||||
)
|
||||
49
pkg/common/messages/event_message.go
Normal file
49
pkg/common/messages/event_message.go
Normal file
@ -0,0 +1,49 @@
|
||||
package messages
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
// 事件
|
||||
type Event struct {
|
||||
MessageId string
|
||||
Tag EventTag // 消息标签:EventTagUser=用户
|
||||
Flag EventFlag // 消息标签:EventFlagCreate=创建 EventFlagUpdate=更新
|
||||
EventId string // 事件ID
|
||||
EventContent interface{} // 事件内容
|
||||
}
|
||||
|
||||
type EventTag string
|
||||
|
||||
const (
|
||||
EventTagUser EventTag = "user"
|
||||
EventTagRoomInto EventTag = "into_room"
|
||||
EventTagMessage EventTag = "message"
|
||||
)
|
||||
|
||||
func TagIndex(key string) string {
|
||||
switch key {
|
||||
case string(EventTagUser):
|
||||
return viper.GetString("es.default.indexUser")
|
||||
case string(EventTagMessage):
|
||||
return viper.GetString("es.default.indexMessage")
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
type EventFlag string
|
||||
|
||||
const (
|
||||
EventFlagSave EventFlag = "save"
|
||||
EventFlagCreate EventFlag = "create"
|
||||
EventFlagUpdate EventFlag = "update"
|
||||
EventFlagDelete EventFlag = "delete"
|
||||
)
|
||||
|
||||
func (message *Event) ToJson() string {
|
||||
b, _ := json.Marshal(message)
|
||||
return string(b)
|
||||
}
|
||||
12
pkg/common/messages/register_message.go
Normal file
12
pkg/common/messages/register_message.go
Normal file
@ -0,0 +1,12 @@
|
||||
package messages
|
||||
|
||||
// 注册消息
|
||||
type Register struct {
|
||||
MessageId string
|
||||
UserId string //用户ID
|
||||
DeviceId string //设备ID
|
||||
RegisterTime string //注册时间
|
||||
ChannelCode string //渠道代码
|
||||
Ip string //ip
|
||||
Platform string //平台
|
||||
}
|
||||
98
pkg/common/messages/transaction_message.go
Normal file
98
pkg/common/messages/transaction_message.go
Normal file
@ -0,0 +1,98 @@
|
||||
package messages
|
||||
|
||||
// 交易消息
|
||||
type Transaction struct {
|
||||
MessageId string
|
||||
FromUserId string //发起用户ID
|
||||
FromCurrency TransactionCurrencyEnum //扣款类型
|
||||
FromAmount string //扣款数量
|
||||
FromPlatform string //扣款所在平台
|
||||
ToUserId string //接收用户
|
||||
ToCurrency TransactionCurrencyEnum //接收类型
|
||||
ToAmount string //接收数量
|
||||
TransactionRate string //交易抽成
|
||||
TransactionState TransactionStateEnum //交易状态
|
||||
TransactionType TransactionTypeEnum //充值、打赏、购买表情、购买守护、兑换、砸蛋、提现、订单等
|
||||
TransactionId string //充值ID、打赏ID、购买表情ID、购买守护ID、兑换ID、砸蛋ID、提现ID、订单ID等
|
||||
TransactionCreateTime string //交易创建时间
|
||||
TransactionCompleteTime string //交易完成时间
|
||||
TransactionSubjectId string //充值为产品ID、打赏为房间ID、购买表情为表情ID、购买守护为房间ID、兑换为配置ID、砸蛋为配置ID、提现为配置ID、订单为品类ID
|
||||
TransactionCode TransactionCodeEnum //充值为充值渠道(支付宝H5、支付宝App、微信、运营赠送等)、打赏为打赏类型(单个、批量)、购买表情为空、购买守护为守护类型、兑换为空、砸蛋为中奖等级、提现为银行名称、订单为空
|
||||
TransactionAmount string //交易金额(单位为扣款类型)
|
||||
TransactionAmountCoupon string //交易优惠金额(单位为扣款类型)
|
||||
TransactionAmountCouponId string //交易优惠凭证ID
|
||||
TransactionAmountPay string //交易实际支付金额(单位为扣款类型)
|
||||
GuildId string //俱乐部ID
|
||||
}
|
||||
|
||||
// 交易更新消息
|
||||
type TransactionUpdate struct {
|
||||
MessageId string
|
||||
TransactionState TransactionStateEnum //交易状态
|
||||
TransactionId string //充值ID、打赏ID、购买表情ID、购买守护ID、兑换ID、砸蛋ID、提现ID、订单ID等
|
||||
TransactionCompleteTime string //交易完成时间
|
||||
}
|
||||
|
||||
type TransactionCodeEnum string
|
||||
|
||||
const (
|
||||
RewardSimple TransactionCodeEnum = "SIMPLE" //单个打赏
|
||||
RewardMulti TransactionCodeEnum = "MULTI" //批量打赏
|
||||
RewardBagSimple TransactionCodeEnum = "BAG_SIMPLE" //背包礼物单个打赏
|
||||
RewardBagMulti TransactionCodeEnum = "BAG_MULTI" //背包礼物批量打赏
|
||||
|
||||
GuardLevel01 TransactionCodeEnum = "1" //青铜守护
|
||||
GuardLevel02 TransactionCodeEnum = "2" //白银守护
|
||||
GuardLevel03 TransactionCodeEnum = "3" //黄金守护
|
||||
|
||||
Hunting1 TransactionCodeEnum = "1" //单砸
|
||||
Hunting10 TransactionCodeEnum = "10" //十砸
|
||||
Hunting100 TransactionCodeEnum = "100" //百砸
|
||||
|
||||
RechargeAppAlipay TransactionCodeEnum = "AppAlipay" //app支付宝
|
||||
RechargeAppWeChat TransactionCodeEnum = "AppWeChat" //app微信
|
||||
RechargeAppIap TransactionCodeEnum = "AppIap" //appIap
|
||||
RechargeH5Alipay TransactionCodeEnum = "H5Alipay" //H5支付宝
|
||||
RechargeH5WeChatClub TransactionCodeEnum = "H5WeChatClub" //H5微信公众号
|
||||
RechargeOperation TransactionCodeEnum = "Operation" //Operation
|
||||
)
|
||||
|
||||
type TransactionStateEnum string
|
||||
|
||||
const (
|
||||
CREATED TransactionStateEnum = "CREATED" //已创建
|
||||
SUCCESS TransactionStateEnum = "SUCCESS" //成功
|
||||
FAILED TransactionStateEnum = "FAILED" //失败
|
||||
)
|
||||
|
||||
type TransactionCurrencyEnum string
|
||||
|
||||
const (
|
||||
DIAMOND TransactionCurrencyEnum = "DIAMOND" //钻石
|
||||
CRYSTAL TransactionCurrencyEnum = "CRYSTAL" //晶石
|
||||
MONEY TransactionCurrencyEnum = "MONEY" //钱
|
||||
FRAGMENT TransactionCurrencyEnum = "FRAGMENT" //碎片
|
||||
)
|
||||
|
||||
type TransactionTypeEnum string
|
||||
|
||||
const (
|
||||
RECHARGE TransactionTypeEnum = "RECHARGE" //充值
|
||||
RechargeNCoin TransactionTypeEnum = "RECHARGE_N_COIN" //充值N币
|
||||
REWARD TransactionTypeEnum = "REWARD" //打赏
|
||||
REWARDNCoin TransactionTypeEnum = "REWARD_N_COIN" //打赏
|
||||
GUARD TransactionTypeEnum = "GUARD" //购买守护
|
||||
EMOJI TransactionTypeEnum = "EMOJI" //购买表情
|
||||
OperationDiamond TransactionTypeEnum = "OPERATION_DIAMOND" //手工加钻石
|
||||
OperationCrystal TransactionTypeEnum = "OPERATION_CRYSTAL" //手工加晶石
|
||||
OperationCrystalReduce TransactionTypeEnum = "OPERATION_CRYSTAL_REDUCE" //手工扣除晶石
|
||||
EXCHANGE TransactionTypeEnum = "EXCHANGE" //兑换
|
||||
HUNTING TransactionTypeEnum = "HUNTING" //星空寻宝
|
||||
WithdrawNCoin TransactionTypeEnum = "WITHDRAW_N_COIN" //提现 N币
|
||||
ORDER TransactionTypeEnum = "ORDER" //订单
|
||||
ORDERNCoin TransactionTypeEnum = "ORDER_N_COIN" //订单
|
||||
ORDER_H5 TransactionTypeEnum = "ORDER_H5" //订单
|
||||
ORDER_H5_NCoin TransactionTypeEnum = "ORDER_H5_N_COIN" //订单
|
||||
LUCK_GIFT TransactionTypeEnum = "LUCK_GIFT" //幸运礼物
|
||||
LuckGiftNCoin TransactionTypeEnum = "LUCK_GIFT_N_COIN" //幸运礼物
|
||||
)
|
||||
767
pkg/common/netease/ImClient.go
Normal file
767
pkg/common/netease/ImClient.go
Normal file
@ -0,0 +1,767 @@
|
||||
package Netease
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"servicebase/pkg/common"
|
||||
"servicebase/pkg/common/HyTools"
|
||||
yunxin "servicebase/pkg/common/netease/dto"
|
||||
"servicebase/pkg/htools"
|
||||
"servicebase/pkg/log"
|
||||
"strings"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cast"
|
||||
|
||||
"math/rand"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/anxpp/beego/logs"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
type ImClient struct {
|
||||
AppKey string
|
||||
AppSecret string
|
||||
}
|
||||
|
||||
type CreateImRes struct {
|
||||
Code int
|
||||
Desc string
|
||||
}
|
||||
|
||||
type BroadcastNotificationReq struct {
|
||||
FromAccountId string `json:"from_account_id"`
|
||||
Content string `json:"content"`
|
||||
TargetOs []string `json:"target_os"`
|
||||
}
|
||||
|
||||
func NewImClient() *ImClient {
|
||||
fmt.Printf("NewImClient: %s\n", viper.GetString("netease.im.key"))
|
||||
key := viper.GetString("netease.im.key")
|
||||
secret := viper.GetString("netease.im.secret")
|
||||
return &ImClient{AppKey: key, AppSecret: secret}
|
||||
}
|
||||
|
||||
// 生成云信header
|
||||
func (client *ImClient) generateHeader() map[string]string {
|
||||
nonce := randNumber()
|
||||
t := time.Now()
|
||||
currentTime := strconv.FormatInt(t.UTC().Unix(), 10)
|
||||
result := make(map[string]string)
|
||||
result["AppKey"] = client.AppKey
|
||||
result["Nonce"] = nonce
|
||||
result["CurTime"] = currentTime
|
||||
result["CheckSum"] = client.generateCheckSum(nonce, currentTime)
|
||||
result["Content-Type"] = "application/x-www-form-urlencoded;charset=utf-8"
|
||||
return result
|
||||
}
|
||||
|
||||
func (client *ImClient) generateJsonHeader() map[string]string {
|
||||
nonce := randNumber()
|
||||
t := time.Now()
|
||||
currentTime := strconv.FormatInt(t.UTC().Unix(), 10)
|
||||
result := make(map[string]string)
|
||||
result["AppKey"] = client.AppKey
|
||||
result["Nonce"] = nonce
|
||||
result["CurTime"] = currentTime
|
||||
result["CheckSum"] = client.generateCheckSum(nonce, currentTime)
|
||||
result["Content-Type"] = "application/json"
|
||||
return result
|
||||
}
|
||||
|
||||
// 生成云信签名
|
||||
func (client *ImClient) generateCheckSum(nonce, currentTime string) string {
|
||||
waitSignStr := client.AppSecret + nonce + currentTime
|
||||
result := HyTools.StringToSHA1(waitSignStr)
|
||||
return result
|
||||
}
|
||||
|
||||
// 创建云信账户
|
||||
// imService.CreateImUser(common.SYNC_DATA_USER_ID,"数据同步",common.PHOTO_DOMAIN_URL+"assets/sys/guanfanggonggao.png")
|
||||
func (client *ImClient) CreateImUser(userId, nickName, avatar string) error {
|
||||
url := "https://api.netease.im/nimserver/user/create.action"
|
||||
httpMethod := common.HTTP_METHOD_POST
|
||||
header := client.generateHeader()
|
||||
sb := HyTools.NewStringBuilder()
|
||||
sb.Append("accid=" + userId)
|
||||
sb.Append("&")
|
||||
sb.Append("token=123456")
|
||||
sb.Append("&")
|
||||
sb.Append("name=" + nickName)
|
||||
sb.Append("&")
|
||||
sb.Append("icon=" + avatar)
|
||||
res, err := HyTools.HttpDo(httpMethod, url, header, sb.ToString())
|
||||
if err != nil {
|
||||
// {"desc":"already register","code":414}
|
||||
logs.Info("YunXin_SignUp_Fail_AccID_%s:"+err.Error(), userId)
|
||||
return err
|
||||
} else {
|
||||
// {"code":200,"info":{"token":"123456","accid":"b8af4bebe2064435974ba2340d852055","name":"b8af4bebe2064435974ba2340d852055"}}
|
||||
var resDTO CreateImRes
|
||||
json.Unmarshal([]byte(res), &resDTO)
|
||||
if resDTO.Code != 200 {
|
||||
logs.Info("YunXin_SignUp_Fail_AccID_%s:"+resDTO.Desc, userId)
|
||||
} else {
|
||||
logs.Info("YunXin_SignUp_Success_AccID_%s:"+res, userId)
|
||||
}
|
||||
}
|
||||
var body map[string]interface{}
|
||||
if errJson := json.Unmarshal([]byte(res), &body); errJson != nil {
|
||||
return errJson
|
||||
}
|
||||
if int(body["code"].(float64)) != 200 {
|
||||
return errors.New(body["desc"].(string))
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// 查询用户信息
|
||||
func (client *ImClient) GetImUserInfo(userId string) error {
|
||||
url := "https://api.netease.im/nimserver/user/getUinfos.action"
|
||||
httpMethod := common.HTTP_METHOD_POST
|
||||
header := client.generateHeader()
|
||||
sb := HyTools.NewStringBuilder()
|
||||
accids := []string{userId}
|
||||
byteData, _ := json.Marshal(accids)
|
||||
sb.Append("accids=" + string(byteData))
|
||||
res, err := HyTools.HttpDo(httpMethod, url, header, sb.ToString())
|
||||
// #查询云信用户信息结果:{"desc":"b8af4bebe2064435974ba2340d852055not register","code":414}#
|
||||
// {"code":200,"uinfos":[{"icon":"https://xzphoto.meetalk.tech/upload/6bba4098-6ea8-4758-8193-19abed540c0b.0","accid":"2251bae8a0514e6892f0374f5dd260d4","name":"弦乐","gender":0}]}
|
||||
logs.Info("#" + "查询云信用户信息结果:" + res + "#")
|
||||
var body map[string]interface{}
|
||||
if errJson := json.Unmarshal([]byte(res), &body); errJson != nil {
|
||||
return errJson
|
||||
}
|
||||
if int(body["code"].(float64)) != 200 {
|
||||
return errors.New(body["desc"].(string))
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// 更新云信信息
|
||||
func (client *ImClient) UpdateImUserInfo(accid, nickName, avatar string) error {
|
||||
url := "https://api.netease.im/nimserver/user/updateUinfo.action"
|
||||
httpMethod := common.HTTP_METHOD_POST
|
||||
header := client.generateHeader()
|
||||
sb := htools.NewStringBuilder()
|
||||
sb.Append("accid=" + accid)
|
||||
sb.Append("&")
|
||||
sb.Append("name=" + nickName)
|
||||
sb.Append("&")
|
||||
sb.Append("icon=" + avatar)
|
||||
res, err := htools.HttpDo(httpMethod, url, header, sb.ToString())
|
||||
logs.Info(common.LOG_QUOTE_STRING + "云信更新用户信息结果:" + res + common.LOG_QUOTE_STRING)
|
||||
return err
|
||||
}
|
||||
|
||||
// 更新云信用户扩展信息
|
||||
func (client *ImClient) UpdateImUserExt(accid, ext string) error {
|
||||
url := "https://api.netease.im/nimserver/user/updateUinfo.action"
|
||||
httpMethod := common.HTTP_METHOD_POST
|
||||
header := client.generateHeader()
|
||||
sb := htools.NewStringBuilder()
|
||||
sb.Append("accid=" + accid)
|
||||
sb.Append("&")
|
||||
sb.Append("ex=" + ext)
|
||||
logs.Info("update_im_user userID[%s] ext:%s", accid, ext)
|
||||
res, err := htools.HttpDo(httpMethod, url, header, sb.ToString())
|
||||
logs.Info(common.LOG_QUOTE_STRING+"云信更新用户ext%s信息结果:"+res+common.LOG_QUOTE_STRING, ext)
|
||||
return err
|
||||
}
|
||||
|
||||
// 封禁云信帐号
|
||||
func (client *ImClient) BlockImUser(accid string) error {
|
||||
|
||||
url := "https://api.netease.im/nimserver/user/block.action"
|
||||
httpMethod := common.HTTP_METHOD_POST
|
||||
header := client.generateHeader()
|
||||
|
||||
sb := htools.NewStringBuilder()
|
||||
sb.Append("accid=" + accid)
|
||||
sb.Append("&")
|
||||
sb.Append("needkick=true")
|
||||
|
||||
res, err := htools.HttpDo(httpMethod, url, header, sb.ToString())
|
||||
logs.Info(common.LOG_QUOTE_STRING + "封禁云信帐号结果:" + res + common.LOG_QUOTE_STRING)
|
||||
return err
|
||||
}
|
||||
|
||||
// 解禁云信帐号
|
||||
func (client *ImClient) UnBlockImUser(accid string) error {
|
||||
|
||||
url := "https://api.netease.im/nimserver/user/unblock.action"
|
||||
httpMethod := common.HTTP_METHOD_POST
|
||||
header := client.generateHeader()
|
||||
|
||||
sb := htools.NewStringBuilder()
|
||||
sb.Append("accid=" + accid)
|
||||
|
||||
res, err := htools.HttpDo(httpMethod, url, header, sb.ToString())
|
||||
logs.Info(common.LOG_QUOTE_STRING + "解禁云信帐号结果:" + res + common.LOG_QUOTE_STRING)
|
||||
return err
|
||||
}
|
||||
|
||||
// 创建云信聊天室
|
||||
func (client *ImClient) CreateChatroom(ownerUserId string, roomName string) (chatroomModel NeteaseChatroomDTO) {
|
||||
logs.Info("CreateChatroom ownerUserId=%s roomName=%s", ownerUserId, roomName)
|
||||
url := "https://api.netease.im/nimserver/chatroom/create.action"
|
||||
httpMethod := common.HTTP_METHOD_POST
|
||||
header := client.generateHeader()
|
||||
sb := htools.NewStringBuilder()
|
||||
sb.Append("creator=" + ownerUserId)
|
||||
sb.Append("&")
|
||||
sb.Append("name=" + roomName)
|
||||
res, err := htools.HttpDo(httpMethod, url, header, sb.ToString())
|
||||
if err != nil {
|
||||
logs.Info(common.LOG_QUOTE_STRING + "云信创建聊天室请求失败:" + err.Error() + common.LOG_QUOTE_STRING)
|
||||
return
|
||||
}
|
||||
// {"valid":true,"ext":"","creator":"1b94b5e7af8a45ed9fda27d28165d4c9","name":"32452345","muted":false,"roomid":11142139973,"queuelevel":0}
|
||||
logs.Info(common.LOG_QUOTE_STRING + "云信创建聊天室结果:" + res + common.LOG_QUOTE_STRING)
|
||||
var createRes CreateChatroomResponse
|
||||
err1 := json.Unmarshal([]byte(res), &createRes)
|
||||
if err1 != nil {
|
||||
logs.Info(common.LOG_QUOTE_STRING + "创建聊天室失败,解析结果错误:" + res + common.LOG_QUOTE_STRING)
|
||||
panic(err1)
|
||||
}
|
||||
if createRes.Code != 200 {
|
||||
|
||||
logs.Info(common.LOG_QUOTE_STRING + "创建Im聊天室失败:code= " + strconv.Itoa(createRes.Code) + common.LOG_QUOTE_STRING)
|
||||
panic(errors.New("创建云信Im聊天室失败"))
|
||||
}
|
||||
chatroomModel = createRes.Chatroom
|
||||
return
|
||||
}
|
||||
|
||||
// IM发送消息
|
||||
func (client *ImClient) SendMsg(parameters map[string]string) error {
|
||||
url := "https://api.netease.im/nimserver/msg/sendMsg.action"
|
||||
httpMethod := common.HTTP_METHOD_POST
|
||||
header := client.generateHeader()
|
||||
sb := htools.NewStringBuilder()
|
||||
parametersCount := len(parameters)
|
||||
i := 0
|
||||
for k, v := range parameters {
|
||||
sb.Append(k + "=" + v)
|
||||
if i < parametersCount-1 {
|
||||
sb.Append("&")
|
||||
}
|
||||
i++
|
||||
}
|
||||
logs.Info(common.LOG_QUOTE_STRING + "云信IM发消息请求:" + sb.ToString() + common.LOG_QUOTE_STRING)
|
||||
res, err := htools.HttpDo(httpMethod, url, header, sb.ToString())
|
||||
logs.Info(common.LOG_QUOTE_STRING + "云信IM发消息结果:" + res + common.LOG_QUOTE_STRING)
|
||||
return err
|
||||
}
|
||||
|
||||
// 添加机器人
|
||||
func (client *ImClient) AddRobot(parameters map[string]string) error {
|
||||
url := "https://api.netease.im/nimserver/chatroom/addRobot.action"
|
||||
httpMethod := common.HTTP_METHOD_POST
|
||||
header := client.generateHeader()
|
||||
sb := htools.NewStringBuilder()
|
||||
parametersCount := len(parameters)
|
||||
i := 0
|
||||
for k, v := range parameters {
|
||||
sb.Append(k + "=" + v)
|
||||
if i < parametersCount-1 {
|
||||
sb.Append("&")
|
||||
}
|
||||
i++
|
||||
}
|
||||
logs.Info(common.LOG_QUOTE_STRING + "添加机器人:" + sb.ToString() + common.LOG_QUOTE_STRING)
|
||||
res, err := htools.HttpDo(httpMethod, url, header, sb.ToString())
|
||||
logs.Info(common.LOG_QUOTE_STRING + "添加机器人:" + res + common.LOG_QUOTE_STRING)
|
||||
return err
|
||||
}
|
||||
|
||||
// 移除机器人
|
||||
func (client *ImClient) RemoveRobot(parameters map[string]string) error {
|
||||
|
||||
url := "https://api.netease.im/nimserver/chatroom/removeRobot.action"
|
||||
httpMethod := common.HTTP_METHOD_POST
|
||||
header := client.generateHeader()
|
||||
sb := htools.NewStringBuilder()
|
||||
parametersCount := len(parameters)
|
||||
i := 0
|
||||
for k, v := range parameters {
|
||||
sb.Append(k + "=" + v)
|
||||
if i < parametersCount-1 {
|
||||
sb.Append("&")
|
||||
}
|
||||
i++
|
||||
}
|
||||
logs.Info(common.LOG_QUOTE_STRING + "移除机器人:" + sb.ToString() + common.LOG_QUOTE_STRING)
|
||||
res, err := htools.HttpDo(httpMethod, url, header, sb.ToString())
|
||||
logs.Info(common.LOG_QUOTE_STRING + "移除机器人:" + res + common.LOG_QUOTE_STRING)
|
||||
return err
|
||||
}
|
||||
|
||||
// 发送聊天室消息
|
||||
func (client *ImClient) SendChatroomMsg(parameters map[string]string) error {
|
||||
|
||||
url := "https://api.netease.im/nimserver/chatroom/sendMsg.action"
|
||||
|
||||
httpMethod := common.HTTP_METHOD_POST
|
||||
header := client.generateHeader()
|
||||
|
||||
sb := htools.NewStringBuilder()
|
||||
parametersCount := len(parameters)
|
||||
i := 0
|
||||
for k, v := range parameters {
|
||||
sb.Append(k + "=" + v)
|
||||
if i < parametersCount-1 {
|
||||
sb.Append("&")
|
||||
}
|
||||
i++
|
||||
}
|
||||
|
||||
logs.Info(common.LOG_QUOTE_STRING + "聊天室发消息请求:" + sb.ToString() + common.LOG_QUOTE_STRING)
|
||||
res, err := htools.HttpDo(httpMethod, url, header, sb.ToString())
|
||||
logs.Info(common.LOG_QUOTE_STRING + "聊天室发消息结果:" + res + common.LOG_QUOTE_STRING)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// 获取在线成员信息
|
||||
func (client *ImClient) GetChatroomMembers(parameters map[string]string) (imResponse ImResponse, err error) {
|
||||
|
||||
url := "https://api.netease.im/nimserver/chatroom/queryMembers.action"
|
||||
|
||||
httpMethod := common.HTTP_METHOD_POST
|
||||
|
||||
header := client.generateHeader()
|
||||
|
||||
body := generateBodyData(parameters)
|
||||
|
||||
logs.Info(common.LOG_QUOTE_STRING + "获取在线成员请求:" + body + common.LOG_QUOTE_STRING)
|
||||
|
||||
res, err1 := htools.HttpDo(httpMethod, url, header, body)
|
||||
|
||||
if err1 != nil {
|
||||
logs.Error(common.LOG_QUOTE_STRING + "获取在线成员失败:" + err1.Error() + common.LOG_QUOTE_STRING)
|
||||
err = err1
|
||||
return
|
||||
}
|
||||
|
||||
logs.Info(common.LOG_QUOTE_STRING + "获取在线成员结果:" + res + common.LOG_QUOTE_STRING)
|
||||
var response ImResponse
|
||||
if err2 := json.Unmarshal([]byte(res), &response); err2 != nil {
|
||||
|
||||
logs.Error(common.LOG_QUOTE_STRING + "获取在线成员解析失败:" + err2.Error() + common.LOG_QUOTE_STRING)
|
||||
err = err2
|
||||
return
|
||||
}
|
||||
|
||||
imResponse = response
|
||||
|
||||
return
|
||||
|
||||
}
|
||||
|
||||
// 分页获取聊天室在线用户列表
|
||||
func (client *ImClient) GetChatroomOnlineUserListByPage(parameters map[string]string) (imResponse ImResponse, err error) {
|
||||
|
||||
url := "https://api.netease.im/nimserver/chatroom/membersByPage.action"
|
||||
|
||||
httpMethod := common.HTTP_METHOD_POST
|
||||
|
||||
header := client.generateHeader()
|
||||
|
||||
body := generateBodyData(parameters)
|
||||
|
||||
logs.Info(common.LOG_QUOTE_STRING + "分页获取聊天室在线列表:" + body + common.LOG_QUOTE_STRING)
|
||||
|
||||
res, err1 := htools.HttpDo(httpMethod, url, header, body)
|
||||
|
||||
if err1 != nil {
|
||||
logs.Error(common.LOG_QUOTE_STRING + "分页获取聊天室在线列表失败:" + err1.Error() + common.LOG_QUOTE_STRING)
|
||||
err = err1
|
||||
return
|
||||
}
|
||||
|
||||
logs.Info(common.LOG_QUOTE_STRING + "分页获取聊天室在线列表结果:" + res + common.LOG_QUOTE_STRING)
|
||||
var response ImResponse
|
||||
if err2 := json.Unmarshal([]byte(res), &response); err2 != nil {
|
||||
|
||||
logs.Error(common.LOG_QUOTE_STRING + "分页获取聊天室在线列表失败:" + err2.Error() + common.LOG_QUOTE_STRING)
|
||||
err = err2
|
||||
return
|
||||
}
|
||||
|
||||
imResponse = response
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// 更新聊天室房间信息
|
||||
func (client *ImClient) UpdateRoomInfo(request yunxin.UpdateRoomInfoRequest) (err error) {
|
||||
|
||||
url := "https://api.netease.im/nimserver/chatroom/update.action"
|
||||
|
||||
httpMethod := common.HTTP_METHOD_POST
|
||||
header := client.generateHeader()
|
||||
|
||||
sb := htools.NewStringBuilder()
|
||||
sb.Append("roomid=" + request.Roomid)
|
||||
sb.Append("&")
|
||||
sb.Append("name=")
|
||||
sb.Append("&")
|
||||
sb.Append("announcement=")
|
||||
sb.Append("&")
|
||||
sb.Append("ext=")
|
||||
sb.Append("&")
|
||||
sb.Append("notifyExt=" + request.NotifyExt)
|
||||
|
||||
logs.Info(common.LOG_QUOTE_STRING + "更新聊天室信息请求:" + sb.ToString() + common.LOG_QUOTE_STRING)
|
||||
res, httpErr := htools.HttpDo(httpMethod, url, header, sb.ToString())
|
||||
logs.Info(common.LOG_QUOTE_STRING + "更新聊天室信息结果:" + res + common.LOG_QUOTE_STRING)
|
||||
|
||||
if httpErr != nil {
|
||||
logs.Info(common.LOG_QUOTE_STRING + "更新聊天室信息失败:" + httpErr.Error() + common.LOG_QUOTE_STRING)
|
||||
err = httpErr
|
||||
return
|
||||
}
|
||||
|
||||
resMap := make(map[string]interface{})
|
||||
jsonErr := json.Unmarshal([]byte(res), &resMap)
|
||||
|
||||
if jsonErr != nil {
|
||||
logs.Info(common.LOG_QUOTE_STRING + "解析更新房间信息结果失败:" + jsonErr.Error() + common.LOG_QUOTE_STRING)
|
||||
err = jsonErr
|
||||
return
|
||||
}
|
||||
|
||||
code := resMap["code"].(float64)
|
||||
codeStr := htools.Float64ToString(code)
|
||||
if codeStr != "200" {
|
||||
logs.Info(common.LOG_QUOTE_STRING + "更新房间信息结果失败: code=" + codeStr + common.LOG_QUOTE_STRING)
|
||||
err = errors.New("更新失败 code=" + codeStr)
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
|
||||
}
|
||||
|
||||
// 聊天室临时禁言
|
||||
func (client *ImClient) ChatroomMuteUser(parameters map[string]string) error {
|
||||
|
||||
url := "https://api.netease.im/nimserver/chatroom/temporaryMute.action"
|
||||
|
||||
httpMethod := common.HTTP_METHOD_POST
|
||||
header := client.generateHeader()
|
||||
|
||||
sb := htools.NewStringBuilder()
|
||||
parametersCount := len(parameters)
|
||||
i := 0
|
||||
for k, v := range parameters {
|
||||
sb.Append(k + "=" + v)
|
||||
if i < parametersCount-1 {
|
||||
sb.Append("&")
|
||||
}
|
||||
i++
|
||||
}
|
||||
|
||||
logs.Info(common.LOG_QUOTE_STRING + "聊天室临时禁言请求:" + sb.ToString() + common.LOG_QUOTE_STRING)
|
||||
res, err := htools.HttpDo(httpMethod, url, header, sb.ToString())
|
||||
logs.Info(common.LOG_QUOTE_STRING + "聊天室临时禁言结果:" + res + common.LOG_QUOTE_STRING)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// 切换聊天室状态
|
||||
func (client *ImClient) ChangeChatroomStat(parameters map[string]string) error {
|
||||
|
||||
url := "https://api.netease.im/nimserver/chatroom/toggleCloseStat.action"
|
||||
|
||||
httpMethod := common.HTTP_METHOD_POST
|
||||
header := client.generateHeader()
|
||||
|
||||
sb := htools.NewStringBuilder()
|
||||
parametersCount := len(parameters)
|
||||
i := 0
|
||||
for k, v := range parameters {
|
||||
sb.Append(k + "=" + v)
|
||||
if i < parametersCount-1 {
|
||||
sb.Append("&")
|
||||
}
|
||||
i++
|
||||
}
|
||||
|
||||
requestId := HyTools.GetUUID()
|
||||
logs.Info(common.LOG_QUOTE_STRING + "聊天室切换聊天室开关状态请求:requestId " + requestId + " body " + sb.ToString() + common.LOG_QUOTE_STRING)
|
||||
res, err := htools.HttpDo(httpMethod, url, header, sb.ToString())
|
||||
if len(res) == 0 {
|
||||
logs.Info(common.LOG_QUOTE_STRING + "聊天室切换聊天室开关状态结果:失败 res为空 requestId " + requestId + common.LOG_QUOTE_STRING)
|
||||
return errors.New("操作失败")
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
logs.Info(common.LOG_QUOTE_STRING + "聊天室切换聊天室开关状态结果:失败 返回error requestId " + requestId + "error " + err.Error() + common.LOG_QUOTE_STRING)
|
||||
return err
|
||||
}
|
||||
|
||||
//{"desc":"parameter roomid should be long","code":414}
|
||||
var resData struct {
|
||||
Code int `json:"code"`
|
||||
Desc string `json:"desc"`
|
||||
}
|
||||
|
||||
_ = json.Unmarshal([]byte(res), &resData)
|
||||
|
||||
if resData.Code != 200 {
|
||||
if resData.Code != 417 { // 重复操作 直接忽略
|
||||
logs.Info(fmt.Sprintf(common.LOG_QUOTE_STRING+"聊天室切换聊天室开关状态结果:失败 code[%d] requestId "+requestId+" desc[%s] "+common.LOG_QUOTE_STRING, resData.Code, resData.Desc))
|
||||
return errors.New("操作失败")
|
||||
}
|
||||
}
|
||||
|
||||
logs.Info(common.LOG_QUOTE_STRING + "聊天室切换聊天室开关状态结果: requestId " + requestId + " response " + res + common.LOG_QUOTE_STRING)
|
||||
return err
|
||||
}
|
||||
|
||||
// 设置聊天室成员角色
|
||||
func (client *ImClient) SetChatroomMemberRole(parameters map[string]string) error {
|
||||
|
||||
url := "https://api.netease.im/nimserver/chatroom/setMemberRole.action"
|
||||
|
||||
httpMethod := common.HTTP_METHOD_POST
|
||||
header := client.generateHeader()
|
||||
|
||||
sb := htools.NewStringBuilder()
|
||||
parametersCount := len(parameters)
|
||||
i := 0
|
||||
for k, v := range parameters {
|
||||
sb.Append(k + "=" + v)
|
||||
if i < parametersCount-1 {
|
||||
sb.Append("&")
|
||||
}
|
||||
i++
|
||||
}
|
||||
|
||||
logs.Info(common.LOG_QUOTE_STRING + "设置聊天室成员角色请求:" + sb.ToString() + common.LOG_QUOTE_STRING)
|
||||
res, err := htools.HttpDo(httpMethod, url, header, sb.ToString())
|
||||
logs.Info(common.LOG_QUOTE_STRING + "设置聊天室成员角色结果:" + res + common.LOG_QUOTE_STRING)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// 发送广播消息
|
||||
func (client *ImClient) SendBroadCastMsg(parameters map[string]string) error {
|
||||
|
||||
url := "https://api.netease.im/nimserver/msg/broadcastMsg.action"
|
||||
|
||||
httpMethod := common.HTTP_METHOD_POST
|
||||
header := client.generateHeader()
|
||||
|
||||
sb := htools.NewStringBuilder()
|
||||
parametersCount := len(parameters)
|
||||
i := 0
|
||||
for k, v := range parameters {
|
||||
sb.Append(k + "=" + v)
|
||||
if i < parametersCount-1 {
|
||||
sb.Append("&")
|
||||
}
|
||||
i++
|
||||
}
|
||||
|
||||
logs.Info(common.LOG_QUOTE_STRING + "发送广播请求:" + sb.ToString() + common.LOG_QUOTE_STRING)
|
||||
res, err := htools.HttpDo(httpMethod, url, header, sb.ToString())
|
||||
logs.Info(common.LOG_QUOTE_STRING + "发送广播结果:" + res + common.LOG_QUOTE_STRING)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// 发送全员广播 V2
|
||||
func (client *ImClient) SendBroadCastMsgV2(req BroadcastNotificationReq) error {
|
||||
|
||||
url := "https://open.yunxinapi.com/im/v2/broadcast_notification"
|
||||
|
||||
httpMethod := common.HTTP_METHOD_POST
|
||||
header := client.generateJsonHeader()
|
||||
|
||||
bodyStr := HyTools.JsonStr(req)
|
||||
|
||||
logs.Info(common.LOG_QUOTE_STRING + "发送广播请求V2:" + bodyStr + common.LOG_QUOTE_STRING)
|
||||
res, err := htools.HttpDo(httpMethod, url, header, bodyStr)
|
||||
logs.Info(common.LOG_QUOTE_STRING + "发送广播结果V2:" + res + common.LOG_QUOTE_STRING)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// 踢出用户登录 V2 https://{endpoint}/im/v2/accounts/{account_id}/actions/kick
|
||||
|
||||
func (client *ImClient) KickOutUserV2(userId string) error {
|
||||
|
||||
url := "https://open.yunxinapi.com/im/v2/accounts/" + userId + "/actions/kick"
|
||||
|
||||
httpMethod := common.HTTP_METHOD_POST
|
||||
header := client.generateJsonHeader()
|
||||
|
||||
req := make(map[string]any, 3)
|
||||
req["type"] = 1
|
||||
req["device_id_list"] = []string{}
|
||||
req["kick_notify_extension"] = ""
|
||||
|
||||
bodyStr := HyTools.JsonStr(req)
|
||||
|
||||
logs.Info(common.LOG_QUOTE_STRING + "发送踢下线请求V2:" + bodyStr + common.LOG_QUOTE_STRING)
|
||||
res, err := htools.HttpDo(httpMethod, url, header, bodyStr)
|
||||
logs.Info(common.LOG_QUOTE_STRING + "发送踢下线结果V2:" + res + common.LOG_QUOTE_STRING)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// 设置/取消 拉黑 静音
|
||||
func (client *ImClient) SetSpecialRelation(parameters map[string]string) error {
|
||||
|
||||
url := "https://api.netease.im/nimserver/user/setSpecialRelation.action"
|
||||
|
||||
httpMethod := common.HTTP_METHOD_POST
|
||||
header := client.generateHeader()
|
||||
|
||||
sb := htools.NewStringBuilder()
|
||||
parametersCount := len(parameters)
|
||||
i := 0
|
||||
for k, v := range parameters {
|
||||
sb.Append(k + "=" + v)
|
||||
if i < parametersCount-1 {
|
||||
sb.Append("&")
|
||||
}
|
||||
i++
|
||||
}
|
||||
|
||||
logs.Info(common.LOG_QUOTE_STRING + "设置/取消 拉黑请求:" + sb.ToString() + common.LOG_QUOTE_STRING)
|
||||
res, err := htools.HttpDo(httpMethod, url, header, sb.ToString())
|
||||
logs.Info(common.LOG_QUOTE_STRING + "设置/取消 拉黑结果:" + res + common.LOG_QUOTE_STRING)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// 发送自定义系统通知
|
||||
func (client *ImClient) BatchSendMsg(parameters map[string]string) error {
|
||||
|
||||
url := "https://api.netease.im/nimserver/msg/sendBatchMsg.action"
|
||||
httpMethod := common.HTTP_METHOD_POST
|
||||
header := client.generateHeader()
|
||||
|
||||
sb := htools.NewStringBuilder()
|
||||
parametersCount := len(parameters)
|
||||
i := 0
|
||||
for k, v := range parameters {
|
||||
sb.Append(k + "=" + v)
|
||||
if i < parametersCount-1 {
|
||||
sb.Append("&")
|
||||
}
|
||||
i++
|
||||
}
|
||||
logs.Info(common.LOG_QUOTE_STRING + "云信IM批量发消息请求:" + sb.ToString() + common.LOG_QUOTE_STRING)
|
||||
res, err := htools.HttpDo(httpMethod, url, header, sb.ToString())
|
||||
logs.Info(common.LOG_QUOTE_STRING + "云信IM批量发消息结果:" + res + common.LOG_QUOTE_STRING)
|
||||
return err
|
||||
}
|
||||
|
||||
// 批量发送消息
|
||||
func (client *ImClient) SendAttachMsg(parameters map[string]string) error {
|
||||
|
||||
url := "https://api.netease.im/nimserver/msg/sendAttachMsg.action"
|
||||
httpMethod := common.HTTP_METHOD_POST
|
||||
header := client.generateHeader()
|
||||
|
||||
sb := htools.NewStringBuilder()
|
||||
parametersCount := len(parameters)
|
||||
i := 0
|
||||
for k, v := range parameters {
|
||||
sb.Append(k + "=" + v)
|
||||
if i < parametersCount-1 {
|
||||
sb.Append("&")
|
||||
}
|
||||
i++
|
||||
}
|
||||
logs.Info(common.LOG_QUOTE_STRING + "云信IM发系统通知请求:" + sb.ToString() + common.LOG_QUOTE_STRING)
|
||||
res, err := htools.HttpDo(httpMethod, url, header, sb.ToString())
|
||||
logs.Info(common.LOG_QUOTE_STRING + "云信IM发系统通知结果:" + res + common.LOG_QUOTE_STRING)
|
||||
if parameters["to"] == "b260b07ff3d1411f926e2d767cb9d6f3" {
|
||||
log.Info("完成给老板发接单消息")
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// CreateChatGroup 创建群组
|
||||
func (client *ImClient) CreateChatGroup(ctx context.Context, ownerUserId string, groupName string, inviteMem []string) (string, error) {
|
||||
|
||||
url := "https://open.yunxinapi.com/im/v2.1/teams"
|
||||
httpMethod := common.HTTP_METHOD_POST
|
||||
header := client.generateJsonHeader()
|
||||
reqBody := &CreateChatGroupReq{
|
||||
OwnerAccountID: ownerUserId,
|
||||
TeamType: 1,
|
||||
Name: groupName,
|
||||
MembersLimit: 3000,
|
||||
InviteAccountIDs: inviteMem,
|
||||
InviteMsg: "管理",
|
||||
Configuration: &TeamConfiguration{
|
||||
JoinMode: 1,
|
||||
},
|
||||
AntispamConfiguration: nil,
|
||||
}
|
||||
bodyBytes, err := json.Marshal(reqBody)
|
||||
if err != nil {
|
||||
return "", errors.WithStack(err)
|
||||
}
|
||||
|
||||
res, err := HyTools.HttpDo(httpMethod, url, header, string(bodyBytes))
|
||||
if err != nil {
|
||||
// {"desc":"already register","code":414}
|
||||
logs.Info("YunXin_CreateChatGroup_Fail_AccID_%s:"+err.Error(), ownerUserId)
|
||||
return "", errors.WithStack(err)
|
||||
}
|
||||
log.InfoF("create group chat resp: %s", res)
|
||||
var body BaseRes[CreateChatGroupRsp]
|
||||
err = json.Unmarshal([]byte(res), &body)
|
||||
if err != nil {
|
||||
return "", errors.WithStack(err)
|
||||
}
|
||||
if body.Code != 200 {
|
||||
return "", errors.Errorf("YunXin_CreateChatGroup code(%d) not 200,msg: %s", body.Code, body.Msg)
|
||||
}
|
||||
if len(body.Data.FailedList) > 0 {
|
||||
var errInfo []string
|
||||
for _, member := range body.Data.FailedList {
|
||||
errInfo = append(errInfo, fmt.Sprintf("account: %s ,code: %d ,msg: %s", member.AccountID, member.ErrorCode, member.ErrorMsg))
|
||||
}
|
||||
return "", errors.Errorf("YunXin_CreateChatGroup err: %s", strings.Join(errInfo, ";"))
|
||||
}
|
||||
|
||||
return cast.ToString(body.Data.TeamInfo.TeamID), nil
|
||||
}
|
||||
|
||||
// ================ 私有方法 ========================
|
||||
func generateBodyData(parameters map[string]string) string {
|
||||
sb := htools.NewStringBuilder()
|
||||
parametersCount := len(parameters)
|
||||
i := 0
|
||||
for k, v := range parameters {
|
||||
sb.Append(k + "=" + v)
|
||||
if i < parametersCount-1 {
|
||||
sb.Append("&")
|
||||
}
|
||||
i++
|
||||
}
|
||||
return sb.ToString()
|
||||
}
|
||||
|
||||
func randNumber() string {
|
||||
str := "0123456789"
|
||||
bytes := []byte(str)
|
||||
var result []byte
|
||||
r := rand.New(rand.NewSource(time.Now().UnixNano()))
|
||||
for i := 0; i < 4; i++ {
|
||||
result = append(result, bytes[r.Intn(len(bytes))])
|
||||
}
|
||||
return string(result)
|
||||
}
|
||||
124
pkg/common/netease/ImClient_test.go
Normal file
124
pkg/common/netease/ImClient_test.go
Normal file
@ -0,0 +1,124 @@
|
||||
package Netease
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// 测试获取IM用户信息
|
||||
func TestImClient_GetImUserInfo(t *testing.T) {
|
||||
type fields struct {
|
||||
AppKey string
|
||||
AppSecret string
|
||||
}
|
||||
type args struct {
|
||||
userId string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
args args
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "test",
|
||||
fields: fields{
|
||||
AppKey: "543b1a440b940b170fccdf494839efc01",
|
||||
AppSecret: "41134093938f1",
|
||||
},
|
||||
args: args{
|
||||
// 2251bae8a0514e6892f0374f5dd260d4
|
||||
// b8af4bebe2064435974ba2340d852055
|
||||
userId: "fcda23bc00e641f5ae17492503b566ed",
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
client := &ImClient{
|
||||
AppKey: tt.fields.AppKey,
|
||||
AppSecret: tt.fields.AppSecret,
|
||||
}
|
||||
if err := client.GetImUserInfo(tt.args.userId); (err != nil) != tt.wantErr {
|
||||
t.Errorf("GetImUserInfo() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// 测试注册IM用户
|
||||
func TestImClient_CreateImUser(t *testing.T) {
|
||||
type fields struct {
|
||||
AppKey string
|
||||
AppSecret string
|
||||
}
|
||||
type args struct {
|
||||
userId string
|
||||
nickname string
|
||||
avatar string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
args args
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "test",
|
||||
fields: fields{
|
||||
AppKey: "543b1a440b940b170fccdf494839efc01",
|
||||
AppSecret: "41134093938f1",
|
||||
},
|
||||
args: args{
|
||||
// 2251bae8a0514e6892f0374f5dd260d4
|
||||
// b8af4bebe2064435974ba2340d852055
|
||||
userId: "fcda23bc00e641f5ae17492503b566ed",
|
||||
nickname: "杏",
|
||||
avatar: "https://photo-app.ddegame.cn/upload/19986a27-3bae-49f7-9643-cd18cda87557.jpg",
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
client := &ImClient{
|
||||
AppKey: tt.fields.AppKey,
|
||||
AppSecret: tt.fields.AppSecret,
|
||||
}
|
||||
if err := client.CreateImUser(tt.args.userId, tt.args.nickname, tt.args.avatar); (err != nil) != tt.wantErr {
|
||||
t.Errorf("GetImUserInfo() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// 测试注册IM用户
|
||||
func TestImClient_CreateImUserOne(t *testing.T) {
|
||||
client := &ImClient{
|
||||
AppKey: "543b1a440b940b170fccdf494839efc01",
|
||||
AppSecret: "41134093938f1",
|
||||
}
|
||||
client.CreateImUser("fcda23bc00e641f5ae17492503b566ed", "杏", "https://photo-app.ddegame.cn/upload/19986a27-3bae-49f7-9643-cd18cda87557.jpg")
|
||||
}
|
||||
|
||||
func TestImClient_CreateChatGroup(t *testing.T) {
|
||||
client := &ImClient{
|
||||
AppKey: "543b1a440b940b170fccdf494839efc01",
|
||||
AppSecret: "41134093938f1",
|
||||
}
|
||||
groupId, err := client.CreateChatGroup(context.Background(), "e1fbefbbd77a402e8c2101a0ebe15f5d", "测试群", []string{"e1fbefbbd77a402e8c2101a0ebe15f5d"})
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
println(groupId)
|
||||
}
|
||||
|
||||
func init() {
|
||||
// viper.SetConfigName("dev.yaml")
|
||||
// viper.AddConfigPath("../../../configs/admin/")
|
||||
// viper.SetConfigType("yaml")
|
||||
// _ = viper.ReadInConfig()
|
||||
// log.Init()
|
||||
// datasource.InitMySQlMaster()
|
||||
}
|
||||
33
pkg/common/netease/ImResponse.go
Normal file
33
pkg/common/netease/ImResponse.go
Normal file
@ -0,0 +1,33 @@
|
||||
package Netease
|
||||
|
||||
type ImResponse struct {
|
||||
Code int `json:"code"`
|
||||
Desc interface{} `json:"desc"`
|
||||
}
|
||||
|
||||
// 获取聊天室在线列表返回对象
|
||||
type GetChatroomMemberResponse struct {
|
||||
Data []ChatroomMemberDTO `json:"data"`
|
||||
}
|
||||
|
||||
// 聊天室会员
|
||||
type ChatroomMemberDTO struct {
|
||||
RoomId int `json:"roomid"`
|
||||
AccId string `json:"accid"`
|
||||
OnlineStat bool `json:"onlineStat"`
|
||||
}
|
||||
|
||||
// 创建聊天室返回结果
|
||||
type CreateChatroomResponse struct {
|
||||
Code int `json:"code"`
|
||||
Chatroom NeteaseChatroomDTO `json:"chatroom"`
|
||||
}
|
||||
|
||||
// 聊天室会员
|
||||
type NeteaseChatroomDTO struct {
|
||||
RoomId int `json:"roomid"`
|
||||
Valid bool `json:"valid"`
|
||||
RoomName string `json:"name"`
|
||||
Ext string `json:"ext"`
|
||||
Creator string `json:"creator"`
|
||||
}
|
||||
10
pkg/common/netease/dto/ImChatroomOnlineMember.go
Normal file
10
pkg/common/netease/dto/ImChatroomOnlineMember.go
Normal file
@ -0,0 +1,10 @@
|
||||
package yunxin
|
||||
|
||||
// 聊天室在线成员对象
|
||||
type ImChatroomOnlineMember struct {
|
||||
MessageRoomId int `json:"roomid"`
|
||||
UserId string `json:"accid"`
|
||||
EnterTime int64 `json:"enterTime"`
|
||||
Type string `json:"type"`
|
||||
OnlineStat bool `json:"onlineStat"`
|
||||
}
|
||||
9
pkg/common/netease/dto/ImUserExtData.go
Normal file
9
pkg/common/netease/dto/ImUserExtData.go
Normal file
@ -0,0 +1,9 @@
|
||||
package yunxin
|
||||
|
||||
// IM用户扩展信息 会话列表用户数据从IM信息获取
|
||||
type ImUserExtData struct {
|
||||
VipLevel string // Vip等级
|
||||
AvatarDecoration string // 头饰
|
||||
GroupType string
|
||||
VipConfig string // json字符串dto.UserVipConfigDTO
|
||||
}
|
||||
7
pkg/common/netease/dto/UpdateRoomInfoRequest.go
Normal file
7
pkg/common/netease/dto/UpdateRoomInfoRequest.go
Normal file
@ -0,0 +1,7 @@
|
||||
package yunxin
|
||||
|
||||
// 更新聊天室信息请求对象
|
||||
type UpdateRoomInfoRequest struct {
|
||||
Roomid string `json:"roomid"` // 房间ID
|
||||
NotifyExt string `json:"notifyExt" // 扩展信息`
|
||||
}
|
||||
38
pkg/common/netease/req.go
Normal file
38
pkg/common/netease/req.go
Normal file
@ -0,0 +1,38 @@
|
||||
package Netease
|
||||
|
||||
// CreateChatGroupReq 创建群组请求
|
||||
// https://doc.yunxin.163.com/messaging2/server-apis/DIwODUwMTE?platform=server
|
||||
type CreateChatGroupReq struct {
|
||||
OwnerAccountID string `json:"owner_account_id"` // M 群主(创建者)的 IM 账号 ID。
|
||||
TeamType int `json:"team_type"` // M 1:高级群。2:超大群。
|
||||
Name string `json:"name"` // M 长度上限 64 位字符。
|
||||
Icon string `json:"icon,omitempty"` // O 群组头像的 URL 地址,例如 "https://netease/xxx.png",长度上限 1024 位字符。
|
||||
Announcement string `json:"announcement,omitempty"` // O 群组公告,长度上限 1024 位字符。
|
||||
Intro string `json:"intro,omitempty"` // O群组简介,长度上限 512 位字符。
|
||||
MembersLimit int `json:"members_limit"` // O 群组成员数上限(包含群主),默认为 200。可设置范围的为:[2 ~ 200]。
|
||||
ServerExtension string `json:"server_extension,omitempty"` // O 自定义群组扩展字段,第三方可以跟据此属性自定义扩展自己的群属性,建议封装成 JSONObject 格式,{key:value}。长度上限 1024 位字符。 对应 SDK 的 serverExtension 字段。
|
||||
CustomerExtension string `json:"customer_extension,omitempty"` // O 客户端自定义扩展字段,仅服务器 API 可以设置,SDK 仅负责透传,不解析内容。 对应 SDK 的 customerExtension 字段。
|
||||
Extension string `json:"extension,omitempty"` // M 创建群组时邀请入群的成员列表。
|
||||
InviteAccountIDs []string `json:"invite_account_ids,omitempty"` // M 邀请入群的附言,长度上限 150 位字符。
|
||||
InviteMsg string `json:"invite_msg,omitempty"`
|
||||
Configuration *TeamConfiguration `json:"configuration,omitempty"`
|
||||
AntispamConfiguration *AntispamConfig `json:"antispam_configuration,omitempty"`
|
||||
}
|
||||
|
||||
type TeamConfiguration struct {
|
||||
JoinMode int `json:"join_mode"` // 通过 SDK 侧操作申请入群的验证方式。 0(默认):无需验证,直接入群。 1:需要群主或管理员验证通过才能入群。 2:不允许任何人申请入群。
|
||||
AgreeMode int `json:"agree_mode"` // 邀请入群时是否需要被邀请人的同意。 0(默认):需要被邀请人同意才能入群。 1:不需要被邀请人同意,直接入群。
|
||||
InviteMode int `json:"invite_mode"` // 邀请权限,即谁可以邀请他人入群。 0(默认):群主和管理员。 1:所有人。
|
||||
UpdateTeamInfoMode int `json:"update_team_info_mode"`
|
||||
UpdateExtensionMode int `json:"update_extension_mode"`
|
||||
}
|
||||
|
||||
type AntispamConfig struct {
|
||||
Enabled bool `json:"enabled"`
|
||||
BusinessIDMap *BusinessIDMap `json:"business_id_map,omitempty"`
|
||||
}
|
||||
|
||||
type BusinessIDMap struct {
|
||||
Type int `json:"type"`
|
||||
AntispamBusinessID string `json:"antispam_business_id"`
|
||||
}
|
||||
35
pkg/common/netease/rsp.go
Normal file
35
pkg/common/netease/rsp.go
Normal file
@ -0,0 +1,35 @@
|
||||
package Netease
|
||||
|
||||
type CreateChatGroupRsp struct {
|
||||
FailedList []*FailedMember `json:"failed_list,omitempty"`
|
||||
TeamInfo *TeamInfo `json:"team_info"`
|
||||
}
|
||||
|
||||
type FailedMember struct {
|
||||
AccountID string `json:"account_id"`
|
||||
ErrorCode int `json:"error_code"`
|
||||
ErrorMsg string `json:"error_msg"`
|
||||
}
|
||||
|
||||
type TeamInfo struct {
|
||||
TeamID int64 `json:"team_id"`
|
||||
OwnerAccountID string `json:"owner_account_id"`
|
||||
Name string `json:"name"`
|
||||
Icon string `json:"icon,omitempty"`
|
||||
Announcement string `json:"announcement,omitempty"`
|
||||
Intro string `json:"intro,omitempty"`
|
||||
MembersLimit int `json:"members_limit"`
|
||||
MemberCount int `json:"member_count"`
|
||||
ServerExtension string `json:"server_extension,omitempty"`
|
||||
CustomerExtension string `json:"customer_extension,omitempty"`
|
||||
CreateTime int64 `json:"create_time"`
|
||||
UpdateTime int64 `json:"update_time"`
|
||||
TeamType int `json:"team_type"`
|
||||
Configuration *TeamConfiguration `json:"configuration,omitempty"`
|
||||
}
|
||||
|
||||
type BaseRes[T any] struct {
|
||||
Code int
|
||||
Msg string
|
||||
Data T
|
||||
}
|
||||
45
pkg/common/network/response.go
Normal file
45
pkg/common/network/response.go
Normal file
@ -0,0 +1,45 @@
|
||||
package network
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
)
|
||||
|
||||
const (
|
||||
SuccessCode = "6000" // 成功
|
||||
NeedLogin = "6018" // 登陆过期
|
||||
ErrorCode = "6020" // 错误
|
||||
|
||||
)
|
||||
|
||||
type Response struct {
|
||||
Code string
|
||||
Result interface{}
|
||||
Msg string
|
||||
}
|
||||
|
||||
type EmptyResponse struct {
|
||||
}
|
||||
|
||||
func Fail(msg string) Response {
|
||||
response := Response{Code: ErrorCode, Msg: msg}
|
||||
return response
|
||||
}
|
||||
|
||||
func Invalid() string {
|
||||
response := Response{Code: NeedLogin, Msg: "用户身份已过期"}
|
||||
str, _ := json.Marshal(response)
|
||||
return string(str)
|
||||
}
|
||||
|
||||
func Success(data interface{}) Response {
|
||||
response := Response{Code: SuccessCode, Result: data}
|
||||
return response
|
||||
}
|
||||
|
||||
func Page(data interface{}, count int64) Response {
|
||||
response := Response{Code: SuccessCode, Result: map[string]interface{}{
|
||||
"List": data,
|
||||
"Count": count,
|
||||
}}
|
||||
return response
|
||||
}
|
||||
148
pkg/common/pinyin/pinyin.go
Normal file
148
pkg/common/pinyin/pinyin.go
Normal file
@ -0,0 +1,148 @@
|
||||
package pinyin
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
type vowel int32
|
||||
|
||||
var (
|
||||
ys = []vowel{'ā', 'ē', 'ī', 'ō', 'ū', 'ǖ', 'Ā', 'Ē', 'Ī', 'Ō', 'Ū', 'Ǖ'} // 单韵母 一声
|
||||
es = []vowel{'á', 'é', 'í', 'ó', 'ú', 'ǘ', 'Á', 'É', 'Í', 'Ó', 'Ú', 'Ǘ'} // 单韵母 二声
|
||||
ss = []vowel{'ǎ', 'ě', 'ǐ', 'ǒ', 'ǔ', 'ǚ', 'Ǎ', 'Ě', 'Ǐ', 'Ǒ', 'Ǔ', 'Ǚ'} // 单韵母 三声
|
||||
fs = []vowel{'à', 'è', 'ì', 'ò', 'ù', 'ǜ', 'À', 'È', 'Ì', 'Ò', 'Ù', 'Ǜ'} // 单韵母 四声
|
||||
ws = []vowel{'a', 'e', 'i', 'o', 'u', 'v', 'A', 'E', 'I', 'O', 'U', 'V'} // 单韵母 无声调
|
||||
)
|
||||
|
||||
var (
|
||||
pinyinTemp map[vowel]interface{}
|
||||
toneTemp map[vowel]vowel
|
||||
)
|
||||
|
||||
const (
|
||||
Tone string = "带声调的拼音" // 带声调的拼音 例如:Cào
|
||||
InitialsInCapitals string = "首字母大写不带声调" // 首字母大写不带声调 例如:Cao
|
||||
None string = "" //如果匹配不到汉字,就靠大家维护下 【匹配失败,手动添加代码到pinyin.txt】
|
||||
)
|
||||
|
||||
func LoadingPYFile(filename string) {
|
||||
f, err := os.Open(filename)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
pinyinTemp = make(map[vowel]interface{}, 0)
|
||||
toneTemp = make(map[vowel]vowel)
|
||||
for i, t := range ys {
|
||||
toneTemp[t] = ws[i]
|
||||
}
|
||||
for i, t := range es {
|
||||
toneTemp[t] = ws[i]
|
||||
}
|
||||
for i, t := range ss {
|
||||
toneTemp[t] = ws[i]
|
||||
}
|
||||
for i, t := range fs {
|
||||
toneTemp[t] = ws[i]
|
||||
}
|
||||
defer func() {
|
||||
_ = f.Close()
|
||||
}()
|
||||
scanner := bufio.NewScanner(f)
|
||||
for scanner.Scan() {
|
||||
//单行分割取出拼音
|
||||
str := strings.Split(scanner.Text(), "=>")
|
||||
if len(str) < 2 {
|
||||
continue
|
||||
}
|
||||
i, err := strconv.ParseInt(str[0], 16, 32)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
pinyinTemp[vowel(i)] = str[1]
|
||||
//fmt.Println(pinyinTemp[vowel(i)])
|
||||
}
|
||||
}
|
||||
|
||||
func PY(source string) (string, error) {
|
||||
return PYSplit(source, "", "")
|
||||
}
|
||||
|
||||
func PYSplit(source string, split string, types string) (string, error) {
|
||||
hz := []vowel(source)
|
||||
words := make([]string, 0)
|
||||
for _, s := range hz {
|
||||
word, err := _vowel(s, types)
|
||||
if err != nil {
|
||||
return None, err
|
||||
}
|
||||
if len(word) > 0 {
|
||||
words = append(words, word)
|
||||
}
|
||||
}
|
||||
return strings.Join(words, split), nil
|
||||
}
|
||||
|
||||
func _vowel(source vowel, types string) (string, error) {
|
||||
switch types {
|
||||
case Tone:
|
||||
return getTone(source), nil
|
||||
case InitialsInCapitals:
|
||||
return getInitialsInCapitals(source), nil
|
||||
default:
|
||||
return getDefault(source), nil
|
||||
}
|
||||
}
|
||||
|
||||
func getTone(source vowel) string {
|
||||
if pinyinTemp[source] != nil {
|
||||
return pinyinTemp[source].(string)
|
||||
}
|
||||
return string(source)
|
||||
}
|
||||
|
||||
func getInitialsInCapitals(source vowel) string {
|
||||
def := getDefault(source)
|
||||
var result string
|
||||
if def == "" {
|
||||
return def
|
||||
}
|
||||
str := []vowel(def)
|
||||
if str[0] > 32 {
|
||||
str[0] = str[0] - 32
|
||||
}
|
||||
for _, v := range str {
|
||||
result += string(v)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func getDefault(source vowel) string {
|
||||
tone := getTone(source)
|
||||
var result string
|
||||
if tone == "" {
|
||||
return None
|
||||
}
|
||||
resultLen := make([]vowel, utf8.RuneCountInString(tone))
|
||||
count := 0
|
||||
for _, t := range tone {
|
||||
changes, ok := toneTemp[vowel(t)]
|
||||
if ok {
|
||||
resultLen[count] = changes
|
||||
} else {
|
||||
resultLen[count] = vowel(t)
|
||||
}
|
||||
count++
|
||||
}
|
||||
for _, v := range resultLen {
|
||||
result += string(v)
|
||||
}
|
||||
return result
|
||||
}
|
||||
41208
pkg/common/pinyin/pinyin.txt
Normal file
41208
pkg/common/pinyin/pinyin.txt
Normal file
File diff suppressed because it is too large
Load Diff
9
pkg/common/pinyin/pinyin_test.go
Normal file
9
pkg/common/pinyin/pinyin_test.go
Normal file
@ -0,0 +1,9 @@
|
||||
package pinyin
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestTo_Py(t *testing.T) {
|
||||
LoadingPYFile("./pinyin.txt")
|
||||
s, _ := PY("3425另264325一4个44平444台")
|
||||
println(s)
|
||||
}
|
||||
30
pkg/common/req/req.go
Normal file
30
pkg/common/req/req.go
Normal file
@ -0,0 +1,30 @@
|
||||
package req
|
||||
|
||||
const (
|
||||
defaultPage = 1
|
||||
defaultSize = 10
|
||||
)
|
||||
|
||||
type Page struct {
|
||||
Page int64 `json:"page" form:"page" uri:"page"`
|
||||
Size int64 `json:"size" form:"size" uri:"size"`
|
||||
}
|
||||
|
||||
func (p *Page) check() {
|
||||
if p.Page < 1 {
|
||||
p.Page = defaultPage
|
||||
}
|
||||
if p.Size <= 0 {
|
||||
p.Size = defaultSize
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Page) Offset() int {
|
||||
p.check()
|
||||
return int(p.Page*p.Size - p.Size)
|
||||
}
|
||||
|
||||
func (p *Page) Limit() int {
|
||||
p.check()
|
||||
return int(p.Size)
|
||||
}
|
||||
154
pkg/common/util/string_util.go
Normal file
154
pkg/common/util/string_util.go
Normal file
@ -0,0 +1,154 @@
|
||||
package util
|
||||
|
||||
import (
|
||||
"crypto/md5"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
PhotoDomainUrl = "https://photo-app.ddegame.cn/"
|
||||
TimeLayout = "2006-01-02 15:04:05"
|
||||
DateLayout = "2006-01-02"
|
||||
DateLayoutShort = "20060102"
|
||||
)
|
||||
|
||||
func FullPhotoUrl(path string) string {
|
||||
if len(path) == 0 {
|
||||
return ""
|
||||
}
|
||||
if strings.Index(path, "http") == 0 {
|
||||
return path
|
||||
}
|
||||
return PhotoDomainUrl + path
|
||||
}
|
||||
|
||||
func Md5ForList(s ...string) string {
|
||||
sort.Strings(s)
|
||||
h := md5.New()
|
||||
h.Write([]byte(strings.Join(s, "")))
|
||||
return hex.EncodeToString(h.Sum(nil))
|
||||
}
|
||||
|
||||
func StringToInt(source string) int {
|
||||
target, _ := strconv.Atoi(source)
|
||||
return target
|
||||
}
|
||||
|
||||
func StringToFloat(source string) float64 {
|
||||
target, _ := strconv.ParseFloat(source, 64)
|
||||
return target
|
||||
}
|
||||
|
||||
func StringIntPlus(s1, s2 string) string {
|
||||
return strconv.Itoa(StringToInt(s1) + StringToInt(s2))
|
||||
}
|
||||
|
||||
func StringIntMultiply(s1, s2 string) string {
|
||||
return strconv.Itoa(StringToInt(s1) * StringToInt(s2))
|
||||
}
|
||||
|
||||
func StringIntSub(s1, s2 string) string {
|
||||
return strconv.Itoa(StringToInt(s1) - StringToInt(s2))
|
||||
}
|
||||
|
||||
func StringFloatSub(s1, s2 string) string {
|
||||
return strconv.FormatFloat(StringToFloat(s1)-StringToFloat(s2), 'f', -1, 64)
|
||||
}
|
||||
|
||||
func ListToSet(list []string) (set []string) {
|
||||
m := make(map[string]bool, 0)
|
||||
for i := range list {
|
||||
m[list[i]] = true
|
||||
}
|
||||
for k := range m {
|
||||
set = append(set, k)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func ToJson(source interface{}) []byte {
|
||||
b, _ := json.Marshal(source)
|
||||
return b
|
||||
}
|
||||
|
||||
func ToJsonString(source interface{}) string {
|
||||
return string(ToJson(source))
|
||||
}
|
||||
|
||||
func NowTimeToString() string {
|
||||
return time.Now().Format(TimeLayout)
|
||||
}
|
||||
|
||||
func NowTimeIncreaseString(t time.Duration) string {
|
||||
return time.Now().Add(t).Format(TimeLayout)
|
||||
}
|
||||
|
||||
func NowDateToString() string {
|
||||
return time.Now().Format(DateLayout)
|
||||
}
|
||||
|
||||
func NowDateToStringShort() string {
|
||||
return time.Now().Format(DateLayoutShort)
|
||||
}
|
||||
|
||||
func DateToString(source time.Time) string {
|
||||
return source.Format(TimeLayout)
|
||||
}
|
||||
|
||||
func Md5(s string) string {
|
||||
h := md5.New()
|
||||
h.Write([]byte(s))
|
||||
return hex.EncodeToString(h.Sum(nil))
|
||||
}
|
||||
|
||||
func ProcessTimeStr(s string) (string, error) {
|
||||
// 定义两种时间格式
|
||||
layout1 := "2006-01-02 15:04:05" // 无时区的格式
|
||||
layout2 := "2006-01-02 15:04:05 -0700 MST" // 带时区的格式(包含偏移和时区名称)
|
||||
|
||||
// 尝试解析为无时区格式
|
||||
_, err1 := time.Parse(layout1, s)
|
||||
if err1 == nil {
|
||||
return s, nil // 直接返回原字符串
|
||||
}
|
||||
|
||||
// 尝试解析为带时区格式
|
||||
t2, err2 := time.Parse(layout2, s)
|
||||
if err2 == nil {
|
||||
// 格式化为无时区格式
|
||||
return t2.Format(layout1), nil
|
||||
}
|
||||
|
||||
// 两种格式都不匹配
|
||||
return "", fmt.Errorf("invalid time format: %s", s)
|
||||
}
|
||||
|
||||
// 解析url里的参数为map
|
||||
func ParseUrlParameter(fullUrl string) (result map[string]string) {
|
||||
|
||||
result = make(map[string]string)
|
||||
|
||||
// 解析URL
|
||||
parsedURL, err := url.Parse(fullUrl)
|
||||
if err != nil {
|
||||
fmt.Printf("解析URL失败: %v\n", err)
|
||||
return
|
||||
}
|
||||
|
||||
// 解析查询参数
|
||||
queryParams := parsedURL.Query()
|
||||
|
||||
// 输出所有参数
|
||||
for key, values := range queryParams {
|
||||
result[key] = values[0]
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
17
pkg/common/util/string_util_test.go
Normal file
17
pkg/common/util/string_util_test.go
Normal file
@ -0,0 +1,17 @@
|
||||
package util
|
||||
|
||||
import (
|
||||
"servicebase/pkg/common"
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func Test_processTimeStr(t *testing.T) {
|
||||
tmp, e := ProcessTimeStr("2025-05-29 09:08:38 +0800 CST")
|
||||
fmt.Printf("%v %v\n", tmp, e)
|
||||
}
|
||||
|
||||
func TestParseUrlParameter(t *testing.T) {
|
||||
// assets/img/op_1754967614.png?c=#000000&s=160
|
||||
ParseUrlParameter(common.FullPhotoUrl("assets/img/op_1754967614.png?c=%23000000&s=160"))
|
||||
}
|
||||
Reference in New Issue
Block a user