Repository: gogs/gogs
File: internal/database/webhook_slack.go (Go)

Code before:

	return &SlackPayload{
		Channel:  slack.Channel,
		Text:     text,
		Username: slack.Username,
		IconURL:  slack.IconURL,
		Attachments: []*SlackAttachment{{
			Color: slack.Color,
			Title: title,
			Text:  attachmentText,
		}},
	}
}

func getSlackReleasePayload(p *api.ReleasePayload) *SlackPayload {
	repoLink := SlackLinkFormatter(p.Repository.HTMLURL, p.Repository.Name)
	refLink := SlackLinkFormatter(p.Repository.HTMLURL+"/src/"+p.Release.TagName, p.Release.TagName)
	text := fmt.Sprintf("[%s] new release %s published by %s", repoLink, refLink, p.Sender.UserName)
	return &SlackPayload{
		Text: text,
	}
}

func GetSlackPayload(p api.Payloader, event HookEventType, meta string) (payload *SlackPayload, err error) {
	slack := &SlackMeta{}
	if err := json.Unmarshal([]byte(meta), &slack); err != nil {
		return nil, errors.Newf("unmarshal: %v", err)
	}

	switch event {
	case HookEventTypeCreate:
		payload = getSlackCreatePayload(p.(*api.CreatePayload))
	case HookEventTypeDelete:
		payload = getSlackDeletePayload(p.(*api.DeletePayload))
	case HookEventTypeFork:
		payload = getSlackForkPayload(p.(*api.ForkPayload))
	case HookEventTypePush:
		payload = getSlackPushPayload(p.(*api.PushPayload), slack)
	case HookEventTypeIssues:
		payload = getSlackIssuesPayload(p.(*api.IssuesPayload), slack)
	case HookEventTypeIssueComment:
		payload = getSlackIssueCommentPayload(p.(*api.IssueCommentPayload), slack)
	case HookEventTypePullRequest:
		payload = getSlackPullRequestPayload(p.(*api.PullRequestPayload), slack)
	case HookEventTypeRelease:
		payload = getSlackReleasePayload(p.(*api.ReleasePayload))
	default:
		return nil, errors.Errorf("unexpected event %q", event)
	}

	payload.Channel = slack.Channel

Review comment (suggestion):
`slack` is already a `*SlackMeta`, but Unmarshal is being called with `&slack` (a `**SlackMeta`). With `encoding/json`, unmarshalling a JSON `null` would set `slack` to `nil`, which can lead to panics later when accessing fields. Unmarshal into `slack` (or declare `var slack SlackMeta` and pass `&slack`) to keep the pointer non-nil and avoid unintended pointer reassignment.
```suggestion
	if err := json.Unmarshal([]byte(meta), slack); err != nil {
```

Code after:

	return &SlackPayload{
		Channel:  slack.Channel,
		Text:     text,
		Username: slack.Username,
		IconURL:  slack.IconURL,
		Attachments: []*SlackAttachment{{
			Color: slack.Color,
			Title: title,
			Text:  attachmentText,
		}},
	}
}

func getSlackReleasePayload(p *api.ReleasePayload) *SlackPayload {
	repoLink := SlackLinkFormatter(p.Repository.HTMLURL, p.Repository.Name)
	refLink := SlackLinkFormatter(p.Repository.HTMLURL+"/src/"+p.Release.TagName, p.Release.TagName)
	text := fmt.Sprintf("[%s] new release %s published by %s", repoLink, refLink, p.Sender.UserName)
	return &SlackPayload{
		Text: text,
	}
}

func GetSlackPayload(p api.Payloader, event HookEventType, meta string) (payload *SlackPayload, err error) {
	slack := &SlackMeta{}
	if err := json.Unmarshal([]byte(meta), slack); err != nil {
		return nil, errors.Newf("unmarshal: %v", err)
	}

	switch event {
	case HookEventTypeCreate:
		payload = getSlackCreatePayload(p.(*api.CreatePayload))
	case HookEventTypeDelete:
		payload = getSlackDeletePayload(p.(*api.DeletePayload))
	case HookEventTypeFork:
		payload = getSlackForkPayload(p.(*api.ForkPayload))
	case HookEventTypePush:
		payload = getSlackPushPayload(p.(*api.PushPayload), slack)
	case HookEventTypeIssues:
		payload = getSlackIssuesPayload(p.(*api.IssuesPayload), slack)
	case HookEventTypeIssueComment:
		payload = getSlackIssueCommentPayload(p.(*api.IssueCommentPayload), slack)
	case HookEventTypePullRequest:
		payload = getSlackPullRequestPayload(p.(*api.PullRequestPayload), slack)
	case HookEventTypeRelease:
		payload = getSlackReleasePayload(p.(*api.ReleasePayload))
	default:
		return nil, errors.Errorf("unexpected event %q", event)
	}

	payload.Channel = slack.Channel