@ -6,6 +6,7 @@ package webhook
import (
import (
"context"
"context"
"fmt"
"fmt"
"html"
"net/http"
"net/http"
"strings"
"strings"
@ -13,7 +14,9 @@ import (
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/json"
"code.gitea.io/gitea/modules/json"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/markup"
api "code.gitea.io/gitea/modules/structs"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/util"
webhook_module "code.gitea.io/gitea/modules/webhook"
webhook_module "code.gitea.io/gitea/modules/webhook"
)
)
@ -42,41 +45,43 @@ func GetTelegramHook(w *webhook_model.Webhook) *TelegramMeta {
return s
return s
}
}
type telegramConvertor struct { }
// Create implements PayloadConvertor Create method
// Create implements PayloadConvertor Create method
func ( t telegramConvertor ) Create ( p * api . CreatePayload ) ( TelegramPayload , error ) {
func ( t telegramConvertor ) Create ( p * api . CreatePayload ) ( TelegramPayload , error ) {
// created tag/branch
// created tag/branch
refName := git . RefName ( p . Ref ) . ShortName ( )
refName := git . RefName ( p . Ref ) . ShortName ( )
title := fmt . Sprintf ( ` [<a href="%s">%s</a>] %s <a href="%s">%s</a> created ` , p . Repo . HTMLURL , p . Repo . FullName , p . RefType ,
title := fmt . Sprintf ( ` [%s] %s %s created ` ,
p . Repo . HTMLURL + "/src/" + refName , refName )
htmlLinkFormatter ( p . Repo . HTMLURL , p . Repo . FullName ) ,
html . EscapeString ( p . RefType ) ,
htmlLinkFormatter ( p . Repo . HTMLURL + "/src/" + util . PathEscapeSegments ( refName ) , refName ) ,
)
return createTelegramPayload ( title ) , nil
return createTelegramPayloadHTML ( title ) , nil
}
}
// Delete implements PayloadConvertor Delete method
// Delete implements PayloadConvertor Delete method
func ( t telegramConvertor ) Delete ( p * api . DeletePayload ) ( TelegramPayload , error ) {
func ( t telegramConvertor ) Delete ( p * api . DeletePayload ) ( TelegramPayload , error ) {
// created tag/branch
// created tag/branch
refName := git . RefName ( p . Ref ) . ShortName ( )
refName := git . RefName ( p . Ref ) . ShortName ( )
title := fmt . Sprintf ( ` [<a href="%s">%s</a>] %s <a href="%s">%s</a> deleted ` , p . Repo . HTMLURL , p . Repo . FullName , p . RefType ,
title := fmt . Sprintf ( ` [%s] %s %s deleted ` ,
p . Repo . HTMLURL + "/src/" + refName , refName )
htmlLinkFormatter ( p . Repo . HTMLURL , p . Repo . FullName ) ,
html . EscapeString ( p . RefType ) ,
return createTelegramPayload ( title ) , nil
htmlLinkFormatter ( p . Repo . HTMLURL + "/src/" + util . PathEscapeSegments ( refName ) , refName ) ,
)
return createTelegramPayloadHTML ( title ) , nil
}
}
// Fork implements PayloadConvertor Fork method
// Fork implements PayloadConvertor Fork method
func ( t telegramConvertor ) Fork ( p * api . ForkPayload ) ( TelegramPayload , error ) {
func ( t telegramConvertor ) Fork ( p * api . ForkPayload ) ( TelegramPayload , error ) {
title := fmt . Sprintf ( ` %s is forked to <a href="%s">%s</a> ` , p . Forkee . FullName , p . Repo . HTMLURL , p . Repo . FullName )
title := fmt . Sprintf ( ` %s is forked to %s ` , html . EscapeString ( p . Forkee . FullName ) , htmlLinkFormatter ( p . Repo . HTMLURL , p . Repo . FullName ) )
return createTelegramPayloadHTML ( title ) , nil
return createTelegramPayload ( title ) , nil
}
}
// Push implements PayloadConvertor Push method
// Push implements PayloadConvertor Push method
func ( t telegramConvertor ) Push ( p * api . PushPayload ) ( TelegramPayload , error ) {
func ( t telegramConvertor ) Push ( p * api . PushPayload ) ( TelegramPayload , error ) {
var (
branchName := git . RefName ( p . Ref ) . ShortName ( )
branchName = git . RefName ( p . Ref ) . ShortName ( )
var titleLink , commitDesc string
commitDesc string
)
var titleLink string
if p . TotalCommits == 1 {
if p . TotalCommits == 1 {
commitDesc = "1 new commit"
commitDesc = "1 new commit"
titleLink = p . Commits [ 0 ] . URL
titleLink = p . Commits [ 0 ] . URL
@ -85,52 +90,42 @@ func (t telegramConvertor) Push(p *api.PushPayload) (TelegramPayload, error) {
titleLink = p . CompareURL
titleLink = p . CompareURL
}
}
if titleLink == "" {
if titleLink == "" {
titleLink = p . Repo . HTMLURL + "/src/" + branchName
titleLink = p . Repo . HTMLURL + "/src/" + util . PathEscapeSegments ( branchName )
}
}
title := fmt . Sprintf ( ` [<a href="%s">%s</a>:<a href="%s">%s</a>] %s ` , p . Repo . HTMLURL , p . Repo . FullName , titleLink , branchName , commitDesc )
title := fmt . Sprintf ( ` [%s:%s] %s ` , htmlLinkFormatter ( p . Repo . HTMLURL , p . Repo . FullName ) , htmlLinkFormatter ( titleLink , branchName ) , html . EscapeString ( commitDesc ) )
var text string
var htmlCommits string
// for each commit, generate attachment text
for _ , commit := range p . Commits {
for i , commit := range p . Commits {
htmlCommits += fmt . Sprintf ( "\n[%s] %s" , htmlLinkFormatter ( commit . URL , commit . ID [ : 7 ] ) , html . EscapeString ( strings . TrimRight ( commit . Message , "\r\n" ) ) )
var authorName string
if commit . Author != nil {
if commit . Author != nil {
authorName = " - " + commit . Author . Name
htmlCommits + = " - " + html . EscapeString ( commit . Author . Name )
}
}
text += fmt . Sprintf ( ` [<a href="%s">%s</a>] %s ` , commit . URL , commit . ID [ : 7 ] ,
strings . TrimRight ( commit . Message , "\r\n" ) ) + authorName
// add linebreak to each commit but the last
if i < len ( p . Commits ) - 1 {
text += "\n"
}
}
}
return createTelegramPayloadHTML ( title + htmlCommits ) , nil
return createTelegramPayload ( title + "\n" + text ) , nil
}
}
// Issue implements PayloadConvertor Issue method
// Issue implements PayloadConvertor Issue method
func ( t telegramConvertor ) Issue ( p * api . IssuePayload ) ( TelegramPayload , error ) {
func ( t telegramConvertor ) Issue ( p * api . IssuePayload ) ( TelegramPayload , error ) {
text , _ , attachmentText , _ := getIssuesPayloadInfo ( p , htmlLinkFormatter , true )
text , _ , extraMarkdown , _ := getIssuesPayloadInfo ( p , htmlLinkFormatter , true )
// TODO: at the moment the markdown can't be rendered easily because it has context-aware links (eg: attachments)
return createTelegramPayload ( text + "\n\n" + attachmentText ) , nil
return createTelegramPayloadHTML ( text + "\n\n" + html . EscapeString ( extraMarkdown ) ) , nil
}
}
// IssueComment implements PayloadConvertor IssueComment method
// IssueComment implements PayloadConvertor IssueComment method
func ( t telegramConvertor ) IssueComment ( p * api . IssueCommentPayload ) ( TelegramPayload , error ) {
func ( t telegramConvertor ) IssueComment ( p * api . IssueCommentPayload ) ( TelegramPayload , error ) {
text , _ , _ := getIssueCommentPayloadInfo ( p , htmlLinkFormatter , true )
text , _ , _ := getIssueCommentPayloadInfo ( p , htmlLinkFormatter , true )
return createTelegramPayloadHTML ( text + "\n" + html . EscapeString ( p . Comment . Body ) ) , nil
return createTelegramPayload ( text + "\n" + p . Comment . Body ) , nil
}
}
// PullRequest implements PayloadConvertor PullRequest method
// PullRequest implements PayloadConvertor PullRequest method
func ( t telegramConvertor ) PullRequest ( p * api . PullRequestPayload ) ( TelegramPayload , error ) {
func ( t telegramConvertor ) PullRequest ( p * api . PullRequestPayload ) ( TelegramPayload , error ) {
text , _ , attachmentText , _ := getPullRequestPayloadInfo ( p , htmlLinkFormatter , true )
text , _ , extraMarkdown , _ := getPullRequestPayloadInfo ( p , htmlLinkFormatter , true )
return createTelegramPayloadHTML ( text + "\n" + html . EscapeString ( extraMarkdown ) ) , nil
return createTelegramPayload ( text + "\n" + attachmentText ) , nil
}
}
// Review implements PayloadConvertor Review method
// Review implements PayloadConvertor Review method
func ( t telegramConvertor ) Review ( p * api . PullRequestPayload , event webhook_module . HookEventType ) ( TelegramPayload , error ) {
func ( t telegramConvertor ) Review ( p * api . PullRequestPayload , event webhook_module . HookEventType ) ( TelegramPayload , error ) {
var text , attachmentText string
var text , extraMarkdown string
switch p . Action {
switch p . Action {
case api . HookIssueReviewed :
case api . HookIssueReviewed :
action , err := parseHookPullRequestEventType ( event )
action , err := parseHookPullRequestEventType ( event )
@ -138,11 +133,11 @@ func (t telegramConvertor) Review(p *api.PullRequestPayload, event webhook_modul
return TelegramPayload { } , err
return TelegramPayload { } , err
}
}
text = fmt . Sprintf ( "[%s] Pull request review %s: #%d %s" , p . Repository . FullName , action , p . Index , p . PullRequest . Title )
text = fmt . Sprintf ( "[%s] Pull request review %s: #%d %s" , html . EscapeString ( p . Repository . FullName ) , html . EscapeString ( action ) , p . Index , html . EscapeString ( p . PullRequest . Title ) )
attachmentText = p . Review . Content
extraMarkdown = p . Review . Content
}
}
return createTelegramPayload ( text + "\n" + attachmentText ) , nil
return createTelegramPayloadHTML ( text + "\n" + html . EscapeString ( extraMarkdown ) ) , nil
}
}
// Repository implements PayloadConvertor Repository method
// Repository implements PayloadConvertor Repository method
@ -150,11 +145,11 @@ func (t telegramConvertor) Repository(p *api.RepositoryPayload) (TelegramPayload
var title string
var title string
switch p . Action {
switch p . Action {
case api . HookRepoCreated :
case api . HookRepoCreated :
title = fmt . Sprintf ( ` [<a href=" %s">%s</a> ] Repository created ` , p . Repository . HTMLURL , p . Repository . FullName )
title = fmt . Sprintf ( ` [%s] Repository created ` , htmlLinkFormatter ( p . Repository . HTMLURL , p . Repository . FullName ) )
return createTelegramPayload ( title ) , nil
return createTelegramPayloadHTML ( title ) , nil
case api . HookRepoDeleted :
case api . HookRepoDeleted :
title = fmt . Sprintf ( "[%s] Repository deleted" , p . Repository . FullName )
title = fmt . Sprintf ( "[%s] Repository deleted" , html . EscapeString ( p . Repository . FullName ) )
return createTelegramPayload ( title ) , nil
return createTelegramPayloadHTML ( title ) , nil
}
}
return TelegramPayload { } , nil
return TelegramPayload { } , nil
}
}
@ -163,34 +158,32 @@ func (t telegramConvertor) Repository(p *api.RepositoryPayload) (TelegramPayload
func ( t telegramConvertor ) Wiki ( p * api . WikiPayload ) ( TelegramPayload , error ) {
func ( t telegramConvertor ) Wiki ( p * api . WikiPayload ) ( TelegramPayload , error ) {
text , _ , _ := getWikiPayloadInfo ( p , htmlLinkFormatter , true )
text , _ , _ := getWikiPayloadInfo ( p , htmlLinkFormatter , true )
return createTelegramPayload ( text ) , nil
return createTelegramPayloadHTML ( text ) , nil
}
}
// Release implements PayloadConvertor Release method
// Release implements PayloadConvertor Release method
func ( t telegramConvertor ) Release ( p * api . ReleasePayload ) ( TelegramPayload , error ) {
func ( t telegramConvertor ) Release ( p * api . ReleasePayload ) ( TelegramPayload , error ) {
text , _ := getReleasePayloadInfo ( p , htmlLinkFormatter , true )
text , _ := getReleasePayloadInfo ( p , htmlLinkFormatter , true )
return createTelegramPayload ( text ) , nil
return createTelegramPayloadHTML ( text ) , nil
}
}
func ( t telegramConvertor ) Package ( p * api . PackagePayload ) ( TelegramPayload , error ) {
func ( t telegramConvertor ) Package ( p * api . PackagePayload ) ( TelegramPayload , error ) {
text , _ := getPackagePayloadInfo ( p , htmlLinkFormatter , true )
text , _ := getPackagePayloadInfo ( p , htmlLinkFormatter , true )
return createTelegramPayload ( text ) , nil
return createTelegramPayloadHTML ( text ) , nil
}
}
func createTelegramPayload ( message string ) TelegramPayload {
func createTelegramPayloadHTML ( msgHTML string ) TelegramPayload {
// https://core.telegram.org/bots/api#formatting-options
return TelegramPayload {
return TelegramPayload {
Message : strings . TrimSpace ( message ) ,
Message : strings . TrimSpace ( markup . Sanitize ( msgHTML ) ) ,
ParseMode : "HTML" ,
ParseMode : "HTML" ,
DisableWebPreview : true ,
DisableWebPreview : true ,
}
}
}
}
type telegramConvertor struct { }
var _ payloadConvertor [ TelegramPayload ] = telegramConvertor { }
func newTelegramRequest ( _ context . Context , w * webhook_model . Webhook , t * webhook_model . HookTask ) ( * http . Request , [ ] byte , error ) {
func newTelegramRequest ( _ context . Context , w * webhook_model . Webhook , t * webhook_model . HookTask ) ( * http . Request , [ ] byte , error ) {
return newJSONRequest ( telegramConvertor { } , w , t , true )
var pc payloadConvertor [ TelegramPayload ] = telegramConvertor { }
return newJSONRequest ( pc , w , t , true )
}
}