<commit_before>/*
Copyright 2016 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package github

import (
	"encoding/json"
	"fmt"
	"strings"
	"time"

	"k8s.io/test-infra/prow/errorutil"
)

const (
	// EventGUID is sent by GitHub in a header of every webhook request.
	// Used as a log field across prow.
	EventGUID = "event-GUID"
	// PrLogField is the number of a PR.
	// Used as a log field across prow.
	PrLogField = "pr"
	// OrgLogField is the organization of a PR.
	// Used as a log field across prow.
	OrgLogField = "org"
	// RepoLogField is the repository of a PR.
	// Used as a log field across prow.
	RepoLogField = "repo"

	// SearchTimeFormat is a time.Time format string for ISO8601 which is the
	// format that GitHub requires for times specified as part of a search query.
	SearchTimeFormat = "2006-01-02T15:04:05Z"

	// DefaultAPIEndpoint is the default GitHub API endpoint.
	DefaultAPIEndpoint = "https://api.github.com"

	// DefaultGraphQLEndpoint is the default GitHub GraphQL API endpoint.
	DefaultGraphQLEndpoint = "https://api.github.com/graphql"
)

var (
	// FoundingYear is the year GitHub was founded. This is just used so that
	// we can lower bound dates related to PRs and issues.
	FoundingYear, _ = time.Parse(SearchTimeFormat, "2007-01-01T00:00:00Z")
)

// These are possible State entries for a Status.
const (
	StatusPending = "pending"
	StatusSuccess = "success"
	StatusError   = "error"
	StatusFailure = "failure"
)

// Possible contents for reactions.
const (
	ReactionThumbsUp                  = "+1"
	ReactionThumbsDown                = "-1"
	ReactionLaugh                     = "laugh"
	ReactionConfused                  = "confused"
	ReactionHeart                     = "heart"
	ReactionHooray                    = "hooray"
	stateCannotBeChangedMessagePrefix = "state cannot be changed."
)

// PullRequestMergeType enumerates the types of merges the GitHub API can
// perform
// https://developer.github.com/v3/pulls/#merge-a-pull-request-merge-button
type PullRequestMergeType string

// Possible types of merges for the GitHub merge API
const (
	MergeMerge  PullRequestMergeType = "merge"
	MergeRebase PullRequestMergeType = "rebase"
	MergeSquash PullRequestMergeType = "squash"
)

func unmarshalClientError(b []byte) error {
	var errors []error
	clientError := ClientError{}
	err := json.Unmarshal(b, &clientError)
	if err == nil {
		return clientError
	}
	errors = append(errors, err)
	alternativeClientError := AlternativeClientError{}
	err = json.Unmarshal(b, &alternativeClientError)
	if err == nil {
		return alternativeClientError
	}
	errors = append(errors, err)
	return errorutil.NewAggregate(errors...)
}

// ClientError represents https://developer.github.com/v3/#client-errors
type ClientError struct {
	Message string `json:"message"`
	Errors  []struct {
		Resource string `json:"resource"`
		Field    string `json:"field"`
		Code     string `json:"code"`
		Message  string `json:"message,omitempty"`
	} `json:"errors,omitempty"`
}

func (r ClientError) Error() string {
	return r.Message
}

// AlternativeClientError represents an alternative format for https://developer.github.com/v3/#client-errors
// This is probably a GitHub bug, as documentation_url should appear only in custom errors
type AlternativeClientError struct {
	Message          string   `json:"message"`
	Errors           []string `json:"errors,omitempty"`
	DocumentationURL string   `json:"documentation_url,omitempty"`
}

func (r AlternativeClientError) Error() string {
	return r.Message
}

// Reaction holds the type of emotional reaction.
type Reaction struct {
	Content string `json:"content"`
}

// Status is used to set a commit status line.
type Status struct {
	State       string `json:"state"`
	TargetURL   string `json:"target_url,omitempty"`
	Description string `json:"description,omitempty"`
	Context     string `json:"context,omitempty"`
}

// CombinedStatus is the latest statuses for a ref.
type CombinedStatus struct {
	SHA      string   `json:"sha"`
	Statuses []Status `json:"statuses"`
	State    string   `json:"state"`
}

// User is a GitHub user account.
type User struct {
	Login   string `json:"login"`
	Name    string `json:"name"`
	Email   string `json:"email"`
	ID      int    `json:"id"`
	HTMLURL string `json:"html_url"`
}

// NormLogin normalizes GitHub login strings
var NormLogin = strings.ToLower

// PullRequestEventAction enumerates the triggers for this
// webhook payload type. See also:
// https://developer.github.com/v3/activity/events/types/#pullrequestevent
type PullRequestEventAction string

const (
	// PullRequestActionAssigned means assignees were added.
	PullRequestActionAssigned PullRequestEventAction = "assigned"
	// PullRequestActionUnassigned means assignees were removed.
	PullRequestActionUnassigned PullRequestEventAction = "unassigned"
	// PullRequestActionReviewRequested means review requests were added.
	PullRequestActionReviewRequested PullRequestEventAction = "review_requested"
	// PullRequestActionReviewRequestRemoved means review requests were removed.
	PullRequestActionReviewRequestRemoved PullRequestEventAction = "review_request_removed"
	// PullRequestActionLabeled means labels were added.
	PullRequestActionLabeled PullRequestEventAction = "labeled"
	// PullRequestActionUnlabeled means labels were removed
	PullRequestActionUnlabeled PullRequestEventAction = "unlabeled"
	// PullRequestActionOpened means the PR was created
	PullRequestActionOpened PullRequestEventAction = "opened"<commit_msg>trim leading @ from logins when normalizing in github client<commit_after>/*
Copyright 2016 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package github

import (
	"encoding/json"
	"fmt"
	"strings"
	"time"

	"k8s.io/test-infra/prow/errorutil"
)

const (
	// EventGUID is sent by GitHub in a header of every webhook request.
	// Used as a log field across prow.
	EventGUID = "event-GUID"
	// PrLogField is the number of a PR.
	// Used as a log field across prow.
	PrLogField = "pr"
	// OrgLogField is the organization of a PR.
	// Used as a log field across prow.
	OrgLogField = "org"
	// RepoLogField is the repository of a PR.
	// Used as a log field across prow.
	RepoLogField = "repo"

	// SearchTimeFormat is a time.Time format string for ISO8601 which is the
	// format that GitHub requires for times specified as part of a search query.
	SearchTimeFormat = "2006-01-02T15:04:05Z"

	// DefaultAPIEndpoint is the default GitHub API endpoint.
	DefaultAPIEndpoint = "https://api.github.com"

	// DefaultGraphQLEndpoint is the default GitHub GraphQL API endpoint.
	DefaultGraphQLEndpoint = "https://api.github.com/graphql"
)

var (
	// FoundingYear is the year GitHub was founded. This is just used so that
	// we can lower bound dates related to PRs and issues.
	FoundingYear, _ = time.Parse(SearchTimeFormat, "2007-01-01T00:00:00Z")
)

// These are possible State entries for a Status.
const (
	StatusPending = "pending"
	StatusSuccess = "success"
	StatusError   = "error"
	StatusFailure = "failure"
)

// Possible contents for reactions.
const (
	ReactionThumbsUp                  = "+1"
	ReactionThumbsDown                = "-1"
	ReactionLaugh                     = "laugh"
	ReactionConfused                  = "confused"
	ReactionHeart                     = "heart"
	ReactionHooray                    = "hooray"
	stateCannotBeChangedMessagePrefix = "state cannot be changed."
)

// PullRequestMergeType enumerates the types of merges the GitHub API can
// perform
// https://developer.github.com/v3/pulls/#merge-a-pull-request-merge-button
type PullRequestMergeType string

// Possible types of merges for the GitHub merge API
const (
	MergeMerge  PullRequestMergeType = "merge"
	MergeRebase PullRequestMergeType = "rebase"
	MergeSquash PullRequestMergeType = "squash"
)

func unmarshalClientError(b []byte) error {
	var errors []error
	clientError := ClientError{}
	err := json.Unmarshal(b, &clientError)
	if err == nil {
		return clientError
	}
	errors = append(errors, err)
	alternativeClientError := AlternativeClientError{}
	err = json.Unmarshal(b, &alternativeClientError)
	if err == nil {
		return alternativeClientError
	}
	errors = append(errors, err)
	return errorutil.NewAggregate(errors...)
}

// ClientError represents https://developer.github.com/v3/#client-errors
type ClientError struct {
	Message string `json:"message"`
	Errors  []struct {
		Resource string `json:"resource"`
		Field    string `json:"field"`
		Code     string `json:"code"`
		Message  string `json:"message,omitempty"`
	} `json:"errors,omitempty"`
}

func (r ClientError) Error() string {
	return r.Message
}

// AlternativeClientError represents an alternative format for https://developer.github.com/v3/#client-errors
// This is probably a GitHub bug, as documentation_url should appear only in custom errors
type AlternativeClientError struct {
	Message          string   `json:"message"`
	Errors           []string `json:"errors,omitempty"`
	DocumentationURL string   `json:"documentation_url,omitempty"`
}

func (r AlternativeClientError) Error() string {
	return r.Message
}

// Reaction holds the type of emotional reaction.
type Reaction struct {
	Content string `json:"content"`
}

// Status is used to set a commit status line.
type Status struct {
	State       string `json:"state"`
	TargetURL   string `json:"target_url,omitempty"`
	Description string `json:"description,omitempty"`
	Context     string `json:"context,omitempty"`
}

// CombinedStatus is the latest statuses for a ref.
type CombinedStatus struct {
	SHA      string   `json:"sha"`
	Statuses []Status `json:"statuses"`
	State    string   `json:"state"`
}

// User is a GitHub user account.
type User struct {
	Login   string `json:"login"`
	Name    string `json:"name"`
	Email   string `json:"email"`
	ID      int    `json:"id"`
	HTMLURL string `json:"html_url"`
}

// NormLogin normalizes GitHub login strings
func NormLogin(login string) string {
	return strings.TrimPrefix(strings.ToLower(login), "@")
}

// PullRequestEventAction enumerates the triggers for this
// webhook payload type. See also:
// https://developer.github.com/v3/activity/events/types/#pullrequestevent
type PullRequestEventAction string

const (
	// PullRequestActionAssigned means assignees were added.
	PullRequestActionAssigned PullRequestEventAction = "assigned"
	// PullRequestActionUnassigned means assignees were removed.
	PullRequestActionUnassigned PullRequestEventAction = "unassigned"
	// PullRequestActionReviewRequested means review requests were added.
	PullRequestActionReviewRequested PullRequestEventAction = "review_requested"
	// PullRequestActionReviewRequestRemoved means review requests were removed.
	PullRequestActionReviewRequestRemoved PullRequestEventAction = "review_request_removed"
	// PullRequestActionLabeled means labels were added.
	PullRequestActionLabeled PullRequestEventAction = "labeled"
	// PullRequestActionUnlabeled means labels were removed
	PullRequestActionUnlabeled PullRequestEventAction = "unlabeled"
	// PullRequestActionOpened means the PR was created
	PullRequestActionOpened PullRequestEventAction = "opened"
{'fraction_non_alphanumeric': 0.08813083340216404, 'fraction_numerical': 0.00776410341124969, 'mean_word_length': 4.059757626410364, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 12, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5246242', 'n_tokens_mistral': 3564, 'n_tokens_neox': 3387, 'n_words': 1166}