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