code.gitea.io/gitea@v1.22.3/services/webhook/telegram.go (about) 1 // Copyright 2019 The Gitea Authors. All rights reserved. 2 // SPDX-License-Identifier: MIT 3 4 package webhook 5 6 import ( 7 "context" 8 "fmt" 9 "net/http" 10 "strings" 11 12 webhook_model "code.gitea.io/gitea/models/webhook" 13 "code.gitea.io/gitea/modules/git" 14 "code.gitea.io/gitea/modules/json" 15 "code.gitea.io/gitea/modules/log" 16 "code.gitea.io/gitea/modules/markup" 17 api "code.gitea.io/gitea/modules/structs" 18 webhook_module "code.gitea.io/gitea/modules/webhook" 19 ) 20 21 type ( 22 // TelegramPayload represents 23 TelegramPayload struct { 24 Message string `json:"text"` 25 ParseMode string `json:"parse_mode"` 26 DisableWebPreview bool `json:"disable_web_page_preview"` 27 } 28 29 // TelegramMeta contains the telegram metadata 30 TelegramMeta struct { 31 BotToken string `json:"bot_token"` 32 ChatID string `json:"chat_id"` 33 ThreadID string `json:"thread_id"` 34 } 35 ) 36 37 // GetTelegramHook returns telegram metadata 38 func GetTelegramHook(w *webhook_model.Webhook) *TelegramMeta { 39 s := &TelegramMeta{} 40 if err := json.Unmarshal([]byte(w.Meta), s); err != nil { 41 log.Error("webhook.GetTelegramHook(%d): %v", w.ID, err) 42 } 43 return s 44 } 45 46 // Create implements PayloadConvertor Create method 47 func (t telegramConvertor) Create(p *api.CreatePayload) (TelegramPayload, error) { 48 // created tag/branch 49 refName := git.RefName(p.Ref).ShortName() 50 title := fmt.Sprintf(`[<a href="%s">%s</a>] %s <a href="%s">%s</a> created`, p.Repo.HTMLURL, p.Repo.FullName, p.RefType, 51 p.Repo.HTMLURL+"/src/"+refName, refName) 52 53 return createTelegramPayload(title), nil 54 } 55 56 // Delete implements PayloadConvertor Delete method 57 func (t telegramConvertor) Delete(p *api.DeletePayload) (TelegramPayload, error) { 58 // created tag/branch 59 refName := git.RefName(p.Ref).ShortName() 60 title := fmt.Sprintf(`[<a href="%s">%s</a>] %s <a href="%s">%s</a> deleted`, p.Repo.HTMLURL, p.Repo.FullName, p.RefType, 61 p.Repo.HTMLURL+"/src/"+refName, refName) 62 63 return createTelegramPayload(title), nil 64 } 65 66 // Fork implements PayloadConvertor Fork method 67 func (t telegramConvertor) Fork(p *api.ForkPayload) (TelegramPayload, error) { 68 title := fmt.Sprintf(`%s is forked to <a href="%s">%s</a>`, p.Forkee.FullName, p.Repo.HTMLURL, p.Repo.FullName) 69 70 return createTelegramPayload(title), nil 71 } 72 73 // Push implements PayloadConvertor Push method 74 func (t telegramConvertor) Push(p *api.PushPayload) (TelegramPayload, error) { 75 var ( 76 branchName = git.RefName(p.Ref).ShortName() 77 commitDesc string 78 ) 79 80 var titleLink string 81 if p.TotalCommits == 1 { 82 commitDesc = "1 new commit" 83 titleLink = p.Commits[0].URL 84 } else { 85 commitDesc = fmt.Sprintf("%d new commits", p.TotalCommits) 86 titleLink = p.CompareURL 87 } 88 if titleLink == "" { 89 titleLink = p.Repo.HTMLURL + "/src/" + branchName 90 } 91 title := fmt.Sprintf(`[<a href="%s">%s</a>:<a href="%s">%s</a>] %s`, p.Repo.HTMLURL, p.Repo.FullName, titleLink, branchName, commitDesc) 92 93 var text string 94 // for each commit, generate attachment text 95 for i, commit := range p.Commits { 96 var authorName string 97 if commit.Author != nil { 98 authorName = " - " + commit.Author.Name 99 } 100 text += fmt.Sprintf(`[<a href="%s">%s</a>] %s`, commit.URL, commit.ID[:7], 101 strings.TrimRight(commit.Message, "\r\n")) + authorName 102 // add linebreak to each commit but the last 103 if i < len(p.Commits)-1 { 104 text += "\n" 105 } 106 } 107 108 return createTelegramPayload(title + "\n" + text), nil 109 } 110 111 // Issue implements PayloadConvertor Issue method 112 func (t telegramConvertor) Issue(p *api.IssuePayload) (TelegramPayload, error) { 113 text, _, attachmentText, _ := getIssuesPayloadInfo(p, htmlLinkFormatter, true) 114 115 return createTelegramPayload(text + "\n\n" + attachmentText), nil 116 } 117 118 // IssueComment implements PayloadConvertor IssueComment method 119 func (t telegramConvertor) IssueComment(p *api.IssueCommentPayload) (TelegramPayload, error) { 120 text, _, _ := getIssueCommentPayloadInfo(p, htmlLinkFormatter, true) 121 122 return createTelegramPayload(text + "\n" + p.Comment.Body), nil 123 } 124 125 // PullRequest implements PayloadConvertor PullRequest method 126 func (t telegramConvertor) PullRequest(p *api.PullRequestPayload) (TelegramPayload, error) { 127 text, _, attachmentText, _ := getPullRequestPayloadInfo(p, htmlLinkFormatter, true) 128 129 return createTelegramPayload(text + "\n" + attachmentText), nil 130 } 131 132 // Review implements PayloadConvertor Review method 133 func (t telegramConvertor) Review(p *api.PullRequestPayload, event webhook_module.HookEventType) (TelegramPayload, error) { 134 var text, attachmentText string 135 switch p.Action { 136 case api.HookIssueReviewed: 137 action, err := parseHookPullRequestEventType(event) 138 if err != nil { 139 return TelegramPayload{}, err 140 } 141 142 text = fmt.Sprintf("[%s] Pull request review %s: #%d %s", p.Repository.FullName, action, p.Index, p.PullRequest.Title) 143 attachmentText = p.Review.Content 144 } 145 146 return createTelegramPayload(text + "\n" + attachmentText), nil 147 } 148 149 // Repository implements PayloadConvertor Repository method 150 func (t telegramConvertor) Repository(p *api.RepositoryPayload) (TelegramPayload, error) { 151 var title string 152 switch p.Action { 153 case api.HookRepoCreated: 154 title = fmt.Sprintf(`[<a href="%s">%s</a>] Repository created`, p.Repository.HTMLURL, p.Repository.FullName) 155 return createTelegramPayload(title), nil 156 case api.HookRepoDeleted: 157 title = fmt.Sprintf("[%s] Repository deleted", p.Repository.FullName) 158 return createTelegramPayload(title), nil 159 } 160 return TelegramPayload{}, nil 161 } 162 163 // Wiki implements PayloadConvertor Wiki method 164 func (t telegramConvertor) Wiki(p *api.WikiPayload) (TelegramPayload, error) { 165 text, _, _ := getWikiPayloadInfo(p, htmlLinkFormatter, true) 166 167 return createTelegramPayload(text), nil 168 } 169 170 // Release implements PayloadConvertor Release method 171 func (t telegramConvertor) Release(p *api.ReleasePayload) (TelegramPayload, error) { 172 text, _ := getReleasePayloadInfo(p, htmlLinkFormatter, true) 173 174 return createTelegramPayload(text), nil 175 } 176 177 func (t telegramConvertor) Package(p *api.PackagePayload) (TelegramPayload, error) { 178 text, _ := getPackagePayloadInfo(p, htmlLinkFormatter, true) 179 180 return createTelegramPayload(text), nil 181 } 182 183 func createTelegramPayload(message string) TelegramPayload { 184 return TelegramPayload{ 185 Message: markup.Sanitize(strings.TrimSpace(message)), 186 ParseMode: "HTML", 187 DisableWebPreview: true, 188 } 189 } 190 191 type telegramConvertor struct{} 192 193 var _ payloadConvertor[TelegramPayload] = telegramConvertor{} 194 195 func newTelegramRequest(ctx context.Context, w *webhook_model.Webhook, t *webhook_model.HookTask) (*http.Request, []byte, error) { 196 return newJSONRequest(telegramConvertor{}, w, t, true) 197 }