diff options
author | Daniel Baumann <daniel@debian.org> | 2024-10-18 20:33:49 +0200 |
---|---|---|
committer | Daniel Baumann <daniel@debian.org> | 2024-12-12 23:57:56 +0100 |
commit | e68b9d00a6e05b3a941f63ffb696f91e554ac5ec (patch) | |
tree | 97775d6c13b0f416af55314eb6a89ef792474615 /services/webhook/telegram.go | |
parent | Initial commit. (diff) | |
download | forgejo-e68b9d00a6e05b3a941f63ffb696f91e554ac5ec.tar.xz forgejo-e68b9d00a6e05b3a941f63ffb696f91e554ac5ec.zip |
Adding upstream version 9.0.3.
Signed-off-by: Daniel Baumann <daniel@debian.org>
Diffstat (limited to 'services/webhook/telegram.go')
-rw-r--r-- | services/webhook/telegram.go | 228 |
1 files changed, 228 insertions, 0 deletions
diff --git a/services/webhook/telegram.go b/services/webhook/telegram.go new file mode 100644 index 0000000..bacfa64 --- /dev/null +++ b/services/webhook/telegram.go @@ -0,0 +1,228 @@ +// Copyright 2019 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package webhook + +import ( + "context" + "fmt" + "html/template" + "net/http" + "net/url" + "strings" + + webhook_model "code.gitea.io/gitea/models/webhook" + "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/json" + "code.gitea.io/gitea/modules/log" + "code.gitea.io/gitea/modules/markup" + api "code.gitea.io/gitea/modules/structs" + webhook_module "code.gitea.io/gitea/modules/webhook" + "code.gitea.io/gitea/services/forms" + "code.gitea.io/gitea/services/webhook/shared" +) + +type telegramHandler struct{} + +func (telegramHandler) Type() webhook_module.HookType { return webhook_module.TELEGRAM } +func (telegramHandler) Icon(size int) template.HTML { return shared.ImgIcon("telegram.png", size) } + +func (telegramHandler) UnmarshalForm(bind func(any)) forms.WebhookForm { + var form struct { + forms.WebhookCoreForm + BotToken string `binding:"Required"` + ChatID string `binding:"Required"` + ThreadID string + } + bind(&form) + + return forms.WebhookForm{ + WebhookCoreForm: form.WebhookCoreForm, + URL: fmt.Sprintf("https://api.telegram.org/bot%s/sendMessage?chat_id=%s&message_thread_id=%s", url.PathEscape(form.BotToken), url.QueryEscape(form.ChatID), url.QueryEscape(form.ThreadID)), + ContentType: webhook_model.ContentTypeJSON, + Secret: "", + HTTPMethod: http.MethodPost, + Metadata: &TelegramMeta{ + BotToken: form.BotToken, + ChatID: form.ChatID, + ThreadID: form.ThreadID, + }, + } +} + +type ( + // TelegramPayload represents + TelegramPayload struct { + Message string `json:"text"` + ParseMode string `json:"parse_mode"` + DisableWebPreview bool `json:"disable_web_page_preview"` + } + + // TelegramMeta contains the telegram metadata + TelegramMeta struct { + BotToken string `json:"bot_token"` + ChatID string `json:"chat_id"` + ThreadID string `json:"thread_id"` + } +) + +// Metadata returns telegram metadata +func (telegramHandler) Metadata(w *webhook_model.Webhook) any { + s := &TelegramMeta{} + if err := json.Unmarshal([]byte(w.Meta), s); err != nil { + log.Error("telegramHandler.Metadata(%d): %v", w.ID, err) + } + return s +} + +// Create implements PayloadConvertor Create method +func (t telegramConvertor) Create(p *api.CreatePayload) (TelegramPayload, error) { + // created tag/branch + 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, + p.Repo.HTMLURL+"/src/"+refName, refName) + + return createTelegramPayload(title), nil +} + +// Delete implements PayloadConvertor Delete method +func (t telegramConvertor) Delete(p *api.DeletePayload) (TelegramPayload, error) { + // created tag/branch + 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, + p.Repo.HTMLURL+"/src/"+refName, refName) + + return createTelegramPayload(title), nil +} + +// Fork implements PayloadConvertor Fork method +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) + + return createTelegramPayload(title), nil +} + +// Push implements PayloadConvertor Push method +func (t telegramConvertor) Push(p *api.PushPayload) (TelegramPayload, error) { + var ( + branchName = git.RefName(p.Ref).ShortName() + commitDesc string + ) + + var titleLink string + if p.TotalCommits == 1 { + commitDesc = "1 new commit" + titleLink = p.Commits[0].URL + } else { + commitDesc = fmt.Sprintf("%d new commits", p.TotalCommits) + titleLink = p.CompareURL + } + if titleLink == "" { + titleLink = p.Repo.HTMLURL + "/src/" + branchName + } + title := fmt.Sprintf(`[<a href="%s">%s</a>:<a href="%s">%s</a>] %s`, p.Repo.HTMLURL, p.Repo.FullName, titleLink, 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(`[<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 createTelegramPayload(title + "\n" + text), nil +} + +// Issue implements PayloadConvertor Issue method +func (t telegramConvertor) Issue(p *api.IssuePayload) (TelegramPayload, error) { + text, _, attachmentText, _ := getIssuesPayloadInfo(p, htmlLinkFormatter, true) + + return createTelegramPayload(text + "\n\n" + attachmentText), nil +} + +// IssueComment implements PayloadConvertor IssueComment method +func (t telegramConvertor) IssueComment(p *api.IssueCommentPayload) (TelegramPayload, error) { + text, _, _ := getIssueCommentPayloadInfo(p, htmlLinkFormatter, true) + + return createTelegramPayload(text + "\n" + p.Comment.Body), nil +} + +// PullRequest implements PayloadConvertor PullRequest method +func (t telegramConvertor) PullRequest(p *api.PullRequestPayload) (TelegramPayload, error) { + text, _, attachmentText, _ := getPullRequestPayloadInfo(p, htmlLinkFormatter, true) + + return createTelegramPayload(text + "\n" + attachmentText), nil +} + +// Review implements PayloadConvertor Review method +func (t telegramConvertor) Review(p *api.PullRequestPayload, event webhook_module.HookEventType) (TelegramPayload, error) { + var text, attachmentText string + if p.Action == api.HookIssueReviewed { + action, err := parseHookPullRequestEventType(event) + if err != nil { + return TelegramPayload{}, err + } + + text = fmt.Sprintf("[%s] Pull request review %s: #%d %s", p.Repository.FullName, action, p.Index, p.PullRequest.Title) + attachmentText = p.Review.Content + } + + return createTelegramPayload(text + "\n" + attachmentText), nil +} + +// Repository implements PayloadConvertor Repository method +func (t telegramConvertor) Repository(p *api.RepositoryPayload) (TelegramPayload, error) { + var title string + switch p.Action { + case api.HookRepoCreated: + title = fmt.Sprintf(`[<a href="%s">%s</a>] Repository created`, p.Repository.HTMLURL, p.Repository.FullName) + return createTelegramPayload(title), nil + case api.HookRepoDeleted: + title = fmt.Sprintf("[%s] Repository deleted", p.Repository.FullName) + return createTelegramPayload(title), nil + } + return TelegramPayload{}, nil +} + +// Wiki implements PayloadConvertor Wiki method +func (t telegramConvertor) Wiki(p *api.WikiPayload) (TelegramPayload, error) { + text, _, _ := getWikiPayloadInfo(p, htmlLinkFormatter, true) + + return createTelegramPayload(text), nil +} + +// Release implements PayloadConvertor Release method +func (t telegramConvertor) Release(p *api.ReleasePayload) (TelegramPayload, error) { + text, _ := getReleasePayloadInfo(p, htmlLinkFormatter, true) + + return createTelegramPayload(text), nil +} + +func (t telegramConvertor) Package(p *api.PackagePayload) (TelegramPayload, error) { + text, _ := getPackagePayloadInfo(p, htmlLinkFormatter, true) + + return createTelegramPayload(text), nil +} + +func createTelegramPayload(message string) TelegramPayload { + return TelegramPayload{ + Message: markup.Sanitize(strings.TrimSpace(message)), + ParseMode: "HTML", + DisableWebPreview: true, + } +} + +type telegramConvertor struct{} + +var _ shared.PayloadConvertor[TelegramPayload] = telegramConvertor{} + +func (telegramHandler) NewRequest(ctx context.Context, w *webhook_model.Webhook, t *webhook_model.HookTask) (*http.Request, []byte, error) { + return shared.NewJSONRequest(telegramConvertor{}, w, t, true) +} |