2017-11-21 07:26:43 +03: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.
package models
import (
"encoding/json"
"fmt"
"strings"
2019-03-27 12:33:00 +03:00
"code.gitea.io/gitea/modules/git"
2019-05-11 13:21:34 +03:00
api "code.gitea.io/gitea/modules/structs"
2019-03-27 12:33:00 +03:00
2017-11-21 07:26:43 +03: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 05:28:29 +03:00
SingleTitle : fmt . Sprintf ( "view ref %s" , refName ) ,
2017-11-21 07:26:43 +03:00
SingleURL : p . Repo . HTMLURL + "/src/" + refName ,
} ,
} , nil
}
2018-05-16 17:01:55 +03: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 05:28:29 +03:00
SingleTitle : fmt . Sprintf ( "view ref %s" , refName ) ,
2018-05-16 17:01:55 +03: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 07:26:43 +03: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 17:01:55 +03:00
func getDingtalkIssuesPayload ( p * api . IssuePayload ) ( * DingtalkPayload , error ) {
var text , title string
switch p . Action {
case api . HookIssueOpened :
title = fmt . Sprintf ( "[%s] Issue opened: #%d %s" , p . Repository . FullName , p . Index , p . Issue . Title )
text = p . Issue . Body
case api . HookIssueClosed :
title = fmt . Sprintf ( "[%s] Issue closed: #%d %s" , p . Repository . FullName , p . Index , p . Issue . Title )
text = p . Issue . Body
case api . HookIssueReOpened :
title = fmt . Sprintf ( "[%s] Issue re-opened: #%d %s" , p . Repository . FullName , p . Index , p . Issue . Title )
text = p . Issue . Body
case api . HookIssueEdited :
title = fmt . Sprintf ( "[%s] Issue edited: #%d %s" , p . Repository . FullName , p . Index , p . Issue . Title )
text = p . Issue . Body
case api . HookIssueAssigned :
title = fmt . Sprintf ( "[%s] Issue assigned to %s: #%d %s" , p . Repository . FullName ,
p . Issue . Assignee . UserName , p . Index , p . Issue . Title )
text = p . Issue . Body
case api . HookIssueUnassigned :
title = fmt . Sprintf ( "[%s] Issue unassigned: #%d %s" , p . Repository . FullName , p . Index , p . Issue . Title )
text = p . Issue . Body
case api . HookIssueLabelUpdated :
2018-05-21 05:28:29 +03:00
title = fmt . Sprintf ( "[%s] Issue labels updated: #%d %s" , p . Repository . FullName , p . Index , p . Issue . Title )
2018-05-16 17:01:55 +03:00
text = p . Issue . Body
case api . HookIssueLabelCleared :
2018-05-21 05:28:29 +03:00
title = fmt . Sprintf ( "[%s] Issue labels cleared: #%d %s" , p . Repository . FullName , p . Index , p . Issue . Title )
2018-05-16 17:01:55 +03:00
text = p . Issue . Body
case api . HookIssueSynchronized :
2018-05-21 05:28:29 +03:00
title = fmt . Sprintf ( "[%s] Issue synchronized: #%d %s" , p . Repository . FullName , p . Index , p . Issue . Title )
text = p . Issue . Body
case api . HookIssueMilestoned :
title = fmt . Sprintf ( "[%s] Issue milestone: #%d %s" , p . Repository . FullName , p . Index , p . Issue . Title )
text = p . Issue . Body
case api . HookIssueDemilestoned :
title = fmt . Sprintf ( "[%s] Issue clear milestone: #%d %s" , p . Repository . FullName , p . Index , p . Issue . Title )
2018-05-16 17:01:55 +03:00
text = p . Issue . Body
}
return & DingtalkPayload {
MsgType : "actionCard" ,
ActionCard : dingtalk . ActionCard {
2018-05-21 05:28:29 +03:00
Text : title + "\r\n\r\n" + text ,
//Markdown: "# " + title + "\n" + text,
2018-05-16 17:01:55 +03:00
Title : title ,
HideAvatar : "0" ,
2018-05-21 05:28:29 +03:00
SingleTitle : "view issue" ,
2018-05-16 17:01:55 +03:00
SingleURL : p . Issue . URL ,
} ,
} , nil
}
func getDingtalkIssueCommentPayload ( p * api . IssueCommentPayload ) ( * DingtalkPayload , error ) {
2019-10-19 01:42:04 +03:00
title := fmt . Sprintf ( "#%d: %s" , p . Issue . Index , p . Issue . Title )
2018-05-16 17:01:55 +03:00
url := fmt . Sprintf ( "%s/issues/%d#%s" , p . Repository . HTMLURL , p . Issue . Index , CommentHashTag ( p . Comment . ID ) )
var content string
switch p . Action {
case api . HookIssueCommentCreated :
2019-10-19 01:42:04 +03:00
if p . IsPull {
title = "New comment on pull request " + title
} else {
title = "New comment on issue " + title
}
2018-05-16 17:01:55 +03:00
content = p . Comment . Body
case api . HookIssueCommentEdited :
2019-10-19 01:42:04 +03:00
if p . IsPull {
title = "Comment edited on pull request " + title
} else {
title = "Comment edited on issue " + title
}
2018-05-16 17:01:55 +03:00
content = p . Comment . Body
case api . HookIssueCommentDeleted :
2019-10-19 01:42:04 +03:00
if p . IsPull {
title = "Comment deleted on pull request " + title
} else {
title = "Comment deleted on issue " + title
}
2018-05-16 17:01:55 +03:00
url = fmt . Sprintf ( "%s/issues/%d" , p . Repository . HTMLURL , p . Issue . Index )
content = p . Comment . Body
}
2019-10-19 01:42:04 +03:00
title = fmt . Sprintf ( "[%s] %s" , p . Repository . FullName , title )
2018-05-16 17:01:55 +03:00
return & DingtalkPayload {
MsgType : "actionCard" ,
ActionCard : dingtalk . ActionCard {
2018-05-21 05:28:29 +03:00
Text : title + "\r\n\r\n" + content ,
2018-05-16 17:01:55 +03:00
Title : title ,
HideAvatar : "0" ,
2018-05-21 05:28:29 +03:00
SingleTitle : "view issue comment" ,
2018-05-16 17:01:55 +03:00
SingleURL : url ,
} ,
} , nil
}
2017-11-21 07:26:43 +03:00
func getDingtalkPullRequestPayload ( p * api . PullRequestPayload ) ( * DingtalkPayload , error ) {
var text , title string
switch p . Action {
case api . HookIssueOpened :
title = fmt . Sprintf ( "[%s] Pull request opened: #%d %s" , p . Repository . FullName , p . Index , p . PullRequest . Title )
text = p . PullRequest . Body
case api . HookIssueClosed :
if p . PullRequest . HasMerged {
title = fmt . Sprintf ( "[%s] Pull request merged: #%d %s" , p . Repository . FullName , p . Index , p . PullRequest . Title )
} else {
title = fmt . Sprintf ( "[%s] Pull request closed: #%d %s" , p . Repository . FullName , p . Index , p . PullRequest . Title )
}
text = p . PullRequest . Body
case api . HookIssueReOpened :
title = fmt . Sprintf ( "[%s] Pull request re-opened: #%d %s" , p . Repository . FullName , p . Index , p . PullRequest . Title )
text = p . PullRequest . Body
case api . HookIssueEdited :
title = fmt . Sprintf ( "[%s] Pull request edited: #%d %s" , p . Repository . FullName , p . Index , p . PullRequest . Title )
text = p . PullRequest . Body
case api . HookIssueAssigned :
2019-02-18 00:12:39 +03:00
list := make ( [ ] string , len ( p . PullRequest . Assignees ) )
for i , user := range p . PullRequest . Assignees {
list [ i ] = user . UserName
2018-05-09 19:29:04 +03:00
}
2017-11-21 07:26:43 +03:00
title = fmt . Sprintf ( "[%s] Pull request assigned to %s: #%d %s" , p . Repository . FullName ,
2019-02-18 00:12:39 +03:00
strings . Join ( list , ", " ) ,
p . Index , p . PullRequest . Title )
2017-11-21 07:26:43 +03:00
text = p . PullRequest . Body
case api . HookIssueUnassigned :
title = fmt . Sprintf ( "[%s] Pull request unassigned: #%d %s" , p . Repository . FullName , p . Index , p . PullRequest . Title )
text = p . PullRequest . Body
case api . HookIssueLabelUpdated :
title = fmt . Sprintf ( "[%s] Pull request labels updated: #%d %s" , p . Repository . FullName , p . Index , p . PullRequest . Title )
text = p . PullRequest . Body
case api . HookIssueLabelCleared :
title = fmt . Sprintf ( "[%s] Pull request labels cleared: #%d %s" , p . Repository . FullName , p . Index , p . PullRequest . Title )
text = p . PullRequest . Body
case api . HookIssueSynchronized :
title = fmt . Sprintf ( "[%s] Pull request synchronized: #%d %s" , p . Repository . FullName , p . Index , p . PullRequest . Title )
text = p . PullRequest . Body
2018-05-21 05:28:29 +03:00
case api . HookIssueMilestoned :
title = fmt . Sprintf ( "[%s] Pull request milestone: #%d %s" , p . Repository . FullName , p . Index , p . PullRequest . Title )
text = p . PullRequest . Body
case api . HookIssueDemilestoned :
title = fmt . Sprintf ( "[%s] Pull request clear milestone: #%d %s" , p . Repository . FullName , p . Index , p . PullRequest . Title )
text = p . PullRequest . Body
2017-11-21 07:26:43 +03:00
}
return & DingtalkPayload {
MsgType : "actionCard" ,
ActionCard : dingtalk . ActionCard {
2018-05-21 05:28:29 +03:00
Text : title + "\r\n\r\n" + text ,
//Markdown: "# " + title + "\n" + text,
2017-11-21 07:26:43 +03:00
Title : title ,
HideAvatar : "0" ,
SingleTitle : "view pull request" ,
SingleURL : p . PullRequest . HTMLURL ,
} ,
} , nil
}
2018-12-27 21:04:30 +03:00
func getDingtalkPullRequestApprovalPayload ( p * api . PullRequestPayload , event HookEventType ) ( * DingtalkPayload , error ) {
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-19 01:42:04 +03:00
text = p . Review . Content
2018-12-27 21:04:30 +03: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 07:26:43 +03: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 17:01:55 +03:00
func getDingtalkReleasePayload ( p * api . ReleasePayload ) ( * DingtalkPayload , error ) {
var title , url string
switch p . Action {
case api . HookReleasePublished :
title = fmt . Sprintf ( "[%s] Release created" , p . Release . TagName )
url = p . Release . URL
return & DingtalkPayload {
MsgType : "actionCard" ,
ActionCard : dingtalk . ActionCard {
Text : title ,
Title : title ,
HideAvatar : "0" ,
2018-05-21 05:28:29 +03:00
SingleTitle : "view release" ,
SingleURL : url ,
} ,
} , nil
case api . HookReleaseUpdated :
title = fmt . Sprintf ( "[%s] Release updated" , p . Release . TagName )
url = p . Release . URL
return & DingtalkPayload {
MsgType : "actionCard" ,
ActionCard : dingtalk . ActionCard {
Text : title ,
Title : title ,
HideAvatar : "0" ,
SingleTitle : "view release" ,
SingleURL : url ,
} ,
} , nil
case api . HookReleaseDeleted :
title = fmt . Sprintf ( "[%s] Release deleted" , p . Release . TagName )
url = p . Release . URL
return & DingtalkPayload {
MsgType : "actionCard" ,
ActionCard : dingtalk . ActionCard {
Text : title ,
Title : title ,
HideAvatar : "0" ,
SingleTitle : "view release" ,
2018-05-16 17:01:55 +03:00
SingleURL : url ,
} ,
} , nil
}
return nil , nil
}
2017-11-21 07:26:43 +03:00
// GetDingtalkPayload converts a ding talk webhook into a DingtalkPayload
func GetDingtalkPayload ( p api . Payloader , event HookEventType , meta string ) ( * DingtalkPayload , error ) {
s := new ( DingtalkPayload )
switch event {
case HookEventCreate :
return getDingtalkCreatePayload ( p . ( * api . CreatePayload ) )
2018-05-16 17:01:55 +03:00
case HookEventDelete :
return getDingtalkDeletePayload ( p . ( * api . DeletePayload ) )
case HookEventFork :
return getDingtalkForkPayload ( p . ( * api . ForkPayload ) )
case HookEventIssues :
return getDingtalkIssuesPayload ( p . ( * api . IssuePayload ) )
case HookEventIssueComment :
return getDingtalkIssueCommentPayload ( p . ( * api . IssueCommentPayload ) )
2017-11-21 07:26:43 +03:00
case HookEventPush :
return getDingtalkPushPayload ( p . ( * api . PushPayload ) )
case HookEventPullRequest :
return getDingtalkPullRequestPayload ( p . ( * api . PullRequestPayload ) )
2018-12-27 21:04:30 +03:00
case HookEventPullRequestApproved , HookEventPullRequestRejected , HookEventPullRequestComment :
return getDingtalkPullRequestApprovalPayload ( p . ( * api . PullRequestPayload ) , event )
2017-11-21 07:26:43 +03:00
case HookEventRepository :
return getDingtalkRepositoryPayload ( p . ( * api . RepositoryPayload ) )
2018-05-16 17:01:55 +03:00
case HookEventRelease :
return getDingtalkReleasePayload ( p . ( * api . ReleasePayload ) )
2017-11-21 07:26:43 +03:00
}
return s , nil
}