Skip to content

Commit a5188a6

Browse files
author
Athurg Feng
committed
从原代码库剥离为单独的仓库
0 parents  commit a5188a6

File tree

7 files changed

+456
-0
lines changed

7 files changed

+456
-0
lines changed

department.go

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
package dingtalk
2+
3+
import (
4+
"encoding/json"
5+
"fmt"
6+
"net/http"
7+
"net/url"
8+
)
9+
10+
// API地址
11+
const (
12+
DEPARTMENT_LIST_URL = DINGTALK_API_URL + "/department/list"
13+
)
14+
15+
// 部门
16+
type Department struct {
17+
Id int
18+
Name string
19+
ParentId int
20+
CreateDeptGroup bool
21+
AutoAddUser bool
22+
Ext string
23+
}
24+
25+
// 获取部门列表API的返回数据
26+
type DepartmentListResponse struct {
27+
CommonResponse
28+
Department []Department
29+
}
30+
31+
// 获取指定部门的子部门列表
32+
func GetDepartmentList(id int, fetchChild bool) ([]Department, error) {
33+
param := url.Values{
34+
"access_token": {accessToken},
35+
"fetch_child": {fmt.Sprintf("%t", fetchChild)},
36+
}
37+
38+
if id != 0 {
39+
param.Set("id", fmt.Sprintf("%d", id))
40+
41+
}
42+
43+
resp, err := http.Get(DEPARTMENT_LIST_URL + "?" + param.Encode())
44+
if err != nil {
45+
return nil, err
46+
}
47+
defer resp.Body.Close()
48+
49+
var info DepartmentListResponse
50+
err = json.NewDecoder(resp.Body).Decode(&info)
51+
if err != nil {
52+
return nil, err
53+
}
54+
55+
if err := info.CommonResponse.Error(); err != nil {
56+
return nil, err
57+
}
58+
59+
return info.Department, nil
60+
}
61+
62+
// 获取所有部门列表
63+
func GetAllDepartments() ([]Department, error) {
64+
return GetDepartmentList(0, true)
65+
}
66+
67+
// 获取重复(部门名称)的部门信息
68+
func DumpDuplicatedDepartments() (map[string]int, error) {
69+
deptCount := map[string]int{}
70+
71+
depts, err := GetDepartmentList(0, true)
72+
if err != nil {
73+
return nil, err
74+
}
75+
76+
for _, dept := range depts {
77+
deptCount[dept.Name] += 1
78+
}
79+
80+
for dept, count := range deptCount {
81+
if count == 1 {
82+
delete(deptCount, dept)
83+
}
84+
}
85+
86+
return deptCount, nil
87+
}
88+
89+
// 获取部门名称-ID映射表
90+
func GetDepartmentIdMap() (map[string]int, error) {
91+
// 获取所有部门信息
92+
depts, err := GetDepartmentList(0, true)
93+
if err != nil {
94+
return nil, err
95+
}
96+
97+
//检查是否有重名部门
98+
deptCount := map[string]int{}
99+
nameIdMap := map[string]int{}
100+
for _, dept := range depts {
101+
deptCount[dept.Name] += 1
102+
nameIdMap[dept.Name] = dept.Id
103+
}
104+
105+
for dept, count := range deptCount {
106+
if count == 1 {
107+
delete(deptCount, dept)
108+
}
109+
}
110+
111+
if len(deptCount) > 0 {
112+
return nil, fmt.Errorf("部分部门重名,重名部门包括%s", deptCount)
113+
}
114+
115+
return nameIdMap, nil
116+
}

dingtalk.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package dingtalk
2+
3+
import (
4+
"fmt"
5+
)
6+
7+
// 钉钉API地址
8+
const (
9+
DINGTALK_API_URL = "https://oapi.dingtalk.com"
10+
)
11+
12+
// 钉钉API公共响应
13+
type CommonResponse struct {
14+
ErrCode int
15+
ErrMsg string
16+
}
17+
18+
func (resp *CommonResponse) Error() error {
19+
if resp.ErrCode != 0 || (resp.ErrMsg != "ok" && resp.ErrMsg != "") {
20+
return fmt.Errorf("[%d]%s", resp.ErrCode, resp.ErrMsg)
21+
}
22+
23+
return nil
24+
}

gettoken.go

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package dingtalk
2+
3+
import (
4+
"encoding/json"
5+
"net/http"
6+
"net/url"
7+
)
8+
9+
// API地址
10+
const (
11+
GETTOKEN_URL = DINGTALK_API_URL + "/gettoken"
12+
)
13+
14+
var accessToken string
15+
16+
// 刷新AccessToken
17+
func RefreshAccessToken(appkey, appsecret string) error {
18+
param := url.Values{
19+
"appkey": {appkey},
20+
"appsecret": {appsecret},
21+
}
22+
23+
resp, err := http.Get(GETTOKEN_URL + "?" + param.Encode())
24+
if err != nil {
25+
return err
26+
}
27+
defer resp.Body.Close()
28+
29+
var info struct {
30+
CommonResponse
31+
AccessToken string `json:"access_token"`
32+
}
33+
34+
err = json.NewDecoder(resp.Body).Decode(&info)
35+
if err != nil {
36+
return err
37+
}
38+
39+
if err := info.CommonResponse.Error(); err != nil {
40+
return err
41+
}
42+
43+
accessToken = info.AccessToken
44+
return nil
45+
}

message.go

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
package dingtalk
2+
3+
// 钉钉消息
4+
type Message struct {
5+
MsgType string `json:"msgtype"`
6+
7+
Markdown *MessagePartialMarkdown `json:"markdown,omitempty"`
8+
Text *MessagePartialText `json:"text,omitempty"`
9+
10+
At *MessagePartialAt `json:"at,omitempty"`
11+
}
12+
13+
// 钉钉消息AT部分
14+
type MessagePartialAt struct {
15+
AtMobiles []string `json:"atMobiles"`
16+
AtDingtalkIds []string `json:"atDingtalkIds"`
17+
IsAtAll bool `json:"isAtAll"`
18+
}
19+
20+
// 钉钉消息文本部分
21+
type MessagePartialText struct {
22+
Content string `json:"content"`
23+
}
24+
25+
// 钉钉消息Markdown部分
26+
type MessagePartialMarkdown struct {
27+
Title string `json:"title"`
28+
Text string `json:"text"`
29+
}
30+
31+
// 创建一条Markdown消息
32+
func NewMarkdownMessage(title, text string) Message {
33+
partial := &MessagePartialMarkdown{
34+
Text: text,
35+
Title: title,
36+
}
37+
msg := Message{
38+
MsgType: "markdown",
39+
Markdown: partial,
40+
}
41+
42+
return msg
43+
}
44+
45+
// 创建一条文本消息
46+
func NewTextMessage(content string) Message {
47+
partial := &MessagePartialText{
48+
Content: content,
49+
}
50+
msg := Message{
51+
MsgType: "text",
52+
Text: partial,
53+
}
54+
55+
return msg
56+
}

robot.go

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package dingtalk
2+
3+
import (
4+
"crypto/hmac"
5+
"crypto/sha256"
6+
"encoding/base64"
7+
"net/http"
8+
)
9+
10+
// 钉钉企业内部机器人请求结构
11+
type RobotRequest struct {
12+
MsgType string
13+
Text struct {
14+
Content string
15+
}
16+
17+
MsgId string
18+
CreateAt int
19+
20+
ConversationType string
21+
ConversationId string
22+
ConversationTitle string
23+
SenderId string
24+
SenderNick string
25+
SenderCorpId string
26+
SenderStaffId string
27+
ChatbotUserId string
28+
AtUsers []struct {
29+
DingtalkId string
30+
StaffId string
31+
}
32+
}
33+
34+
func IsValidateRobotRequest(appSecret string, r *http.Request) bool {
35+
s := r.Header.Get("timestamp") + "\n" + appSecret
36+
37+
mac := hmac.New(sha256.New, []byte(appSecret))
38+
mac.Write([]byte(s))
39+
expectMac := mac.Sum(nil)
40+
41+
sign := base64.StdEncoding.EncodeToString(expectMac)
42+
return sign == r.Header.Get("sign")
43+
}

0 commit comments

Comments
 (0)