// Copyright 2013 The go-github AUTHORS. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

//go:generate go run gen-accessors.go
//go:generate go run gen-stringify-test.go
//go:generate ../script/metadata.sh update-go

package github

import (
	
	
	
	
	
	
	
	
	
	
	
	
	

	
)

const (
	Version = "v66.0.0"

	defaultAPIVersion = "2022-11-28"
	defaultBaseURL    = "https://api.github.com/"
	defaultUserAgent  = "go-github" + "/" + Version
	uploadBaseURL     = "https://uploads.github.com/"

	headerAPIVersion    = "X-GitHub-Api-Version"
	headerRateLimit     = "X-RateLimit-Limit"
	headerRateRemaining = "X-RateLimit-Remaining"
	headerRateReset     = "X-RateLimit-Reset"
	headerOTP           = "X-GitHub-OTP"
	headerRetryAfter    = "Retry-After"

	headerTokenExpiration = "GitHub-Authentication-Token-Expiration"

	mediaTypeV3                = "application/vnd.github.v3+json"
	defaultMediaType           = "application/octet-stream"
	mediaTypeV3SHA             = "application/vnd.github.v3.sha"
	mediaTypeV3Diff            = "application/vnd.github.v3.diff"
	mediaTypeV3Patch           = "application/vnd.github.v3.patch"
	mediaTypeOrgPermissionRepo = "application/vnd.github.v3.repository+json"
	mediaTypeIssueImportAPI    = "application/vnd.github.golden-comet-preview+json"

	// Media Type values to access preview APIs
	// These media types will be added to the API request as headers
	// and used to enable particular features on GitHub API that are still in preview.
	// After some time, specific media types will be promoted (to a "stable" state).
	// From then on, the preview headers are not required anymore to activate the additional
	// feature on GitHub.com's API. However, this API header might still be needed for users
	// to run a GitHub Enterprise Server on-premise.
	// It's not uncommon for GitHub Enterprise Server customers to run older versions which
	// would probably rely on the preview headers for some time.
	// While the header promotion is going out for GitHub.com, it may be some time before it
	// even arrives in GitHub Enterprise Server.
	// We keep those preview headers around to avoid breaking older GitHub Enterprise Server
	// versions. Additionally, non-functional (preview) headers don't create any side effects
	// on GitHub Cloud version.
	//
	// See https://github.com/google/go-github/pull/2125 for full context.

	// https://developer.github.com/changes/2014-12-09-new-attributes-for-stars-api/
	mediaTypeStarringPreview = "application/vnd.github.v3.star+json"

	// https://help.github.com/enterprise/2.4/admin/guides/migrations/exporting-the-github-com-organization-s-repositories/
	mediaTypeMigrationsPreview = "application/vnd.github.wyandotte-preview+json"

	// https://developer.github.com/changes/2016-04-06-deployment-and-deployment-status-enhancements/
	mediaTypeDeploymentStatusPreview = "application/vnd.github.ant-man-preview+json"

	// https://developer.github.com/changes/2018-10-16-deployments-environments-states-and-auto-inactive-updates/
	mediaTypeExpandDeploymentStatusPreview = "application/vnd.github.flash-preview+json"

	// https://developer.github.com/changes/2016-05-12-reactions-api-preview/
	mediaTypeReactionsPreview = "application/vnd.github.squirrel-girl-preview"

	// https://developer.github.com/changes/2016-05-23-timeline-preview-api/
	mediaTypeTimelinePreview = "application/vnd.github.mockingbird-preview+json"

	// https://developer.github.com/changes/2016-09-14-projects-api/
	mediaTypeProjectsPreview = "application/vnd.github.inertia-preview+json"

	// https://developer.github.com/changes/2017-01-05-commit-search-api/
	mediaTypeCommitSearchPreview = "application/vnd.github.cloak-preview+json"

	// https://developer.github.com/changes/2017-02-28-user-blocking-apis-and-webhook/
	mediaTypeBlockUsersPreview = "application/vnd.github.giant-sentry-fist-preview+json"

	// https://developer.github.com/changes/2017-05-23-coc-api/
	mediaTypeCodesOfConductPreview = "application/vnd.github.scarlet-witch-preview+json"

	// https://developer.github.com/changes/2017-07-17-update-topics-on-repositories/
	mediaTypeTopicsPreview = "application/vnd.github.mercy-preview+json"

	// https://developer.github.com/changes/2018-03-16-protected-branches-required-approving-reviews/
	mediaTypeRequiredApprovingReviewsPreview = "application/vnd.github.luke-cage-preview+json"

	// https://developer.github.com/changes/2018-05-07-new-checks-api-public-beta/
	mediaTypeCheckRunsPreview = "application/vnd.github.antiope-preview+json"

	// https://developer.github.com/enterprise/2.13/v3/repos/pre_receive_hooks/
	mediaTypePreReceiveHooksPreview = "application/vnd.github.eye-scream-preview"

	// https://developer.github.com/changes/2018-02-22-protected-branches-required-signatures/
	mediaTypeSignaturePreview = "application/vnd.github.zzzax-preview+json"

	// https://developer.github.com/changes/2018-09-05-project-card-events/
	mediaTypeProjectCardDetailsPreview = "application/vnd.github.starfox-preview+json"

	// https://developer.github.com/changes/2018-12-18-interactions-preview/
	mediaTypeInteractionRestrictionsPreview = "application/vnd.github.sombra-preview+json"

	// https://developer.github.com/changes/2019-03-14-enabling-disabling-pages/
	mediaTypeEnablePagesAPIPreview = "application/vnd.github.switcheroo-preview+json"

	// https://developer.github.com/changes/2019-04-24-vulnerability-alerts/
	mediaTypeRequiredVulnerabilityAlertsPreview = "application/vnd.github.dorian-preview+json"

	// https://developer.github.com/changes/2019-05-29-update-branch-api/
	mediaTypeUpdatePullRequestBranchPreview = "application/vnd.github.lydian-preview+json"

	// https://developer.github.com/changes/2019-04-11-pulls-branches-for-commit/
	mediaTypeListPullsOrBranchesForCommitPreview = "application/vnd.github.groot-preview+json"

	// https://docs.github.com/rest/previews/#repository-creation-permissions
	mediaTypeMemberAllowedRepoCreationTypePreview = "application/vnd.github.surtur-preview+json"

	// https://docs.github.com/rest/previews/#create-and-use-repository-templates
	mediaTypeRepositoryTemplatePreview = "application/vnd.github.baptiste-preview+json"

	// https://developer.github.com/changes/2019-10-03-multi-line-comments/
	mediaTypeMultiLineCommentsPreview = "application/vnd.github.comfort-fade-preview+json"

	// https://developer.github.com/changes/2019-11-05-deprecated-passwords-and-authorizations-api/
	mediaTypeOAuthAppPreview = "application/vnd.github.doctor-strange-preview+json"

	// https://developer.github.com/changes/2019-12-03-internal-visibility-changes/
	mediaTypeRepositoryVisibilityPreview = "application/vnd.github.nebula-preview+json"

	// https://developer.github.com/changes/2018-12-10-content-attachments-api/
	mediaTypeContentAttachmentsPreview = "application/vnd.github.corsair-preview+json"
)

var errNonNilContext = errors.New("context must be non-nil")

// A Client manages communication with the GitHub API.
type Client struct {
	clientMu sync.Mutex   // clientMu protects the client during calls that modify the CheckRedirect func.
	client   *http.Client // HTTP client used to communicate with the API.

	// Base URL for API requests. Defaults to the public GitHub API, but can be
	// set to a domain endpoint to use with GitHub Enterprise. BaseURL should
	// always be specified with a trailing slash.
	BaseURL *url.URL

	// Base URL for uploading files.
	UploadURL *url.URL

	// User agent used when communicating with the GitHub API.
	UserAgent string

	rateMu                  sync.Mutex
	rateLimits              [Categories]Rate // Rate limits for the client as determined by the most recent API calls.
	secondaryRateLimitReset time.Time        // Secondary rate limit reset for the client as determined by the most recent API calls.

	common service // Reuse a single struct instead of allocating one for each service on the heap.

	// Services used for talking to different parts of the GitHub API.
	Actions            *ActionsService
	Activity           *ActivityService
	Admin              *AdminService
	Apps               *AppsService
	Authorizations     *AuthorizationsService
	Billing            *BillingService
	Checks             *ChecksService
	CodeScanning       *CodeScanningService
	CodesOfConduct     *CodesOfConductService
	Codespaces         *CodespacesService
	Copilot            *CopilotService
	Dependabot         *DependabotService
	DependencyGraph    *DependencyGraphService
	Emojis             *EmojisService
	Enterprise         *EnterpriseService
	Gists              *GistsService
	Git                *GitService
	Gitignores         *GitignoresService
	Interactions       *InteractionsService
	IssueImport        *IssueImportService
	Issues             *IssuesService
	Licenses           *LicensesService
	Markdown           *MarkdownService
	Marketplace        *MarketplaceService
	Meta               *MetaService
	Migrations         *MigrationService
	Organizations      *OrganizationsService
	Projects           *ProjectsService
	PullRequests       *PullRequestsService
	RateLimit          *RateLimitService
	Reactions          *ReactionsService
	Repositories       *RepositoriesService
	SCIM               *SCIMService
	Search             *SearchService
	SecretScanning     *SecretScanningService
	SecurityAdvisories *SecurityAdvisoriesService
	Teams              *TeamsService
	Users              *UsersService
}

type service struct {
	client *Client
}

// Client returns the http.Client used by this GitHub client.
// This should only be used for requests to the GitHub API because
// request headers will contain an authorization token.
func ( *Client) () *http.Client {
	.clientMu.Lock()
	defer .clientMu.Unlock()
	 := *.client
	return &
}

// ListOptions specifies the optional parameters to various List methods that
// support offset pagination.
type ListOptions struct {
	// For paginated result sets, page of results to retrieve.
	Page int `url:"page,omitempty"`

	// For paginated result sets, the number of results to include per page.
	PerPage int `url:"per_page,omitempty"`
}

// ListCursorOptions specifies the optional parameters to various List methods that
// support cursor pagination.
type ListCursorOptions struct {
	// For paginated result sets, page of results to retrieve.
	Page string `url:"page,omitempty"`

	// For paginated result sets, the number of results to include per page.
	PerPage int `url:"per_page,omitempty"`

	// For paginated result sets, the number of results per page (max 100), starting from the first matching result.
	// This parameter must not be used in combination with last.
	First int `url:"first,omitempty"`

	// For paginated result sets, the number of results per page (max 100), starting from the last matching result.
	// This parameter must not be used in combination with first.
	Last int `url:"last,omitempty"`

	// A cursor, as given in the Link header. If specified, the query only searches for events after this cursor.
	After string `url:"after,omitempty"`

	// A cursor, as given in the Link header. If specified, the query only searches for events before this cursor.
	Before string `url:"before,omitempty"`

	// A cursor, as given in the Link header. If specified, the query continues the search using this cursor.
	Cursor string `url:"cursor,omitempty"`
}

// UploadOptions specifies the parameters to methods that support uploads.
type UploadOptions struct {
	Name      string `url:"name,omitempty"`
	Label     string `url:"label,omitempty"`
	MediaType string `url:"-"`
}

// RawType represents type of raw format of a request instead of JSON.
type RawType uint8

const (
	// Diff format.
	Diff RawType = 1 + iota
	// Patch format.
	Patch
)

// RawOptions specifies parameters when user wants to get raw format of
// a response instead of JSON.
type RawOptions struct {
	Type RawType
}

// addOptions adds the parameters in opts as URL query parameters to s. opts
// must be a struct whose fields may contain "url" tags.
func addOptions( string,  interface{}) (string, error) {
	 := reflect.ValueOf()
	if .Kind() == reflect.Ptr && .IsNil() {
		return , nil
	}

	,  := url.Parse()
	if  != nil {
		return , 
	}

	,  := query.Values()
	if  != nil {
		return , 
	}

	.RawQuery = .Encode()
	return .String(), nil
}

// NewClient returns a new GitHub API client. If a nil httpClient is
// provided, a new http.Client will be used. To use API methods which require
// authentication, either use Client.WithAuthToken or provide NewClient with
// an http.Client that will perform the authentication for you (such as that
// provided by the golang.org/x/oauth2 library).
func ( *http.Client) *Client {
	if  == nil {
		 = &http.Client{}
	}
	 := *
	 := &Client{client: &}
	.initialize()
	return 
}

// WithAuthToken returns a copy of the client configured to use the provided token for the Authorization header.
func ( *Client) ( string) *Client {
	 := .copy()
	defer .initialize()
	 := .client.Transport
	if  == nil {
		 = http.DefaultTransport
	}
	.client.Transport = roundTripperFunc(
		func( *http.Request) (*http.Response, error) {
			 = .Clone(.Context())
			.Header.Set("Authorization", fmt.Sprintf("Bearer %s", ))
			return .RoundTrip()
		},
	)
	return 
}

// WithEnterpriseURLs returns a copy of the client configured to use the provided base and
// upload URLs. If the base URL does not have the suffix "/api/v3/", it will be added
// automatically. If the upload URL does not have the suffix "/api/uploads", it will be
// added automatically.
//
// Note that WithEnterpriseURLs is a convenience helper only;
// its behavior is equivalent to setting the BaseURL and UploadURL fields.
//
// Another important thing is that by default, the GitHub Enterprise URL format
// should be http(s)://[hostname]/api/v3/ or you will always receive the 406 status code.
// The upload URL format should be http(s)://[hostname]/api/uploads/.
func ( *Client) (,  string) (*Client, error) {
	 := .copy()
	defer .initialize()
	var  error
	.BaseURL,  = url.Parse()
	if  != nil {
		return nil, 
	}

	if !strings.HasSuffix(.BaseURL.Path, "/") {
		.BaseURL.Path += "/"
	}
	if !strings.HasSuffix(.BaseURL.Path, "/api/v3/") &&
		!strings.HasPrefix(.BaseURL.Host, "api.") &&
		!strings.Contains(.BaseURL.Host, ".api.") {
		.BaseURL.Path += "api/v3/"
	}

	.UploadURL,  = url.Parse()
	if  != nil {
		return nil, 
	}

	if !strings.HasSuffix(.UploadURL.Path, "/") {
		.UploadURL.Path += "/"
	}
	if !strings.HasSuffix(.UploadURL.Path, "/api/uploads/") &&
		!strings.HasPrefix(.UploadURL.Host, "api.") &&
		!strings.Contains(.UploadURL.Host, ".api.") {
		.UploadURL.Path += "api/uploads/"
	}
	return , nil
}

// initialize sets default values and initializes services.
func ( *Client) () {
	if .client == nil {
		.client = &http.Client{}
	}
	if .BaseURL == nil {
		.BaseURL, _ = url.Parse(defaultBaseURL)
	}
	if .UploadURL == nil {
		.UploadURL, _ = url.Parse(uploadBaseURL)
	}
	if .UserAgent == "" {
		.UserAgent = defaultUserAgent
	}
	.common.client = 
	.Actions = (*ActionsService)(&.common)
	.Activity = (*ActivityService)(&.common)
	.Admin = (*AdminService)(&.common)
	.Apps = (*AppsService)(&.common)
	.Authorizations = (*AuthorizationsService)(&.common)
	.Billing = (*BillingService)(&.common)
	.Checks = (*ChecksService)(&.common)
	.CodeScanning = (*CodeScanningService)(&.common)
	.Codespaces = (*CodespacesService)(&.common)
	.CodesOfConduct = (*CodesOfConductService)(&.common)
	.Copilot = (*CopilotService)(&.common)
	.Dependabot = (*DependabotService)(&.common)
	.DependencyGraph = (*DependencyGraphService)(&.common)
	.Emojis = (*EmojisService)(&.common)
	.Enterprise = (*EnterpriseService)(&.common)
	.Gists = (*GistsService)(&.common)
	.Git = (*GitService)(&.common)
	.Gitignores = (*GitignoresService)(&.common)
	.Interactions = (*InteractionsService)(&.common)
	.IssueImport = (*IssueImportService)(&.common)
	.Issues = (*IssuesService)(&.common)
	.Licenses = (*LicensesService)(&.common)
	.Markdown = (*MarkdownService)(&.common)
	.Marketplace = &MarketplaceService{client: }
	.Meta = (*MetaService)(&.common)
	.Migrations = (*MigrationService)(&.common)
	.Organizations = (*OrganizationsService)(&.common)
	.Projects = (*ProjectsService)(&.common)
	.PullRequests = (*PullRequestsService)(&.common)
	.RateLimit = (*RateLimitService)(&.common)
	.Reactions = (*ReactionsService)(&.common)
	.Repositories = (*RepositoriesService)(&.common)
	.SCIM = (*SCIMService)(&.common)
	.Search = (*SearchService)(&.common)
	.SecretScanning = (*SecretScanningService)(&.common)
	.SecurityAdvisories = (*SecurityAdvisoriesService)(&.common)
	.Teams = (*TeamsService)(&.common)
	.Users = (*UsersService)(&.common)
}

// copy returns a copy of the current client. It must be initialized before use.
func ( *Client) () *Client {
	.clientMu.Lock()
	// can't use *c here because that would copy mutexes by value.
	 := Client{
		client:                  &http.Client{},
		UserAgent:               .UserAgent,
		BaseURL:                 .BaseURL,
		UploadURL:               .UploadURL,
		secondaryRateLimitReset: .secondaryRateLimitReset,
	}
	.clientMu.Unlock()
	if .client != nil {
		.client.Transport = .client.Transport
		.client.CheckRedirect = .client.CheckRedirect
		.client.Jar = .client.Jar
		.client.Timeout = .client.Timeout
	}
	.rateMu.Lock()
	copy(.rateLimits[:], .rateLimits[:])
	.rateMu.Unlock()
	return &
}

// NewClientWithEnvProxy enhances NewClient with the HttpProxy env.
func () *Client {
	return NewClient(&http.Client{Transport: &http.Transport{Proxy: http.ProxyFromEnvironment}})
}

// NewTokenClient returns a new GitHub API client authenticated with the provided token.
// Deprecated: Use NewClient(nil).WithAuthToken(token) instead.
func ( context.Context,  string) *Client {
	// This always returns a nil error.
	return NewClient(nil).WithAuthToken()
}

// NewEnterpriseClient returns a new GitHub API client with provided
// base URL and upload URL (often is your GitHub Enterprise hostname).
//
// Deprecated: Use NewClient(httpClient).WithEnterpriseURLs(baseURL, uploadURL) instead.
func (,  string,  *http.Client) (*Client, error) {
	return NewClient().WithEnterpriseURLs(, )
}

// RequestOption represents an option that can modify an http.Request.
type RequestOption func(req *http.Request)

// WithVersion overrides the GitHub v3 API version for this individual request.
// For more information, see:
// https://github.blog/2022-11-28-to-infinity-and-beyond-enabling-the-future-of-githubs-rest-api-with-api-versioning/
func ( string) RequestOption {
	return func( *http.Request) {
		.Header.Set(headerAPIVersion, )
	}
}

// NewRequest creates an API request. A relative URL can be provided in urlStr,
// in which case it is resolved relative to the BaseURL of the Client.
// Relative URLs should always be specified without a preceding slash. If
// specified, the value pointed to by body is JSON encoded and included as the
// request body.
func ( *Client) (,  string,  interface{},  ...RequestOption) (*http.Request, error) {
	if !strings.HasSuffix(.BaseURL.Path, "/") {
		return nil, fmt.Errorf("BaseURL must have a trailing slash, but %q does not", .BaseURL)
	}

	,  := .BaseURL.Parse()
	if  != nil {
		return nil, 
	}

	var  io.ReadWriter
	if  != nil {
		 = &bytes.Buffer{}
		 := json.NewEncoder()
		.SetEscapeHTML(false)
		 := .Encode()
		if  != nil {
			return nil, 
		}
	}

	,  := http.NewRequest(, .String(), )
	if  != nil {
		return nil, 
	}

	if  != nil {
		.Header.Set("Content-Type", "application/json")
	}
	.Header.Set("Accept", mediaTypeV3)
	if .UserAgent != "" {
		.Header.Set("User-Agent", .UserAgent)
	}
	.Header.Set(headerAPIVersion, defaultAPIVersion)

	for ,  := range  {
		()
	}

	return , nil
}

// NewFormRequest creates an API request. A relative URL can be provided in urlStr,
// in which case it is resolved relative to the BaseURL of the Client.
// Relative URLs should always be specified without a preceding slash.
// Body is sent with Content-Type: application/x-www-form-urlencoded.
func ( *Client) ( string,  io.Reader,  ...RequestOption) (*http.Request, error) {
	if !strings.HasSuffix(.BaseURL.Path, "/") {
		return nil, fmt.Errorf("BaseURL must have a trailing slash, but %q does not", .BaseURL)
	}

	,  := .BaseURL.Parse()
	if  != nil {
		return nil, 
	}

	,  := http.NewRequest(http.MethodPost, .String(), )
	if  != nil {
		return nil, 
	}

	.Header.Set("Content-Type", "application/x-www-form-urlencoded")
	.Header.Set("Accept", mediaTypeV3)
	if .UserAgent != "" {
		.Header.Set("User-Agent", .UserAgent)
	}
	.Header.Set(headerAPIVersion, defaultAPIVersion)

	for ,  := range  {
		()
	}

	return , nil
}

// NewUploadRequest creates an upload request. A relative URL can be provided in
// urlStr, in which case it is resolved relative to the UploadURL of the Client.
// Relative URLs should always be specified without a preceding slash.
func ( *Client) ( string,  io.Reader,  int64,  string,  ...RequestOption) (*http.Request, error) {
	if !strings.HasSuffix(.UploadURL.Path, "/") {
		return nil, fmt.Errorf("UploadURL must have a trailing slash, but %q does not", .UploadURL)
	}
	,  := .UploadURL.Parse()
	if  != nil {
		return nil, 
	}

	,  := http.NewRequest("POST", .String(), )
	if  != nil {
		return nil, 
	}

	.ContentLength = 

	if  == "" {
		 = defaultMediaType
	}
	.Header.Set("Content-Type", )
	.Header.Set("Accept", mediaTypeV3)
	.Header.Set("User-Agent", .UserAgent)
	.Header.Set(headerAPIVersion, defaultAPIVersion)

	for ,  := range  {
		()
	}

	return , nil
}

// Response is a GitHub API response. This wraps the standard http.Response
// returned from GitHub and provides convenient access to things like
// pagination links.
type Response struct {
	*http.Response

	// These fields provide the page values for paginating through a set of
	// results. Any or all of these may be set to the zero value for
	// responses that are not part of a paginated set, or for which there
	// are no additional pages.
	//
	// These fields support what is called "offset pagination" and should
	// be used with the ListOptions struct.
	NextPage  int
	PrevPage  int
	FirstPage int
	LastPage  int

	// Additionally, some APIs support "cursor pagination" instead of offset.
	// This means that a token points directly to the next record which
	// can lead to O(1) performance compared to O(n) performance provided
	// by offset pagination.
	//
	// For APIs that support cursor pagination (such as
	// TeamsService.ListIDPGroupsInOrganization), the following field
	// will be populated to point to the next page.
	//
	// To use this token, set ListCursorOptions.Page to this value before
	// calling the endpoint again.
	NextPageToken string

	// For APIs that support cursor pagination, such as RepositoriesService.ListHookDeliveries,
	// the following field will be populated to point to the next page.
	// Set ListCursorOptions.Cursor to this value when calling the endpoint again.
	Cursor string

	// For APIs that support before/after pagination, such as OrganizationsService.AuditLog.
	Before string
	After  string

	// Explicitly specify the Rate type so Rate's String() receiver doesn't
	// propagate to Response.
	Rate Rate

	// token's expiration date. Timestamp is 0001-01-01 when token doesn't expire.
	// So it is valid for TokenExpiration.Equal(Timestamp{}) or TokenExpiration.Time.After(time.Now())
	TokenExpiration Timestamp
}

// newResponse creates a new Response for the provided http.Response.
// r must not be nil.
func newResponse( *http.Response) *Response {
	 := &Response{Response: }
	.populatePageValues()
	.Rate = parseRate()
	.TokenExpiration = parseTokenExpiration()
	return 
}

// populatePageValues parses the HTTP Link response headers and populates the
// various pagination link values in the Response.
func ( *Response) () {
	if ,  := .Response.Header["Link"];  && len() > 0 {
		for ,  := range strings.Split([0], ",") {
			 := strings.Split(strings.TrimSpace(), ";")

			// link must at least have href and rel
			if len() < 2 {
				continue
			}

			// ensure href is properly formatted
			if !strings.HasPrefix([0], "<") || !strings.HasSuffix([0], ">") {
				continue
			}

			// try to pull out page parameter
			,  := url.Parse([0][1 : len([0])-1])
			if  != nil {
				continue
			}

			 := .Query()

			if  := .Get("cursor");  != "" {
				for ,  := range [1:] {
					switch strings.TrimSpace() {
					case `rel="next"`:
						.Cursor = 
					}
				}

				continue
			}

			 := .Get("page")
			 := .Get("since")
			 := .Get("before")
			 := .Get("after")

			if  == "" &&  == "" &&  == "" &&  == "" {
				continue
			}

			if  != "" &&  == "" {
				 = 
			}

			for ,  := range [1:] {
				switch strings.TrimSpace() {
				case `rel="next"`:
					if .NextPage,  = strconv.Atoi();  != nil {
						.NextPageToken = 
					}
					.After = 
				case `rel="prev"`:
					.PrevPage, _ = strconv.Atoi()
					.Before = 
				case `rel="first"`:
					.FirstPage, _ = strconv.Atoi()
				case `rel="last"`:
					.LastPage, _ = strconv.Atoi()
				}
			}
		}
	}
}

// parseRate parses the rate related headers.
func parseRate( *http.Response) Rate {
	var  Rate
	if  := .Header.Get(headerRateLimit);  != "" {
		.Limit, _ = strconv.Atoi()
	}
	if  := .Header.Get(headerRateRemaining);  != "" {
		.Remaining, _ = strconv.Atoi()
	}
	if  := .Header.Get(headerRateReset);  != "" {
		if ,  := strconv.ParseInt(, 10, 64);  != 0 {
			.Reset = Timestamp{time.Unix(, 0)}
		}
	}
	return 
}

// parseSecondaryRate parses the secondary rate related headers,
// and returns the time to retry after.
func parseSecondaryRate( *http.Response) *time.Duration {
	// According to GitHub support, the "Retry-After" header value will be
	// an integer which represents the number of seconds that one should
	// wait before resuming making requests.
	if  := .Header.Get(headerRetryAfter);  != "" {
		,  := strconv.ParseInt(, 10, 64) // Error handling is noop.
		 := time.Duration() * time.Second
		return &
	}

	// According to GitHub support, endpoints might return x-ratelimit-reset instead,
	// as an integer which represents the number of seconds since epoch UTC,
	// representing the time to resume making requests.
	if  := .Header.Get(headerRateReset);  != "" {
		,  := strconv.ParseInt(, 10, 64) // Error handling is noop.
		 := time.Until(time.Unix(, 0))
		return &
	}

	return nil
}

// parseTokenExpiration parses the TokenExpiration related headers.
// Returns 0001-01-01 if the header is not defined or could not be parsed.
func parseTokenExpiration( *http.Response) Timestamp {
	if  := .Header.Get(headerTokenExpiration);  != "" {
		if ,  := time.Parse("2006-01-02 15:04:05 MST", );  == nil {
			return Timestamp{.Local()}
		}
		// Some tokens include the timezone offset instead of the timezone.
		// https://github.com/google/go-github/issues/2649
		if ,  := time.Parse("2006-01-02 15:04:05 -0700", );  == nil {
			return Timestamp{.Local()}
		}
	}
	return Timestamp{} // 0001-01-01 00:00:00
}

type requestContext uint8

const (
	bypassRateLimitCheck requestContext = iota
	SleepUntilPrimaryRateLimitResetWhenRateLimited
)

// BareDo sends an API request and lets you handle the api response. If an error
// or API Error occurs, the error will contain more information. Otherwise you
// are supposed to read and close the response's Body. If rate limit is exceeded
// and reset time is in the future, BareDo returns *RateLimitError immediately
// without making a network API call.
//
// The provided ctx must be non-nil, if it is nil an error is returned. If it is
// canceled or times out, ctx.Err() will be returned.
func ( *Client) ( context.Context,  *http.Request) (*Response, error) {
	if  == nil {
		return nil, errNonNilContext
	}

	 = withContext(, )

	 := GetRateLimitCategory(.Method, .URL.Path)

	if  := .Value(bypassRateLimitCheck);  == nil {
		// If we've hit rate limit, don't make further requests before Reset time.
		if  := .checkRateLimitBeforeDo(, );  != nil {
			return &Response{
				Response: .Response,
				Rate:     .Rate,
			}, 
		}
		// If we've hit a secondary rate limit, don't make further requests before Retry After.
		if  := .checkSecondaryRateLimitBeforeDo();  != nil {
			return &Response{
				Response: .Response,
			}, 
		}
	}

	,  := .client.Do()
	if  != nil {
		// If we got an error, and the context has been canceled,
		// the context's error is probably more useful.
		select {
		case <-.Done():
			return nil, .Err()
		default:
		}

		// If the error type is *url.Error, sanitize its URL before returning.
		if ,  := .(*url.Error);  {
			if ,  := url.Parse(.URL);  == nil {
				.URL = sanitizeURL().String()
				return nil, 
			}
		}

		return nil, 
	}

	 := newResponse()

	// Don't update the rate limits if this was a cached response.
	// X-From-Cache is set by https://github.com/gregjones/httpcache
	if .Header.Get("X-From-Cache") == "" {
		.rateMu.Lock()
		.rateLimits[] = .Rate
		.rateMu.Unlock()
	}

	 = CheckResponse()
	if  != nil {
		defer .Body.Close()
		// Special case for AcceptedErrors. If an AcceptedError
		// has been encountered, the response's payload will be
		// added to the AcceptedError and returned.
		//
		// Issue #1022
		,  := .(*AcceptedError)
		if  {
			,  := io.ReadAll(.Body)
			if  != nil {
				return , 
			}

			.Raw = 
			 = 
		}

		,  := .(*RateLimitError)
		if  && .Context().Value(SleepUntilPrimaryRateLimitResetWhenRateLimited) != nil {
			if  := sleepUntilResetWithBuffer(.Context(), .Rate.Reset.Time);  != nil {
				return , 
			}
			// retry the request once when the rate limit has reset
			return .(context.WithValue(.Context(), SleepUntilPrimaryRateLimitResetWhenRateLimited, nil), )
		}

		// Update the secondary rate limit if we hit it.
		,  := .(*AbuseRateLimitError)
		if  && .RetryAfter != nil {
			.rateMu.Lock()
			.secondaryRateLimitReset = time.Now().Add(*.RetryAfter)
			.rateMu.Unlock()
		}
	}
	return , 
}

// Do sends an API request and returns the API response. The API response is
// JSON decoded and stored in the value pointed to by v, or returned as an
// error if an API error has occurred. If v implements the io.Writer interface,
// the raw response body will be written to v, without attempting to first
// decode it. If v is nil, and no error happens, the response is returned as is.
// If rate limit is exceeded and reset time is in the future, Do returns
// *RateLimitError immediately without making a network API call.
//
// The provided ctx must be non-nil, if it is nil an error is returned. If it
// is canceled or times out, ctx.Err() will be returned.
func ( *Client) ( context.Context,  *http.Request,  interface{}) (*Response, error) {
	,  := .BareDo(, )
	if  != nil {
		return , 
	}
	defer .Body.Close()

	switch v := .(type) {
	case nil:
	case io.Writer:
		_,  = io.Copy(, .Body)
	default:
		 := json.NewDecoder(.Body).Decode()
		if  == io.EOF {
			 = nil // ignore EOF errors caused by empty response body
		}
		if  != nil {
			 = 
		}
	}
	return , 
}

// checkRateLimitBeforeDo does not make any network calls, but uses existing knowledge from
// current client state in order to quickly check if *RateLimitError can be immediately returned
// from Client.Do, and if so, returns it so that Client.Do can skip making a network API call unnecessarily.
// Otherwise it returns nil, and Client.Do should proceed normally.
func ( *Client) ( *http.Request,  RateLimitCategory) *RateLimitError {
	.rateMu.Lock()
	 := .rateLimits[]
	.rateMu.Unlock()
	if !.Reset.Time.IsZero() && .Remaining == 0 && time.Now().Before(.Reset.Time) {
		// Create a fake response.
		 := &http.Response{
			Status:     http.StatusText(http.StatusForbidden),
			StatusCode: http.StatusForbidden,
			Request:    ,
			Header:     make(http.Header),
			Body:       io.NopCloser(strings.NewReader("")),
		}

		if .Context().Value(SleepUntilPrimaryRateLimitResetWhenRateLimited) != nil {
			if  := sleepUntilResetWithBuffer(.Context(), .Reset.Time);  == nil {
				return nil
			}
			return &RateLimitError{
				Rate:     ,
				Response: ,
				Message:  fmt.Sprintf("Context cancelled while waiting for rate limit to reset until %v, not making remote request.", .Reset.Time),
			}
		}

		return &RateLimitError{
			Rate:     ,
			Response: ,
			Message:  fmt.Sprintf("API rate limit of %v still exceeded until %v, not making remote request.", .Limit, .Reset.Time),
		}
	}

	return nil
}

// checkSecondaryRateLimitBeforeDo does not make any network calls, but uses existing knowledge from
// current client state in order to quickly check if *AbuseRateLimitError can be immediately returned
// from Client.Do, and if so, returns it so that Client.Do can skip making a network API call unnecessarily.
// Otherwise it returns nil, and Client.Do should proceed normally.
func ( *Client) ( *http.Request) *AbuseRateLimitError {
	.rateMu.Lock()
	 := .secondaryRateLimitReset
	.rateMu.Unlock()
	if !.IsZero() && time.Now().Before() {
		// Create a fake response.
		 := &http.Response{
			Status:     http.StatusText(http.StatusForbidden),
			StatusCode: http.StatusForbidden,
			Request:    ,
			Header:     make(http.Header),
			Body:       io.NopCloser(strings.NewReader("")),
		}

		 := time.Until()
		return &AbuseRateLimitError{
			Response:   ,
			Message:    fmt.Sprintf("API secondary rate limit exceeded until %v, not making remote request.", ),
			RetryAfter: &,
		}
	}

	return nil
}

// compareHTTPResponse returns whether two http.Response objects are equal or not.
// Currently, only StatusCode is checked. This function is used when implementing the
// Is(error) bool interface for the custom error types in this package.
func compareHTTPResponse(,  *http.Response) bool {
	if  == nil &&  == nil {
		return true
	}

	if  != nil &&  != nil {
		return .StatusCode == .StatusCode
	}
	return false
}

/*
An ErrorResponse reports one or more errors caused by an API request.

GitHub API docs: https://docs.github.com/rest/#client-errors
*/
type ErrorResponse struct {
	Response *http.Response `json:"-"`       // HTTP response that caused this error
	Message  string         `json:"message"` // error message
	Errors   []Error        `json:"errors"`  // more detail on individual errors
	// Block is only populated on certain types of errors such as code 451.
	Block *ErrorBlock `json:"block,omitempty"`
	// Most errors will also include a documentation_url field pointing
	// to some content that might help you resolve the error, see
	// https://docs.github.com/rest/#client-errors
	DocumentationURL string `json:"documentation_url,omitempty"`
}

// ErrorBlock contains a further explanation for the reason of an error.
// See https://developer.github.com/changes/2016-03-17-the-451-status-code-is-now-supported/
// for more information.
type ErrorBlock struct {
	Reason    string     `json:"reason,omitempty"`
	CreatedAt *Timestamp `json:"created_at,omitempty"`
}

func ( *ErrorResponse) () string {
	if .Response != nil && .Response.Request != nil {
		return fmt.Sprintf("%v %v: %d %v %+v",
			.Response.Request.Method, sanitizeURL(.Response.Request.URL),
			.Response.StatusCode, .Message, .Errors)
	}

	if .Response != nil {
		return fmt.Sprintf("%d %v %+v", .Response.StatusCode, .Message, .Errors)
	}

	return fmt.Sprintf("%v %+v", .Message, .Errors)
}

// Is returns whether the provided error equals this error.
func ( *ErrorResponse) ( error) bool {
	,  := .(*ErrorResponse)
	if ! {
		return false
	}

	if .Message != .Message || (.DocumentationURL != .DocumentationURL) ||
		!compareHTTPResponse(.Response, .Response) {
		return false
	}

	// Compare Errors.
	if len(.Errors) != len(.Errors) {
		return false
	}
	for  := range .Errors {
		if .Errors[] != .Errors[] {
			return false
		}
	}

	// Compare Block.
	if (.Block != nil && .Block == nil) || (.Block == nil && .Block != nil) {
		return false
	}
	if .Block != nil && .Block != nil {
		if .Block.Reason != .Block.Reason {
			return false
		}
		if (.Block.CreatedAt != nil && .Block.CreatedAt == nil) || (.Block.CreatedAt ==
			nil && .Block.CreatedAt != nil) {
			return false
		}
		if .Block.CreatedAt != nil && .Block.CreatedAt != nil {
			if *(.Block.CreatedAt) != *(.Block.CreatedAt) {
				return false
			}
		}
	}

	return true
}

// TwoFactorAuthError occurs when using HTTP Basic Authentication for a user
// that has two-factor authentication enabled. The request can be reattempted
// by providing a one-time password in the request.
type TwoFactorAuthError ErrorResponse

func ( *TwoFactorAuthError) () string { return (*ErrorResponse)().Error() }

// RateLimitError occurs when GitHub returns 403 Forbidden response with a rate limit
// remaining value of 0.
type RateLimitError struct {
	Rate     Rate           // Rate specifies last known rate limit for the client
	Response *http.Response // HTTP response that caused this error
	Message  string         `json:"message"` // error message
}

func ( *RateLimitError) () string {
	return fmt.Sprintf("%v %v: %d %v %v",
		.Response.Request.Method, sanitizeURL(.Response.Request.URL),
		.Response.StatusCode, .Message, formatRateReset(time.Until(.Rate.Reset.Time)))
}

// Is returns whether the provided error equals this error.
func ( *RateLimitError) ( error) bool {
	,  := .(*RateLimitError)
	if ! {
		return false
	}

	return .Rate == .Rate &&
		.Message == .Message &&
		compareHTTPResponse(.Response, .Response)
}

// AcceptedError occurs when GitHub returns 202 Accepted response with an
// empty body, which means a job was scheduled on the GitHub side to process
// the information needed and cache it.
// Technically, 202 Accepted is not a real error, it's just used to
// indicate that results are not ready yet, but should be available soon.
// The request can be repeated after some time.
type AcceptedError struct {
	// Raw contains the response body.
	Raw []byte
}

func (*AcceptedError) () string {
	return "job scheduled on GitHub side; try again later"
}

// Is returns whether the provided error equals this error.
func ( *AcceptedError) ( error) bool {
	,  := .(*AcceptedError)
	if ! {
		return false
	}
	return bytes.Equal(.Raw, .Raw)
}

// AbuseRateLimitError occurs when GitHub returns 403 Forbidden response with the
// "documentation_url" field value equal to "https://docs.github.com/rest/overview/rate-limits-for-the-rest-api#about-secondary-rate-limits".
type AbuseRateLimitError struct {
	Response *http.Response // HTTP response that caused this error
	Message  string         `json:"message"` // error message

	// RetryAfter is provided with some abuse rate limit errors. If present,
	// it is the amount of time that the client should wait before retrying.
	// Otherwise, the client should try again later (after an unspecified amount of time).
	RetryAfter *time.Duration
}

func ( *AbuseRateLimitError) () string {
	return fmt.Sprintf("%v %v: %d %v",
		.Response.Request.Method, sanitizeURL(.Response.Request.URL),
		.Response.StatusCode, .Message)
}

// Is returns whether the provided error equals this error.
func ( *AbuseRateLimitError) ( error) bool {
	,  := .(*AbuseRateLimitError)
	if ! {
		return false
	}

	return .Message == .Message &&
		.RetryAfter == .RetryAfter &&
		compareHTTPResponse(.Response, .Response)
}

// sanitizeURL redacts the client_secret parameter from the URL which may be
// exposed to the user.
func sanitizeURL( *url.URL) *url.URL {
	if  == nil {
		return nil
	}
	 := .Query()
	if len(.Get("client_secret")) > 0 {
		.Set("client_secret", "REDACTED")
		.RawQuery = .Encode()
	}
	return 
}

/*
An Error reports more details on an individual error in an ErrorResponse.
These are the possible validation error codes:

	missing:
	    resource does not exist
	missing_field:
	    a required field on a resource has not been set
	invalid:
	    the formatting of a field is invalid
	already_exists:
	    another resource has the same valid as this field
	custom:
	    some resources return this (e.g. github.User.CreateKey()), additional
	    information is set in the Message field of the Error

GitHub error responses structure are often undocumented and inconsistent.
Sometimes error is just a simple string (Issue #540).
In such cases, Message represents an error message as a workaround.

GitHub API docs: https://docs.github.com/rest/#client-errors
*/
type Error struct {
	Resource string `json:"resource"` // resource on which the error occurred
	Field    string `json:"field"`    // field on which the error occurred
	Code     string `json:"code"`     // validation error code
	Message  string `json:"message"`  // Message describing the error. Errors with Code == "custom" will always have this set.
}

func ( *Error) () string {
	return fmt.Sprintf("%v error caused by %v field on %v resource",
		.Code, .Field, .Resource)
}

func ( *Error) ( []byte) error {
	type  Error // avoid infinite recursion by using type alias.
	if  := json.Unmarshal(, (*)());  != nil {
		return json.Unmarshal(, &.Message) // data can be json string.
	}
	return nil
}

// CheckResponse checks the API response for errors, and returns them if
// present. A response is considered an error if it has a status code outside
// the 200 range or equal to 202 Accepted.
// API error responses are expected to have response
// body, and a JSON response body that maps to ErrorResponse.
//
// The error type will be *RateLimitError for rate limit exceeded errors,
// *AcceptedError for 202 Accepted status codes,
// and *TwoFactorAuthError for two-factor authentication errors.
func ( *http.Response) error {
	if .StatusCode == http.StatusAccepted {
		return &AcceptedError{}
	}
	if  := .StatusCode; 200 <=  &&  <= 299 {
		return nil
	}

	 := &ErrorResponse{Response: }
	,  := io.ReadAll(.Body)
	if  == nil &&  != nil {
		 = json.Unmarshal(, )
		if  != nil {
			// reset the response as if this never happened
			 = &ErrorResponse{Response: }
		}
	}
	// Re-populate error response body because GitHub error responses are often
	// undocumented and inconsistent.
	// Issue #1136, #540.
	.Body = io.NopCloser(bytes.NewBuffer())
	switch {
	case .StatusCode == http.StatusUnauthorized && strings.HasPrefix(.Header.Get(headerOTP), "required"):
		return (*TwoFactorAuthError)()
	case .StatusCode == http.StatusForbidden && .Header.Get(headerRateRemaining) == "0":
		return &RateLimitError{
			Rate:     parseRate(),
			Response: .Response,
			Message:  .Message,
		}
	case .StatusCode == http.StatusForbidden &&
		(strings.HasSuffix(.DocumentationURL, "#abuse-rate-limits") ||
			strings.HasSuffix(.DocumentationURL, "secondary-rate-limits")):
		 := &AbuseRateLimitError{
			Response: .Response,
			Message:  .Message,
		}
		if  := parseSecondaryRate();  != nil {
			.RetryAfter = 
		}
		return 
	default:
		return 
	}
}

// parseBoolResponse determines the boolean result from a GitHub API response.
// Several GitHub API methods return boolean responses indicated by the HTTP
// status code in the response (true indicated by a 204, false indicated by a
// 404). This helper function will determine that result and hide the 404
// error if present. Any other error will be returned through as-is.
func parseBoolResponse( error) (bool, error) {
	if  == nil {
		return true, nil
	}

	if ,  := .(*ErrorResponse);  && .Response.StatusCode == http.StatusNotFound {
		// Simply false. In this one case, we do not pass the error through.
		return false, nil
	}

	// some other real error occurred
	return false, 
}

type RateLimitCategory uint8

const (
	CoreCategory RateLimitCategory = iota
	SearchCategory
	GraphqlCategory
	IntegrationManifestCategory
	SourceImportCategory
	CodeScanningUploadCategory
	ActionsRunnerRegistrationCategory
	ScimCategory
	DependencySnapshotsCategory
	CodeSearchCategory
	AuditLogCategory

	Categories // An array of this length will be able to contain all rate limit categories.
)

// GetRateLimitCategory returns the rate limit RateLimitCategory of the endpoint, determined by HTTP method and Request.URL.Path.
func (,  string) RateLimitCategory {
	switch {
	// https://docs.github.com/rest/rate-limit#about-rate-limits
	default:
		// NOTE: coreCategory is returned for actionsRunnerRegistrationCategory too,
		// because no API found for this category.
		return CoreCategory

	// https://docs.github.com/en/rest/search/search#search-code
	case strings.HasPrefix(, "/search/code") &&
		 == http.MethodGet:
		return CodeSearchCategory

	case strings.HasPrefix(, "/search/"):
		return SearchCategory
	case  == "/graphql":
		return GraphqlCategory
	case strings.HasPrefix(, "/app-manifests/") &&
		strings.HasSuffix(, "/conversions") &&
		 == http.MethodPost:
		return IntegrationManifestCategory

	// https://docs.github.com/rest/migrations/source-imports#start-an-import
	case strings.HasPrefix(, "/repos/") &&
		strings.HasSuffix(, "/import") &&
		 == http.MethodPut:
		return SourceImportCategory

	// https://docs.github.com/rest/code-scanning#upload-an-analysis-as-sarif-data
	case strings.HasSuffix(, "/code-scanning/sarifs"):
		return CodeScanningUploadCategory

	// https://docs.github.com/enterprise-cloud@latest/rest/scim
	case strings.HasPrefix(, "/scim/"):
		return ScimCategory

	// https://docs.github.com/en/rest/dependency-graph/dependency-submission#create-a-snapshot-of-dependencies-for-a-repository
	case strings.HasPrefix(, "/repos/") &&
		strings.HasSuffix(, "/dependency-graph/snapshots") &&
		 == http.MethodPost:
		return DependencySnapshotsCategory

	// https://docs.github.com/en/enterprise-cloud@latest/rest/orgs/orgs?apiVersion=2022-11-28#get-the-audit-log-for-an-organization
	case strings.HasSuffix(, "/audit-log"):
		return AuditLogCategory
	}
}

// RateLimits returns the rate limits for the current client.
//
// Deprecated: Use RateLimitService.Get instead.
func ( *Client) ( context.Context) (*RateLimits, *Response, error) {
	return .RateLimit.Get()
}

func setCredentialsAsHeaders( *http.Request, ,  string) *http.Request {
	// To set extra headers, we must make a copy of the Request so
	// that we don't modify the Request we were given. This is required by the
	// specification of http.RoundTripper.
	//
	// Since we are going to modify only req.Header here, we only need a deep copy
	// of req.Header.
	 := new(http.Request)
	* = *
	.Header = make(http.Header, len(.Header))

	for ,  := range .Header {
		.Header[] = append([]string(nil), ...)
	}
	.SetBasicAuth(, )
	return 
}

/*
UnauthenticatedRateLimitedTransport allows you to make unauthenticated calls
that need to use a higher rate limit associated with your OAuth application.

	t := &github.UnauthenticatedRateLimitedTransport{
		ClientID:     "your app's client ID",
		ClientSecret: "your app's client secret",
	}
	client := github.NewClient(t.Client())

This will add the client id and secret as a base64-encoded string in the format
ClientID:ClientSecret and apply it as an "Authorization": "Basic" header.

See https://docs.github.com/rest/#unauthenticated-rate-limited-requests for
more information.
*/
type UnauthenticatedRateLimitedTransport struct {
	// ClientID is the GitHub OAuth client ID of the current application, which
	// can be found by selecting its entry in the list at
	// https://github.com/settings/applications.
	ClientID string

	// ClientSecret is the GitHub OAuth client secret of the current
	// application.
	ClientSecret string

	// Transport is the underlying HTTP transport to use when making requests.
	// It will default to http.DefaultTransport if nil.
	Transport http.RoundTripper
}

// RoundTrip implements the RoundTripper interface.
func ( *UnauthenticatedRateLimitedTransport) ( *http.Request) (*http.Response, error) {
	if .ClientID == "" {
		return nil, errors.New("t.ClientID is empty")
	}
	if .ClientSecret == "" {
		return nil, errors.New("t.ClientSecret is empty")
	}

	 := setCredentialsAsHeaders(, .ClientID, .ClientSecret)
	// Make the HTTP request.
	return .transport().RoundTrip()
}

// Client returns an *http.Client that makes requests which are subject to the
// rate limit of your OAuth application.
func ( *UnauthenticatedRateLimitedTransport) () *http.Client {
	return &http.Client{Transport: }
}

func ( *UnauthenticatedRateLimitedTransport) () http.RoundTripper {
	if .Transport != nil {
		return .Transport
	}
	return http.DefaultTransport
}

// BasicAuthTransport is an http.RoundTripper that authenticates all requests
// using HTTP Basic Authentication with the provided username and password. It
// additionally supports users who have two-factor authentication enabled on
// their GitHub account.
type BasicAuthTransport struct {
	Username string // GitHub username
	Password string // GitHub password
	OTP      string // one-time password for users with two-factor auth enabled

	// Transport is the underlying HTTP transport to use when making requests.
	// It will default to http.DefaultTransport if nil.
	Transport http.RoundTripper
}

// RoundTrip implements the RoundTripper interface.
func ( *BasicAuthTransport) ( *http.Request) (*http.Response, error) {
	 := setCredentialsAsHeaders(, .Username, .Password)
	if .OTP != "" {
		.Header.Set(headerOTP, .OTP)
	}
	return .transport().RoundTrip()
}

// Client returns an *http.Client that makes requests that are authenticated
// using HTTP Basic Authentication.
func ( *BasicAuthTransport) () *http.Client {
	return &http.Client{Transport: }
}

func ( *BasicAuthTransport) () http.RoundTripper {
	if .Transport != nil {
		return .Transport
	}
	return http.DefaultTransport
}

// formatRateReset formats d to look like "[rate reset in 2s]" or
// "[rate reset in 87m02s]" for the positive durations. And like "[rate limit was reset 87m02s ago]"
// for the negative cases.
func formatRateReset( time.Duration) string {
	 :=  < 0
	if  {
		 *= -1
	}
	 := int(0.5 + .Seconds())
	 :=  / 60
	 :=  - *60

	var  string
	if  > 0 {
		 = fmt.Sprintf("%dm%02ds", , )
	} else {
		 = fmt.Sprintf("%ds", )
	}

	if  {
		return fmt.Sprintf("[rate limit was reset %v ago]", )
	}
	return fmt.Sprintf("[rate reset in %v]", )
}

func sleepUntilResetWithBuffer( context.Context,  time.Time) error {
	 := time.Second
	 := time.NewTimer(time.Until() + )
	select {
	case <-.Done():
		if !.Stop() {
			<-.C
		}
		return .Err()
	case <-.C:
	}
	return nil
}

// When using roundTripWithOptionalFollowRedirect, note that it
// is the responsibility of the caller to close the response body.
func ( *Client) ( context.Context,  string,  int,  ...RequestOption) (*http.Response, error) {
	,  := .NewRequest("GET", , nil, ...)
	if  != nil {
		return nil, 
	}

	var  *http.Response
	// Use http.DefaultTransport if no custom Transport is configured
	 = withContext(, )
	if .client.Transport == nil {
		,  = http.DefaultTransport.RoundTrip()
	} else {
		,  = .client.Transport.RoundTrip()
	}
	if  != nil {
		return nil, 
	}

	// If redirect response is returned, follow it
	if  > 0 && .StatusCode == http.StatusMovedPermanently {
		_ = .Body.Close()
		 = .Header.Get("Location")
		,  = .(, , -1, ...)
	}
	return , 
}

// Bool is a helper routine that allocates a new bool value
// to store v and returns a pointer to it.
func ( bool) *bool { return & }

// Int is a helper routine that allocates a new int value
// to store v and returns a pointer to it.
func ( int) *int { return & }

// Int64 is a helper routine that allocates a new int64 value
// to store v and returns a pointer to it.
func ( int64) *int64 { return & }

// String is a helper routine that allocates a new string value
// to store v and returns a pointer to it.
func ( string) *string { return & }

// roundTripperFunc creates a RoundTripper (transport)
type roundTripperFunc func(*http.Request) (*http.Response, error)

func ( roundTripperFunc) ( *http.Request) (*http.Response, error) {
	return ()
}