2017-11-21 12:26:43 +08:00
// Copyright 2017 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
2019-11-04 06:13:25 +08:00
package webhook
2017-11-21 12:26:43 +08:00
import (
"encoding/json"
"fmt"
"strings"
2019-11-04 06:13:25 +08:00
"code.gitea.io/gitea/models"
2019-03-27 17:33:00 +08:00
"code.gitea.io/gitea/modules/git"
2019-05-11 18:21:34 +08:00
api "code.gitea.io/gitea/modules/structs"
2019-03-27 17:33:00 +08:00
2017-11-21 12:26:43 +08:00
dingtalk "github.com/lunny/dingtalk_webhook"
)
type (
// DingtalkPayload represents
DingtalkPayload dingtalk . Payload
)
// SetSecret sets the dingtalk secret
func ( p * DingtalkPayload ) SetSecret ( _ string ) { }
// JSONPayload Marshals the DingtalkPayload to json
func ( p * DingtalkPayload ) JSONPayload ( ) ( [ ] byte , error ) {
data , err := json . MarshalIndent ( p , "" , " " )
if err != nil {
return [ ] byte { } , err
}
return data , nil
}
func getDingtalkCreatePayload ( p * api . CreatePayload ) ( * DingtalkPayload , error ) {
// created tag/branch
refName := git . RefEndName ( p . Ref )
title := fmt . Sprintf ( "[%s] %s %s created" , p . Repo . FullName , p . RefType , refName )
return & DingtalkPayload {
MsgType : "actionCard" ,
ActionCard : dingtalk . ActionCard {
Text : title ,
Title : title ,
HideAvatar : "0" ,
2018-05-21 10:28:29 +08:00
SingleTitle : fmt . Sprintf ( "view ref %s" , refName ) ,
2017-11-21 12:26:43 +08:00
SingleURL : p . Repo . HTMLURL + "/src/" + refName ,
} ,
} , nil
}
2018-05-16 22:01:55 +08:00
func getDingtalkDeletePayload ( p * api . DeletePayload ) ( * DingtalkPayload , error ) {
// created tag/branch
refName := git . RefEndName ( p . Ref )
title := fmt . Sprintf ( "[%s] %s %s deleted" , p . Repo . FullName , p . RefType , refName )
return & DingtalkPayload {
MsgType : "actionCard" ,
ActionCard : dingtalk . ActionCard {
Text : title ,
Title : title ,
HideAvatar : "0" ,
2018-05-21 10:28:29 +08:00
SingleTitle : fmt . Sprintf ( "view ref %s" , refName ) ,
2018-05-16 22:01:55 +08:00
SingleURL : p . Repo . HTMLURL + "/src/" + refName ,
} ,
} , nil
}
func getDingtalkForkPayload ( p * api . ForkPayload ) ( * DingtalkPayload , error ) {
title := fmt . Sprintf ( "%s is forked to %s" , p . Forkee . FullName , p . Repo . FullName )
return & DingtalkPayload {
MsgType : "actionCard" ,
ActionCard : dingtalk . ActionCard {
Text : title ,
Title : title ,
HideAvatar : "0" ,
SingleTitle : fmt . Sprintf ( "view forked repo %s" , p . Repo . FullName ) ,
SingleURL : p . Repo . HTMLURL ,
} ,
} , nil
}
2017-11-21 12:26:43 +08:00
func getDingtalkPushPayload ( p * api . PushPayload ) ( * DingtalkPayload , error ) {
var (
branchName = git . RefEndName ( p . Ref )
commitDesc string
)
var titleLink , linkText string
if len ( p . Commits ) == 1 {
commitDesc = "1 new commit"
titleLink = p . Commits [ 0 ] . URL
linkText = fmt . Sprintf ( "view commit %s" , p . Commits [ 0 ] . ID [ : 7 ] )
} else {
commitDesc = fmt . Sprintf ( "%d new commits" , len ( p . Commits ) )
titleLink = p . CompareURL
linkText = fmt . Sprintf ( "view commit %s...%s" , p . Commits [ 0 ] . ID [ : 7 ] , p . Commits [ len ( p . Commits ) - 1 ] . ID [ : 7 ] )
}
if titleLink == "" {
titleLink = p . Repo . HTMLURL + "/src/" + branchName
}
title := fmt . Sprintf ( "[%s:%s] %s" , p . Repo . FullName , branchName , commitDesc )
var text string
// for each commit, generate attachment text
for i , commit := range p . Commits {
var authorName string
if commit . Author != nil {
authorName = " - " + commit . Author . Name
}
text += fmt . Sprintf ( "[%s](%s) %s" , commit . ID [ : 7 ] , commit . URL ,
strings . TrimRight ( commit . Message , "\r\n" ) ) + authorName
// add linebreak to each commit but the last
if i < len ( p . Commits ) - 1 {
text += "\n"
}
}
return & DingtalkPayload {
MsgType : "actionCard" ,
ActionCard : dingtalk . ActionCard {
Text : text ,
Title : title ,
HideAvatar : "0" ,
SingleTitle : linkText ,
SingleURL : titleLink ,
} ,
} , nil
}
2018-05-16 22:01:55 +08:00
func getDingtalkIssuesPayload ( p * api . IssuePayload ) ( * DingtalkPayload , error ) {
2020-01-04 16:20:15 -06:00
text , issueTitle , attachmentText , _ := getIssuesPayloadInfo ( p , noneLinkFormatter , true )
2018-05-16 22:01:55 +08:00
return & DingtalkPayload {
MsgType : "actionCard" ,
ActionCard : dingtalk . ActionCard {
2019-12-28 16:55:09 +08:00
Text : text + "\r\n\r\n" + attachmentText ,
2018-05-21 10:28:29 +08:00
//Markdown: "# " + title + "\n" + text,
2019-12-28 16:55:09 +08:00
Title : issueTitle ,
2018-05-16 22:01:55 +08:00
HideAvatar : "0" ,
2018-05-21 10:28:29 +08:00
SingleTitle : "view issue" ,
2018-05-16 22:01:55 +08:00
SingleURL : p . Issue . URL ,
} ,
} , nil
}
func getDingtalkIssueCommentPayload ( p * api . IssueCommentPayload ) ( * DingtalkPayload , error ) {
2020-01-04 16:20:15 -06:00
text , issueTitle , _ := getIssueCommentPayloadInfo ( p , noneLinkFormatter , true )
2019-10-18 17:42:04 -05:00
2018-05-16 22:01:55 +08:00
return & DingtalkPayload {
MsgType : "actionCard" ,
ActionCard : dingtalk . ActionCard {
2019-12-28 16:55:09 +08:00
Text : text + "\r\n\r\n" + p . Comment . Body ,
Title : issueTitle ,
2018-05-16 22:01:55 +08:00
HideAvatar : "0" ,
2018-05-21 10:28:29 +08:00
SingleTitle : "view issue comment" ,
2019-12-28 16:55:09 +08:00
SingleURL : p . Comment . HTMLURL ,
2018-05-16 22:01:55 +08:00
} ,
} , nil
}
2017-11-21 12:26:43 +08:00
func getDingtalkPullRequestPayload ( p * api . PullRequestPayload ) ( * DingtalkPayload , error ) {
2020-01-04 16:20:15 -06:00
text , issueTitle , attachmentText , _ := getPullRequestPayloadInfo ( p , noneLinkFormatter , true )
2017-11-21 12:26:43 +08:00
return & DingtalkPayload {
MsgType : "actionCard" ,
ActionCard : dingtalk . ActionCard {
2019-12-28 16:55:09 +08:00
Text : text + "\r\n\r\n" + attachmentText ,
2018-05-21 10:28:29 +08:00
//Markdown: "# " + title + "\n" + text,
2019-12-28 16:55:09 +08:00
Title : issueTitle ,
2017-11-21 12:26:43 +08:00
HideAvatar : "0" ,
SingleTitle : "view pull request" ,
SingleURL : p . PullRequest . HTMLURL ,
} ,
} , nil
}
2019-11-04 06:13:25 +08:00
func getDingtalkPullRequestApprovalPayload ( p * api . PullRequestPayload , event models . HookEventType ) ( * DingtalkPayload , error ) {
2018-12-27 19:04:30 +01:00
var text , title string
switch p . Action {
case api . HookIssueSynchronized :
action , err := parseHookPullRequestEventType ( event )
if err != nil {
return nil , err
}
title = fmt . Sprintf ( "[%s] Pull request review %s : #%d %s" , p . Repository . FullName , action , p . Index , p . PullRequest . Title )
2019-10-18 17:42:04 -05:00
text = p . Review . Content
2018-12-27 19:04:30 +01:00
}
return & DingtalkPayload {
MsgType : "actionCard" ,
ActionCard : dingtalk . ActionCard {
Text : title + "\r\n\r\n" + text ,
Title : title ,
HideAvatar : "0" ,
SingleTitle : "view pull request" ,
SingleURL : p . PullRequest . HTMLURL ,
} ,
} , nil
}
2017-11-21 12:26:43 +08:00
func getDingtalkRepositoryPayload ( p * api . RepositoryPayload ) ( * DingtalkPayload , error ) {
var title , url string
switch p . Action {
case api . HookRepoCreated :
title = fmt . Sprintf ( "[%s] Repository created" , p . Repository . FullName )
url = p . Repository . HTMLURL
return & DingtalkPayload {
MsgType : "actionCard" ,
ActionCard : dingtalk . ActionCard {
Text : title ,
Title : title ,
HideAvatar : "0" ,
SingleTitle : "view repository" ,
SingleURL : url ,
} ,
} , nil
case api . HookRepoDeleted :
title = fmt . Sprintf ( "[%s] Repository deleted" , p . Repository . FullName )
return & DingtalkPayload {
MsgType : "text" ,
Text : struct {
Content string ` json:"content" `
} {
Content : title ,
} ,
} , nil
}
return nil , nil
}
2018-05-16 22:01:55 +08:00
func getDingtalkReleasePayload ( p * api . ReleasePayload ) ( * DingtalkPayload , error ) {
2020-01-04 16:20:15 -06:00
text , _ := getReleasePayloadInfo ( p , noneLinkFormatter , true )
2018-05-21 10:28:29 +08:00
2019-12-28 16:55:09 +08:00
return & DingtalkPayload {
MsgType : "actionCard" ,
ActionCard : dingtalk . ActionCard {
Text : text ,
Title : text ,
HideAvatar : "0" ,
SingleTitle : "view release" ,
SingleURL : p . Release . URL ,
} ,
} , nil
2018-05-16 22:01:55 +08:00
}
2017-11-21 12:26:43 +08:00
// GetDingtalkPayload converts a ding talk webhook into a DingtalkPayload
2019-11-04 06:13:25 +08:00
func GetDingtalkPayload ( p api . Payloader , event models . HookEventType , meta string ) ( * DingtalkPayload , error ) {
2017-11-21 12:26:43 +08:00
s := new ( DingtalkPayload )
switch event {
2019-11-04 06:13:25 +08:00
case models . HookEventCreate :
2017-11-21 12:26:43 +08:00
return getDingtalkCreatePayload ( p . ( * api . CreatePayload ) )
2019-11-04 06:13:25 +08:00
case models . HookEventDelete :
2018-05-16 22:01:55 +08:00
return getDingtalkDeletePayload ( p . ( * api . DeletePayload ) )
2019-11-04 06:13:25 +08:00
case models . HookEventFork :
2018-05-16 22:01:55 +08:00
return getDingtalkForkPayload ( p . ( * api . ForkPayload ) )
2019-11-04 06:13:25 +08:00
case models . HookEventIssues :
2018-05-16 22:01:55 +08:00
return getDingtalkIssuesPayload ( p . ( * api . IssuePayload ) )
2019-11-04 06:13:25 +08:00
case models . HookEventIssueComment :
2018-05-16 22:01:55 +08:00
return getDingtalkIssueCommentPayload ( p . ( * api . IssueCommentPayload ) )
2019-11-04 06:13:25 +08:00
case models . HookEventPush :
2017-11-21 12:26:43 +08:00
return getDingtalkPushPayload ( p . ( * api . PushPayload ) )
2019-11-04 06:13:25 +08:00
case models . HookEventPullRequest :
2017-11-21 12:26:43 +08:00
return getDingtalkPullRequestPayload ( p . ( * api . PullRequestPayload ) )
2019-11-04 06:13:25 +08:00
case models . HookEventPullRequestApproved , models . HookEventPullRequestRejected , models . HookEventPullRequestComment :
2018-12-27 19:04:30 +01:00
return getDingtalkPullRequestApprovalPayload ( p . ( * api . PullRequestPayload ) , event )
2019-11-04 06:13:25 +08:00
case models . HookEventRepository :
2017-11-21 12:26:43 +08:00
return getDingtalkRepositoryPayload ( p . ( * api . RepositoryPayload ) )
2019-11-04 06:13:25 +08:00
case models . HookEventRelease :
2018-05-16 22:01:55 +08:00
return getDingtalkReleasePayload ( p . ( * api . ReleasePayload ) )
2017-11-21 12:26:43 +08:00
}
return s , nil
}