parent
5e6091a30a
commit
2bce24068d
@ -0,0 +1,114 @@ |
||||
// Copyright 2014 The Gogs 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" |
||||
"errors" |
||||
"fmt" |
||||
"strings" |
||||
) |
||||
|
||||
const ( |
||||
SLACK_COLOR string = "#dd4b39" |
||||
) |
||||
|
||||
type Slack struct { |
||||
Domain string `json:"domain"` |
||||
Token string `json:"token"` |
||||
Channel string `json:"channel"` |
||||
} |
||||
|
||||
type SlackPayload struct { |
||||
Channel string `json:"channel"` |
||||
Text string `json:"text"` |
||||
Username string `json:"username"` |
||||
IconUrl string `json:"icon_url"` |
||||
UnfurlLinks int `json:"unfurl_links"` |
||||
LinkNames int `json:"link_names"` |
||||
Attachments []SlackAttachment `json:"attachments"` |
||||
} |
||||
|
||||
type SlackAttachment struct { |
||||
Color string `json:"color"` |
||||
Text string `json:"text"` |
||||
} |
||||
|
||||
func GetSlackURL(domain string, token string) string { |
||||
return fmt.Sprintf( |
||||
"https://%s.slack.com/services/hooks/incoming-webhook?token=%s", |
||||
domain, |
||||
token, |
||||
) |
||||
} |
||||
|
||||
func (p SlackPayload) GetJSONPayload() ([]byte, error) { |
||||
data, err := json.Marshal(p) |
||||
if err != nil { |
||||
return []byte{}, err |
||||
} |
||||
return data, nil |
||||
} |
||||
|
||||
func GetSlackPayload(p *Payload, meta string) (*SlackPayload, error) { |
||||
slack := &Slack{} |
||||
slackPayload := &SlackPayload{} |
||||
if err := json.Unmarshal([]byte(meta), &slack); err != nil { |
||||
return slackPayload, errors.New("GetSlackPayload meta json:" + err.Error()) |
||||
} |
||||
|
||||
// TODO: handle different payload types: push, new branch, delete branch etc.
|
||||
// when they are added to gogs. Only handles push now
|
||||
return getSlackPushPayload(p, slack) |
||||
} |
||||
|
||||
func getSlackPushPayload(p *Payload, slack *Slack) (*SlackPayload, error) { |
||||
// n new commits
|
||||
refSplit := strings.Split(p.Ref, "/") |
||||
branchName := refSplit[len(refSplit)-1] |
||||
var commitString string |
||||
|
||||
// TODO: add commit compare before/after link when gogs adds it
|
||||
if len(p.Commits) == 1 { |
||||
commitString = "1 new commit" |
||||
} else { |
||||
commitString = fmt.Sprintf("%d new commits", len(p.Commits)) |
||||
} |
||||
|
||||
text := fmt.Sprintf("[%s:%s] %s pushed by %s", p.Repo.Name, branchName, commitString, p.Pusher.Name) |
||||
var attachmentText string |
||||
|
||||
// for each commit, generate attachment text
|
||||
for i, commit := range p.Commits { |
||||
attachmentText += fmt.Sprintf("<%s|%s>: %s - %s", commit.Url, commit.Id[:7], SlackFormatter(commit.Message), commit.Author.Name) |
||||
// add linebreak to each commit but the last
|
||||
if i < len(p.Commits)-1 { |
||||
attachmentText += "\n" |
||||
} |
||||
} |
||||
|
||||
slackAttachments := []SlackAttachment{{Color: SLACK_COLOR, Text: attachmentText}} |
||||
|
||||
return &SlackPayload{ |
||||
Channel: slack.Channel, |
||||
Text: text, |
||||
Username: "gogs", |
||||
IconUrl: "https://raw.githubusercontent.com/gogits/gogs/master/public/img/favicon.png", |
||||
UnfurlLinks: 0, |
||||
LinkNames: 0, |
||||
Attachments: slackAttachments, |
||||
}, nil |
||||
} |
||||
|
||||
// see: https://api.slack.com/docs/formatting
|
||||
func SlackFormatter(s string) string { |
||||
// take only first line of commit
|
||||
first := strings.Split(s, "\n")[0] |
||||
// replace & < >
|
||||
first = strings.Replace(first, "&", "&", -1) |
||||
first = strings.Replace(first, "<", "<", -1) |
||||
first = strings.Replace(first, ">", ">", -1) |
||||
return first |
||||
} |
@ -0,0 +1,23 @@ |
||||
<div id="gogs" class="{{if (and .PageIsSettingsHooksEdit (not (eq .HookType "gogs")))}}hidden{{end}}"> |
||||
<form class="form form-align panel-body repo-setting-form" id="repo-setting-form-gogs" action="{{.RepoLink}}/settings/hooks/gogs/{{if .PageIsSettingsHooksNew}}new{{else}}{{.Webhook.Id}}{{end}}" method="post"> |
||||
{{.CsrfTokenHtml}} |
||||
<input type="hidden" name="hook_type" value="gogs"> |
||||
<div class="text-center panel-desc">{{.i18n.Tr "repo.settings.add_webhook_desc" | Str2html}}</div> |
||||
<div class="field"> |
||||
<label class="req" for="payload-url">{{.i18n.Tr "repo.settings.payload_url"}}</label> |
||||
<input class="ipt ipt-large ipt-radius {{if .Err_UserName}}ipt-error{{end}}" id="payload-url" name="payload_url" type="url" value="{{.Webhook.Url}}" required /> |
||||
</div> |
||||
<div class="field"> |
||||
<label class="req">{{.i18n.Tr "repo.settings.content_type"}}</label> |
||||
<select name="content_type"> |
||||
<option value="1" {{if or .PageIsSettingsHooksNew (eq .Webhook.ContentType 1)}}selected{{end}}>application/json</option> |
||||
<option value="2" {{if eq .Webhook.ContentType 2}}selected{{end}}>application/x-www-form-urlencoded</option> |
||||
</select> |
||||
</div> |
||||
<div class="field"> |
||||
<label for="secret">{{.i18n.Tr "repo.settings.secret"}}</label> |
||||
<input class="ipt ipt-large ipt-radius {{if .Err_UserName}}ipt-error{{end}}" id="secret" name="secret" type="password" value="{{.Webhook.Secret}}" autocomplete="off" /> |
||||
</div> |
||||
{{template "repo/settings/hook_settings" .}} |
||||
</form> |
||||
</div> |
@ -0,0 +1,15 @@ |
||||
<div class="field"> |
||||
<h4 class="text-center">{{.i18n.Tr "repo.settings.event_desc"}}</h4> |
||||
<label></label> |
||||
<input name="push_only" type="radio" {{if or .PageIsSettingsHooksNew .Webhook.PushOnly}}checked{{end}}> {{.i18n.Tr "repo.settings.event_push_only" | Str2html}} |
||||
</div> |
||||
<div class="field"> |
||||
<label for="active">{{.i18n.Tr "repo.settings.active"}}</label> |
||||
<input class="ipt-chk" id="active" name="active" type="checkbox" {{if or .PageIsSettingsHooksNew .Webhook.IsActive}}checked{{end}} /> |
||||
<span>{{.i18n.Tr "repo.settings.active_helper"}}</span> |
||||
</div> |
||||
<div class="field"> |
||||
<label></label> |
||||
<button class="btn btn-green btn-large btn-radius">{{if .PageIsSettingsHooksNew}}{{.i18n.Tr "repo.settings.add_webhook"}}{{else}}{{.i18n.Tr "repo.settings.update_webhook"}}{{end}}</button> |
||||
{{if .PageIsSettingsHooksEdit}}<a class="btn btn-red btn-large btn-link btn-radius" href="{{.RepoLink}}/settings/hooks?remove={{.Webhook.Id}}"><strong>{{.i18n.Tr "repo.settings.delete_webhook"}}</strong></a>{{end}} |
||||
</div> |
@ -0,0 +1,11 @@ |
||||
{{if .PageIsSettingsHooksNew}} |
||||
<div id="hook-type" class="form-align"> |
||||
<label class="req">{{.i18n.Tr "repo.settings.hook_type"}}</label> |
||||
<select name="hook_type" id="hook-type" class="form-control"> |
||||
{{if .HookType}}<option value="{{.HookType}}">{{.HookType}}</option>{{end}} |
||||
{{range .HookTypes}} |
||||
{{if not (eq $.HookType .)}}<option value="{{.}}" >{{.}}</option>{{end}} |
||||
{{end}} |
||||
</select> |
||||
</div> |
||||
{{end}} |
@ -0,0 +1,20 @@ |
||||
<div id="slack" class="{{if or .PageIsSettingsHooksNew (and .PageIsSettingsHooksEdit (not (eq .HookType "slack")))}}hidden{{end}}"> |
||||
<form class="form form-align panel-body repo-setting-form" id="repo-setting-form-slack" action="{{.RepoLink}}/settings/hooks/slack/{{if .PageIsSettingsHooksNew}}new{{else}}{{.Webhook.Id}}{{end}}" method="post"> |
||||
{{.CsrfTokenHtml}} |
||||
<input type="hidden" name="hook_type" value="slack"> |
||||
<div class="text-center panel-desc">{{.i18n.Tr "repo.settings.add_slack_hook_desc" | Str2html}}</div> |
||||
<div class="field"> |
||||
<label class="req" for="domain">{{.i18n.Tr "repo.settings.slack_domain"}}</label> |
||||
<input class="ipt ipt-large ipt-radius {{if .Err_UserName}}ipt-error{{end}}" id="domain" name="domain" type="text" value="{{.SlackHook.Domain}}" placeholde="myslack" required /> |
||||
</div> |
||||
<div class="field"> |
||||
<label class="req" for="token">{{.i18n.Tr "repo.settings.slack_token"}}</label> |
||||
<input class="ipt ipt-large ipt-radius {{if .Err_UserName}}ipt-error{{end}}" id="token" name="token" type="text" value="{{.SlackHook.Token}}" autocomplete="off" required /> |
||||
</div> |
||||
<div class="field"> |
||||
<label class="req" for="channel">{{.i18n.Tr "repo.settings.slack_channel"}}</label> |
||||
<input class="ipt ipt-large ipt-radius {{if .Err_UserName}}ipt-error{{end}}" id="channel" name="channel" type="text" value="{{.SlackHook.Channel}}" placeholder="#general" required /> |
||||
</div> |
||||
{{template "repo/settings/hook_settings" .}} |
||||
</form> |
||||
</div> |
Loading…
Reference in new issue