func stacks(all bool, max int) []byte {
	// We don't know how big the traces are, so grow a few times if they don't fit. Start large, though.
	n := initialMaxStackBufSize
	var trace []byte
	for n <= max {
		trace = make([]byte, n)
		nbytes := runtime.Stack(trace, all)
		if nbytes < len(trace) {
			return trace[:nbytes]
		}
		n *= 2
	}
	return trace
}

// stacks is a wrapper for runtime.Stack that attempts to recover the data for all goroutines.

stacks is a wrapper for runtime . Stack that attempts to recover the data for all goroutines .


func (l *Log) exit(err error) {
	fmt.Fprintf(os.Stderr, "log: exiting because of error: %s\n", err)
	// If logExitFunc is set, we do that instead of exiting.
	if logExitFunc != nil {
		logExitFunc(err)
		return
	}
	l.flushAll()
	os.Exit(2)
}

// exit is called if there is trouble creating or writing log files.
// It flushes the logs and exits the program; there's no point in hanging around.
// l.mu is held.

exit is called if there is trouble creating or writing log files . It flushes the logs and exits the program ; there s no point in hanging around . l . mu is held .


func (sb *syncBuffer) rotateFile(now time.Time) error {
	if sb.file != nil {
		sb.Flush()
		sb.file.Close()
	}
	var err error
	sb.file, _, err = sb.logger.create(severityName[sb.sev], now)
	sb.nbytes = 0
	if err != nil {
		return err
	}

	sb.Writer = bufio.NewWriterSize(sb.file, bufferSize)

	// Write header.
	var buf bytes.Buffer
	fmt.Fprintf(&buf, "Log file created at: %s\n", now.Format("2006/01/02 15:04:05"))
	fmt.Fprintf(&buf, "Running on machine: %s\n", host)
	fmt.Fprintf(&buf, "Binary: Built with %s %s for %s/%s\n", runtime.Compiler, runtime.Version(), runtime.GOOS, runtime.GOARCH)
	fmt.Fprintf(&buf, "Log line format: [IWEF]mmdd hh:mm:ss.uuuuuu threadid file:line] msg\n")
	n, err := sb.file.Write(buf.Bytes())
	sb.nbytes += uint64(n)
	return err
}

func
(
sb
*
syncBuffer
)
rotateFile
(
now
time
.
Time
)
error
{
if
sb
.
file
!=
{
sb
.
Flush
(
)
sb
.
file
.
Close
(
)
}
var
err
error
sb
.
file
,
_
,
err
=
sb
.
logger
.
create
(
severityName
[
sb
.
sev
]
,
now
)
sb
.
nbytes
=
0
if
err
!=
{
return
err
}
sb
.
Writer
=
bufio
.
NewWriterSize
(
sb
.
file
,
bufferSize
)
// Write header.
var
buf
bytes
.
Buffer
fmt
.
Fprintf
(
&
buf
,
"
\n
"
,
now
.
Format
(
"
"
)
)
fmt
.
Fprintf
(
&
buf
,
"
\n
"
,
host
)
fmt
.
Fprintf
(
&
buf
,
"
\n
"
,
runtime
.
Compiler
,
runtime
.
Version
(
)
,
runtime
.
GOOS
,
runtime
.
GOARCH
)
fmt
.
Fprintf
(
&
buf
,
"
\n
"
)
n
,
err
:=
sb
.
file
.
Write
(
buf
.
Bytes
(
)
)
sb
.
nbytes
+=
uint64
(
n
)
return
err
}

// rotateFile closes the syncBuffer's file and starts a new one.

rotateFile closes the syncBuffer s file and starts a new one .


func (l *Log) createFiles(sev Severity) error {
	now := time.Now()
	// Files are created in decreasing severity order, so as soon as we find one
	// has already been created, we can stop.
	for s := sev; s >= InfoLog && l.file[s] == nil; s-- {
		w, err := newFlushSyncWriter(l, s, now)
		if err != nil {
			return err
		}
		l.file[s] = w
	}
	return nil
}

// createFiles creates all the log files for severity from sev down to infoLog.
// l.mu is held.

createFiles creates all the log files for severity from sev down to infoLog . l . mu is held .


func (l *Log) flushDaemon() {
	for _ = range time.NewTicker(flushInterval).C {
		l.lockAndFlushAll()
	}
}

func ( l * Log ) flushDaemon ( ) { for _ = range time . NewTicker ( flushInterval ) . C { l . lockAndFlushAll ( ) } }

// flushDaemon periodically flushes the log file buffers.

flushDaemon periodically flushes the log file buffers .


func (l *Log) lockAndFlushAll() {
	l.mu.Lock()
	l.flushAll()
	l.mu.Unlock()
}

func ( l * Log ) lockAndFlushAll ( ) { l . mu . Lock ( ) l . flushAll ( ) l . mu . Unlock ( ) }

// lockAndFlushAll is like flushAll but locks l.mu first.

lockAndFlushAll is like flushAll but locks l . mu first .


func (l *Log) flushAll() {
	// Flush from fatal down, in case there's trouble flushing.
	for s := FatalLog; s >= InfoLog; s-- {
		file := l.file[s]
		if file != nil {
			file.Flush() // ignore error
			file.Sync()  // ignore error
		}
	}
}

// flushAll flushes all the logs and attempts to "sync" their data to disk.
// l.mu is held.

flushAll flushes all the logs and attempts to sync their data to disk . l . mu is held .


func (b *Bundle) Add(f func(context.Context) error) {
	b.waitGroup.Add(1)

	// Run the function in the background.
	go func() {
		defer b.waitGroup.Done()

		err := f(b.context)
		if err == nil {
			return
		}

		// On first error, cancel the context and save the error.
		b.errorOnce.Do(func() {
			b.firstError = err
			b.cancel()
		})
	}()
}

// Add a new operation to the bundle. The operation will be invoked with a
// context that will be cancelled if any other operation fails or has already
// failed.

Add a new operation to the bundle . The operation will be invoked with a context that will be cancelled if any other operation fails or has already failed .


func (b *Bundle) Join() error {
	b.waitGroup.Wait()

	// context.WithCancel requires that we arrange for this to be called
	// eventually in order to avoid leaking resources. Since everything is done,
	// to do so now is harmless.
	b.cancel()

	return b.firstError
}

// Wait for all previously-added operations to complete. Return nil if all
// operations succeeded. Otherwise return the first error.
//
// Add must not be called concurrently with or after Join.

Wait for all previously - added operations to complete . Return nil if all operations succeeded . Otherwise return the first error . Add must not be called concurrently with or after Join .


func NewBundle(parent context.Context) *Bundle {
	b := &Bundle{}
	b.context, b.cancel = context.WithCancel(parent)

	return b
}

func NewBundle ( parent context . Context ) * Bundle { b := & Bundle { } b . context , b . cancel = context . WithCancel ( parent ) return b }

// Create a bundle whose operations are fed a context inheriting from the given
// parent context, which must be non-nil. The bundle must eventually be joined
// with Join.

Create a bundle whose operations are fed a context inheriting from the given parent context which must be non - nil . The bundle must eventually be joined with Join .


func (tokens Tokens) Expand() (result Tokens, err error) {
	var updated bool
	for i := 0; i < len(tokens); i++ {
		var start int
		quote := Token{symbolToken, ":"}
		if *tokens[i] != quote {
			result = append(result, tokens[i])
		} else {
			updated = true
			for start = i + 1; *tokens[start] == quote; start++ {
				result = append(result, tokens[start])
			}
			if tokens[i+1].typ == openToken {
				if i, err = tokens.findClose(start + 1); err != nil {
					return nil, err
				}
			} else {
				i = start
			}
			result = append(result, &Token{openToken, "("}, &Token{symbolToken, "quote"})
			result = append(result, tokens[start:i+1]...)
			result = append(result, &Token{closeToken, ")"})
		}
	}
	if updated {
		result, err = result.Expand()
	}
	return
}

func ( tokens Tokens ) Expand ( ) ( result Tokens , err error ) { var updated bool for i := 0 ; i < len ( tokens ) ; i ++ { var start int quote := Token { symbolToken , " " } if * tokens [ i ] != quote { result = append ( result , tokens [ i ] ) } else { updated = true for start = i + 1 ; * tokens [ start ] == quote ; start ++ { result = append ( result , tokens [ start ] ) } if tokens [ i + 1 ] . typ == openToken { if i , err = tokens . findClose ( start + 1 ) ; err != nil { return nil , err } } else { i = start } result = append ( result , & Token { openToken , " " } , & Token { symbolToken , " " } ) result = append ( result , tokens [ start : i + 1 ] ... ) result = append ( result , & Token { closeToken , " " } ) } } if updated { result , err = result . Expand ( ) } return }

// Expand until there are no more expansions to do


func CacheFunc(bodyHandler func(http.ResponseWriter, *http.Request), expiration time.Duration) http.HandlerFunc {
	return Cache(http.HandlerFunc(bodyHandler), expiration).ServeHTTP
}

func CacheFunc ( bodyHandler func ( http . ResponseWriter , * http . Request ) , expiration time . Duration ) http . HandlerFunc { return Cache ( http . HandlerFunc ( bodyHandler ) , expiration ) . ServeHTTP }

// CacheFunc accepts two parameters
// first is the http.HandlerFunc which you want to cache its result
// the second is, optional, the cache Entry's expiration duration
// if the expiration <=2 seconds then expiration is taken by the "cache-control's maxage" header
// returns an http.HandlerFunc, which you can use as your default router or per-route handler
//
// All type of responses are cached, templates, json, text, anything.
//
// You CAN NOT add validators with this function

CacheFunc accepts two parameters first is the http . HandlerFunc which you want to cache its result the second is optional the cache Entry s expiration duration if the expiration < = 2 seconds then expiration is taken by the cache - control s maxage header returns an http . HandlerFunc which you can use as your default router or per - route handler All type of responses are cached templates json text anything . You CAN NOT add validators with this function


func CacheFasthttp(bodyHandler fasthttp.RequestHandler, expiration time.Duration) *fhttp.Handler {
	return fhttp.NewHandler(bodyHandler, expiration)
}

func CacheFasthttp ( bodyHandler fasthttp . RequestHandler , expiration time . Duration ) * fhttp . Handler { return fhttp . NewHandler ( bodyHandler , expiration ) }

// CacheFasthttp accepts two parameters
// first is the fasthttp.RequestHandler which you want to cache its result
// the second is, optional, the cache Entry's expiration duration
// if the expiration <=2 seconds then expiration is taken by the "cache-control's maxage" header
// returns a fhttp.Handler with a ServeHTTP which is the fasthttp.RequestHandler,
// which you can use as your default router or per-route handler
//
// All type of responses are cached, templates, json, text, anything.
//
// You can add validators with this function

CacheFasthttp accepts two parameters first is the fasthttp . RequestHandler which you want to cache its result the second is optional the cache Entry s expiration duration if the expiration < = 2 seconds then expiration is taken by the cache - control s maxage header returns a fhttp . Handler with a ServeHTTP which is the fasthttp . RequestHandler which you can use as your default router or per - route handler All type of responses are cached templates json text anything . You can add validators with this function


func CacheFasthttpFunc(bodyHandler fasthttp.RequestHandler, expiration time.Duration) fasthttp.RequestHandler {
	return CacheFasthttp(bodyHandler, expiration).ServeHTTP
}

func CacheFasthttpFunc ( bodyHandler fasthttp . RequestHandler , expiration time . Duration ) fasthttp . RequestHandler { return CacheFasthttp ( bodyHandler , expiration ) . ServeHTTP }

// CacheFasthttpFunc accepts two parameters
// first is the fasthttp.RequestHandler which you want to cache its result
// the second is, optional, the cache Entry's expiration duration
// if the expiration <=2 seconds then expiration is taken by the "cache-control's maxage" header
// returns a fasthttp.RequestHandler, which you can use as your default router or per-route handler
//
// All type of responses are cached, templates, json, text, anything.
//
// You CAN NOT add validators with this function

CacheFasthttpFunc accepts two parameters first is the fasthttp . RequestHandler which you want to cache its result the second is optional the cache Entry s expiration duration if the expiration < = 2 seconds then expiration is taken by the cache - control s maxage header returns a fasthttp . RequestHandler which you can use as your default router or per - route handler All type of responses are cached templates json text anything . You CAN NOT add validators with this function


func (r *Response) ContentType() string {
	if r.contentType == "" {
		r.contentType = "text/html; charset=utf-8"
	}
	return r.contentType
}

func ( r * Response ) ContentType ( ) string { if r . contentType == " " { r . contentType = " " } return r . contentType }

// ContentType returns a valid content type


func (s *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	// println("Request to the remote service has been established")
	key := getURLParam(r, cfg.QueryCacheKey)
	if key == "" {
		// println("return because key was empty")
		w.WriteHeader(cfg.FailStatus)
		return
	}

	// we always need the Entry, so get it now
	entry := s.store.Get(key)

	if entry == nil && r.Method != methodPost {
		// if it's nil then means it never setted before
		// it doesn't exists, and client doesn't wants to
		// add a cache entry, so just return
		//
		// no delete action is valid
		// no get action is valid
		// no post action is requested
		w.WriteHeader(cfg.FailStatus)
		return
	}

	switch r.Method {
	case methodGet:
		{
			// get from the cache and send to client
			res, ok := entry.Response()
			if !ok {
				// entry exists but it has been expired
				// return
				w.WriteHeader(cfg.FailStatus)
				return
			}

			// entry exists and response is valid
			// send it to the client
			w.Header().Set(cfg.ContentTypeHeader, res.ContentType())
			w.WriteHeader(res.StatusCode())
			w.Write(res.Body())
		}
	case methodPost:
		{
			// save a new cache entry if entry ==nil or
			// update an existing if entry !=nil

			body, err := ioutil.ReadAll(r.Body)
			if err != nil || len(body) == 0 {
				// println("body's request was empty, return fail")
				w.WriteHeader(cfg.FailStatus)
				return
			}

			statusCode, _ := getURLParamInt(r, cfg.QueryCacheStatusCode)
			contentType := getURLParam(r, cfg.QueryCacheContentType)

			// now that we have the information
			// we want to see if this is a totally new cache entry
			// or just update an existing one with the new information
			// (an update can change the status code, content type
			//     and ofcourse the body and expiration time by header)

			if entry == nil {
				// get the information by its url
				// println("we have a post request method, let's save a cached entry ")
				// get the cache expiration via url param
				expirationSeconds, err := getURLParamInt64(r, cfg.QueryCacheDuration)
				// get the body from the requested body
				// get the expiration from the "cache-control's maxage" if no url param is setted
				if expirationSeconds <= 0 || err != nil {
					expirationSeconds = int64(nethttp.GetMaxAge(r)().Seconds())
				}
				// if not setted then try to get it via
				if expirationSeconds <= 0 {
					expirationSeconds = int64(cfg.MinimumCacheDuration.Seconds())
				}

				cacheDuration := time.Duration(expirationSeconds) * time.Second

				// store by its url+the key in order to be unique key among different servers with the same paths
				s.store.Set(key, statusCode, contentType, body, cacheDuration)
			} else {
				// update an existing one and change its duration  based on the header
				// (if > existing duration)
				entry.Reset(statusCode, contentType, body, nethttp.GetMaxAge(r))
			}

			w.WriteHeader(cfg.SuccessStatus)
		}
	case methodDelete:
		{
			// remove the entry entirely from the cache
			// manually DELETE cache should remove this entirely
			// no just invalidate it
			s.store.Remove(key)
			w.WriteHeader(cfg.SuccessStatus)
		}
	default:
		w.WriteHeader(cfg.FailStatus)
	}

}

// ServeHTTP serves the cache Service to the outside world,
// it is used only when you want to achieve something like horizontal scaling
// it parses the request and tries to return the response with the cached body of the requested cache key
// server-side function

ServeHTTP serves the cache Service to the outside world it is used only when you want to achieve something like horizontal scaling it parses the request and tries to return the response with the cached body of the requested cache key server - side function


func New(addr string, store Store) *http.Server {
	if store == nil {
		store = NewMemoryStore()
	}
	h := &Handler{store: store}
	return &http.Server{
		Addr:    addr,
		Handler: h,
	}
}

func New ( addr string , store Store ) * http . Server { if store == nil { store = NewMemoryStore ( ) } h := & Handler { store : store } return & http . Server { Addr : addr , Handler : h , } }

// the actual work is done on the handler.go
// here we just provide a helper for the main package to create
// an http.Server and serve a cache remote service, without any user touches
// New returns a http.Server which hosts
// the server-side handler for the remote cache service.
//
// it doesn't listens to the server

the actual work is done on the handler . go here we just provide a helper for the main package to create an http . Server and serve a cache remote service without any user touches New returns a http . Server which hosts the server - side handler for the remote cache service . it doesn t listens to the server


func AcquireResponseRecorder(underline http.ResponseWriter) *ResponseRecorder {
	v := rpool.Get()
	var res *ResponseRecorder
	if v != nil {
		res = v.(*ResponseRecorder)
	} else {
		res = &ResponseRecorder{}
	}
	res.underline = underline
	return res
}

func AcquireResponseRecorder ( underline http . ResponseWriter ) * ResponseRecorder { v := rpool . Get ( ) var res * ResponseRecorder if v != nil { res = v . ( * ResponseRecorder ) } else { res = & ResponseRecorder { } } res . underline = underline return res }

// AcquireResponseRecorder returns a ResponseRecorder


func ReleaseResponseRecorder(res *ResponseRecorder) {
	res.underline = nil
	res.statusCode = 0
	res.chunks = res.chunks[0:0]
	rpool.Put(res)
}

func ReleaseResponseRecorder ( res * ResponseRecorder ) { res . underline = nil res . statusCode = 0 res . chunks = res . chunks [ 0 : 0 ] rpool . Put ( res ) }

// ReleaseResponseRecorder releases a ResponseRecorder which has been previously received by AcquireResponseRecorder


func (v *validatorRule) Claim(r *http.Request) bool {
	// check for pre-cache validators, if at least one of them return false
	// for this specific request, then skip the whole cache
	for _, shouldProcess := range v.preValidators {
		if !shouldProcess(r) {
			return false
		}
	}
	return true
}

// Claim returns true if incoming request can claim for a cached handler
// the original handler should run as it is and exit

Claim returns true if incoming request can claim for a cached handler the original handler should run as it is and exit


func (h *Handler) Rule(r rule.Rule) *Handler {
	if r == nil {
		// if nothing passed then use the allow-everyting rule
		r = rule.Satisfied()
	}
	h.rule = r

	return h
}

// Rule sets the ruleset for this handler.
//
// returns itself.

Rule sets the ruleset for this handler . returns itself .


func (e *Entry) Reset(statusCode int, contentType string,
	body []byte, lifeChanger LifeChanger) {

	if e.response == nil {
		e.response = &Response{}
	}
	if statusCode > 0 {
		e.response.statusCode = statusCode
	}

	if contentType != "" {
		e.response.contentType = contentType
	}

	e.response.body = body
	// check if a given life changer provided
	// and if it does then execute the change life time
	if lifeChanger != nil {
		e.ChangeLifetime(lifeChanger)
	}
	e.expiresAt = time.Now().Add(e.life)
}

// Reset called each time the entry is expired
// and the handler calls this after the original handler executed
// to re-set the response with the new handler's content result

Reset called each time the entry is expired and the handler calls this after the original handler executed to re - set the response with the new handler s content result


func NoCache(reqCtx *fasthttp.RequestCtx) {
	reqCtx.Response.Header.Set(cfg.NoCacheHeader, "true")
}

func NoCache ( reqCtx * fasthttp . RequestCtx ) { reqCtx . Response . Header . Set ( cfg . NoCacheHeader , " " ) }

// NoCache called when a particular handler is not valid for cache.
// If this function called inside a handler then the handler is not cached.

NoCache called when a particular handler is not valid for cache . If this function called inside a handler then the handler is not cached .


func clientOAuth(tokens *oauthTokens) *clientOAuthAuthentication {
	a := clientOAuthAuthentication{
		Tokens:  tokens,
		BaseUrl: config.BaseUrl,
		Client: http.Client{
			Transport: &http.Transport{
				Dial: dialTimeout,
			},
		},
	}
	return &a
}

func clientOAuth ( tokens * oauthTokens ) * clientOAuthAuthentication { a := clientOAuthAuthentication { Tokens : tokens , BaseUrl : config . BaseUrl , Client : http . Client { Transport : & http . Transport { Dial : dialTimeout , } , } , } return & a }

// ClientOAuth instantiates ClientOAuthAuthentication with the client OAuth tokens


func (a clientOAuthAuthentication) authenticate(req *http.Request, endpoint string, params []byte) error {
	// Ensure tokens havent expired
	if time.Now().UTC().Unix() > a.Tokens.ExpireTime {
		return errors.New("The OAuth tokens are expired. Use refreshTokens to refresh them")
	}
	req.Header.Set("Authorization", "Bearer "+a.Tokens.AccessToken)
	return nil
}

func
(
a
clientOAuthAuthentication
)
authenticate
(
req
*
http
.
Request
,
endpoint
string
,
params
[
]
byte
)
error
{
// Ensure tokens havent expired
if
time
.
Now
(
)
.
UTC
(
)
.
Unix
(
)
>
a
.
Tokens
.
ExpireTime
{
return
errors
.
New
(
"
"
)
}
req
.
Header
.
Set
(
"
"
,
"
"
+
a
.
Tokens
.
AccessToken
)
return
}

// Client OAuth authentication requires us to attach an unexpired OAuth token to
// the request header

Client OAuth authentication requires us to attach an unexpired OAuth token to the request header


func apiKeyAuth(key string, secret string) *apiKeyAuthentication {
	a := apiKeyAuthentication{
		Key:     key,
		Secret:  secret,
		BaseUrl: config.BaseUrl,
		Client: http.Client{
			Transport: &http.Transport{
				Dial: dialTimeout,
			},
		},
	}
	return &a
}

func apiKeyAuth ( key string , secret string ) * apiKeyAuthentication { a := apiKeyAuthentication { Key : key , Secret : secret , BaseUrl : config . BaseUrl , Client : http . Client { Transport : & http . Transport { Dial : dialTimeout , } , } , } return & a }

// ApiKeyAuth instantiates ApiKeyAuthentication with the API key & secret


func (a apiKeyAuthentication) authenticate(req *http.Request, endpoint string, params []byte) error {

	nonce := strconv.FormatInt(time.Now().UTC().UnixNano(), 10)
	message := nonce + endpoint + string(params) //As per Coinbase Documentation

	req.Header.Set("ACCESS_KEY", a.Key)

	h := hmac.New(sha256.New, []byte(a.Secret))
	h.Write([]byte(message))

	signature := hex.EncodeToString(h.Sum(nil))

	req.Header.Set("ACCESS_SIGNATURE", signature)
	req.Header.Set("ACCESS_NONCE", nonce)

	return nil
}

func
(
a
apiKeyAuthentication
)
authenticate
(
req
*
http
.
Request
,
endpoint
string
,
params
[
]
byte
)
error
{
nonce
:=
strconv
.
FormatInt
(
time
.
Now
(
)
.
UTC
(
)
.
UnixNano
(
)
,
10
)
message
:=
nonce
+
endpoint
+
string
(
params
)
//As per Coinbase Documentation
req
.
Header
.
Set
(
"
"
,
a
.
Key
)
h
:=
hmac
.
New
(
sha256
.
New
,
[
]
byte
(
a
.
Secret
)
)
h
.
Write
(
[
]
byte
(
message
)
)
signature
:=
hex
.
EncodeToString
(
h
.
Sum
(
)
)
req
.
Header
.
Set
(
"
"
,
signature
)
req
.
Header
.
Set
(
"
"
,
nonce
)
return
}

// API Key + Secret authentication requires a request header of the HMAC SHA-256
// signature of the "message" as well as an incrementing nonce and the API key

API Key + Secret authentication requires a request header of the HMAC SHA - 256 signature of the message as well as an incrementing nonce and the API key


func serviceOAuth(certFilePath string) (*serviceOAuthAuthentication, error) {
	// First we read the cert
	certs := x509.NewCertPool()
	pemData, err := ioutil.ReadFile(certFilePath)
	if err != nil {
		return nil, err
	}
	certs.AppendCertsFromPEM(pemData)
	mTLSConfig := &tls.Config{
		RootCAs: certs, //Add the cert as a TLS config
	}
	a := serviceOAuthAuthentication{
		BaseUrl: "https://coinbase.com/",
		Client: http.Client{
			Transport: &http.Transport{
				Dial:            dialTimeout,
				TLSClientConfig: mTLSConfig,
			},
		},
	}
	return &a, nil
}

func
serviceOAuth
(
certFilePath
string
)
(
*
serviceOAuthAuthentication
,
error
)
{
// First we read the cert
certs
:=
x509
.
NewCertPool
(
)
pemData
,
err
:=
ioutil
.
ReadFile
(
certFilePath
)
if
err
!=
{
return
,
err
}
certs
.
AppendCertsFromPEM
(
pemData
)
mTLSConfig
:=
&
tls
.
Config
{
RootCAs
:
certs
,
//Add the cert as a TLS config
}
a
:=
serviceOAuthAuthentication
{
BaseUrl
:
"
"
,
Client
:
http
.
Client
{
Transport
:
&
http
.
Transport
{
Dial
:
dialTimeout
,
TLSClientConfig
:
mTLSConfig
,
}
,
}
,
}
return
&
a
,
}

// ServiceOAuth instantiates ServiceOAuthAuthentication with the coinbase certificate file


func (a serviceOAuthAuthentication) authenticate(req *http.Request, endpoint string, params []byte) error {
	return nil // No additional headers needed for service OAuth requests
}

// Service OAuth authentication requires no additional headers to be sent. The
// Coinbase Public Certificate is set as a TLS config in the http.Client

Service OAuth authentication requires no additional headers to be sent . The Coinbase Public Certificate is set as a TLS config in the http . Client


func OAuthService(clientId string, clientSecret string, redirectUri string) (*OAuth, error) {
	certFilePath := basePath + "/ca-coinbase.crt"
	serviceAuth, err := serviceOAuth(certFilePath)
	if err != nil {
		return nil, err
	}
	o := OAuth{
		ClientId:     clientId,
		ClientSecret: clientSecret,
		RedirectUri:  redirectUri,
		Rpc: rpc{
			auth: serviceAuth,
			mock: false,
		},
	}
	return &o, nil
}

func OAuthService ( clientId string , clientSecret string , redirectUri string ) ( * OAuth , error ) { certFilePath := basePath + " " serviceAuth , err := serviceOAuth ( certFilePath ) if err != nil { return nil , err } o := OAuth { ClientId : clientId , ClientSecret : clientSecret , RedirectUri : redirectUri , Rpc : rpc { auth : serviceAuth , mock : false , } , } return & o , nil }

// OAuthService Instantiates OAuth Struct in order to send service related OAuth requests


func (o OAuth) CreateAuthorizeUrl(scope []string) string {
	Url, _ := url.Parse("https://coinbase.com")
	Url.Path += "/oauth/authorize"

	parameters := url.Values{}
	parameters.Add("response_type", "code")
	parameters.Add("client_id", o.ClientId)
	parameters.Add("redirect_uri", o.RedirectUri)
	parameters.Add("scope", strings.Join(scope, " "))
	Url.RawQuery = parameters.Encode()

	return Url.String()
}

func ( o OAuth ) CreateAuthorizeUrl ( scope [ ] string ) string { Url , _ := url . Parse ( " " ) Url . Path += " " parameters := url . Values { } parameters . Add ( " " , " " ) parameters . Add ( " " , o . ClientId ) parameters . Add ( " " , o . RedirectUri ) parameters . Add ( " " , strings . Join ( scope , " " ) ) Url . RawQuery = parameters . Encode ( ) return Url . String ( ) }

// CreateAuthorizeUrl create the Authorize Url used to redirect users for
// coinbase app authorization. The scope parameter includes the specific
// permissions one wants to ask from the user

CreateAuthorizeUrl create the Authorize Url used to redirect users for coinbase app authorization . The scope parameter includes the specific permissions one wants to ask from the user


func (o OAuth) RefreshTokens(oldTokens map[string]interface{}) (*oauthTokens, error) {
	refresh_token := oldTokens["refresh_token"].(string)
	return o.GetTokens(refresh_token, "refresh_token")
}

func ( o OAuth ) RefreshTokens ( oldTokens map [ string ] interface { } ) ( * oauthTokens , error ) { refresh_token := oldTokens [ " " ] . ( string ) return o . GetTokens ( refresh_token , " " ) }

// RefreshTokens refreshes a users existing OAuth tokens


func (o OAuth) NewTokens(code string) (*oauthTokens, error) {
	return o.GetTokens(code, "authorization_code")
}

func ( o OAuth ) NewTokens ( code string ) ( * oauthTokens , error ) { return o . GetTokens ( code , " " ) }

// NewTokens generates new tokens for an OAuth user


func (o OAuth) NewTokensFromRequest(req *http.Request) (*oauthTokens, error) {
	query := req.URL.Query()
	code := query.Get("code")
	return o.GetTokens(code, "authorization_code")
}

func ( o OAuth ) NewTokensFromRequest ( req * http . Request ) ( * oauthTokens , error ) { query := req . URL . Query ( ) code := query . Get ( " " ) return o . GetTokens ( code , " " ) }

// NewTokensRequest generates new tokens for OAuth user given an http request
// containing the query parameter 'code'

NewTokensRequest generates new tokens for OAuth user given an http request containing the query parameter code


func (r rpc) Request(method string, endpoint string, params interface{}, holder interface{}) error {

	jsonParams, err := json.Marshal(params)
	if err != nil {
		return err
	}

	request, err := r.createRequest(method, endpoint, jsonParams)
	if err != nil {
		return err
	}

	var data []byte
	if r.mock == true { // Mock mode: Replace actual request with expected JSON from file
		data, err = r.simulateRequest(endpoint, method)
	} else {
		data, err = r.executeRequest(request)
	}
	if err != nil {
		return err
	}
	if err := json.Unmarshal(data, &holder); err != nil {
		return err
	}

	return nil
}

// Request sends a request with params marshaled into a JSON payload in the body
// The response value is marshaled from JSON into the specified holder struct

Request sends a request with params marshaled into a JSON payload in the body The response value is marshaled from JSON into the specified holder struct


func (r rpc) createRequest(method string, endpoint string, params []byte) (*http.Request, error) {

	endpoint = r.auth.getBaseUrl() + endpoint //BaseUrl depends on Auth type used

	req, err := http.NewRequest(method, endpoint, bytes.NewBuffer(params))
	if err != nil {
		return nil, err
	}

	// Authenticate the request
	r.auth.authenticate(req, endpoint, params)

	req.Header.Set("User-Agent", "CoinbaseGo/v1")
	req.Header.Set("Content-Type", "application/json")

	return req, nil
}

func
(
r
rpc
)
createRequest
(
method
string
,
endpoint
string
,
params
[
]
byte
)
(
*
http
.
Request
,
error
)
{
endpoint
=
r
.
auth
.
getBaseUrl
(
)
+
endpoint
//BaseUrl depends on Auth type used
req
,
err
:=
http
.
NewRequest
(
method
,
endpoint
,
bytes
.
NewBuffer
(
params
)
)
if
err
!=
{
return
,
err
}
// Authenticate the request
r
.
auth
.
authenticate
(
req
,
endpoint
,
params
)
req
.
Header
.
Set
(
"
"
,
"
"
)
req
.
Header
.
Set
(
"
"
,
"
"
)
return
req
,
}

// CreateRequest formats a request with all the necessary headers


func (r rpc) executeRequest(req *http.Request) ([]byte, error) {
	resp, err := r.auth.getClient().Do(req)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()
	buf := new(bytes.Buffer)
	buf.ReadFrom(resp.Body)
	bytes := buf.Bytes()
	if resp.StatusCode != 200 {
		if len(bytes) == 0 { // Log response body for debugging purposes
			log.Printf("Response body was empty")
		} else {
			log.Printf("Response body:\n\t%s\n", bytes)
		}
		return nil, fmt.Errorf("%s %s failed. Response code was %s", req.Method, req.URL, resp.Status)
	}
	return bytes, nil
}

// executeRequest takes a prepared http.Request and returns the body of the response
// If the response is not of HTTP Code 200, an error is returned

executeRequest takes a prepared http . Request and returns the body of the response If the response is not of HTTP Code 200 an error is returned


func (r rpc) simulateRequest(endpoint string, method string) ([]byte, error) {
	// Test files conform to replacing '/' in endpoint with '_'
	fileName := strings.Replace(endpoint, "/", "_", -1)
	// file names also have method type prepended to ensure uniqueness
	filePath := basePath + "/test_data/" + method + "_" + fileName + ".json"
	data, err := ioutil.ReadFile(filePath)
	if err != nil {
		return nil, err
	}
	return data, nil
}

// simulateRequest simulates a request by returning a sample JSON from file


func ApiKeyClient(key string, secret string) Client {
	c := Client{
		rpc: rpc{
			auth: apiKeyAuth(key, secret),
			mock: false,
		},
	}
	return c
}

func ApiKeyClient ( key string , secret string ) Client { c := Client { rpc : rpc { auth : apiKeyAuth ( key , secret ) , mock : false , } , } return c }

// ApiKeyClient instantiates the client with ApiKey Authentication


func OAuthClient(tokens *oauthTokens) Client {
	c := Client{
		rpc: rpc{
			auth: clientOAuth(tokens),
			mock: false,
		},
	}
	return c
}

func OAuthClient ( tokens * oauthTokens ) Client { c := Client { rpc : rpc { auth : clientOAuth ( tokens ) , mock : false , } , } return c }

// OAuthClient instantiates the client with OAuth Authentication


func (c Client) Get(path string, params interface{}, holder interface{}) error {
	return c.rpc.Request("GET", path, params, &holder)
}

func ( c Client ) Get ( path string , params interface { } , holder interface { } ) error { return c . rpc . Request ( " " , path , params , & holder ) }

// Get sends a GET request and marshals response data into holder


func (c Client) GetBalance() (float64, error) {
	balance := map[string]string{}
	if err := c.Get("account/balance", nil, &balance); err != nil {
		return 0.0, err
	}
	balanceFloat, err := strconv.ParseFloat(balance["amount"], 64)
	if err != nil {
		return 0, err
	}
	return balanceFloat, nil
}

func ( c Client ) GetBalance ( ) ( float64 , error ) { balance := map [ string ] string { } if err := c . Get ( " " , nil , & balance ) ; err != nil { return 0.0 , err } balanceFloat , err := strconv . ParseFloat ( balance [ " " ] , 64 ) if err != nil { return 0 , err } return balanceFloat , nil }

// GetBalance returns current balance in BTC


func (c Client) GetAllAddresses(params *AddressesParams) (*addresses, error) {
	holder := addressesHolder{}
	if err := c.Get("addresses", params, &holder); err != nil {
		return nil, err
	}
	addresses := addresses{
		paginationStats: holder.paginationStats,
	}
	// Remove one layer of nesting
	for _, addr := range holder.Addresses {
		addresses.Addresses = append(addresses.Addresses, addr.Address)
	}
	return &addresses, nil
}

func
(
c
Client
)
GetAllAddresses
(
params
*
AddressesParams
)
(
*
addresses
,
error
)
{
holder
:=
addressesHolder
{
}
if
err
:=
c
.
Get
(
"
"
,
params
,
&
holder
)
;
err
!=
{
return
,
err
}
addresses
:=
addresses
{
paginationStats
:
holder
.
paginationStats
,
}
// Remove one layer of nesting
for
_
,
addr
:=
range
holder
.
Addresses
{
addresses
.
Addresses
=
append
(
addresses
.
Addresses
,
addr
.
Address
)
}
return
&
addresses
,
}

// GetAllAddresses returns bitcoin addresses associated with client account


func (c Client) GenerateReceiveAddress(params *AddressParams) (string, error) {
	holder := map[string]interface{}{}
	if err := c.Post("account/generate_receive_address", params, &holder); err != nil {
		return "", err
	}
	return holder["address"].(string), nil
}

func ( c Client ) GenerateReceiveAddress ( params * AddressParams ) ( string , error ) { holder := map [ string ] interface { } { } if err := c . Post ( " " , params , & holder ) ; err != nil { return " " , err } return holder [ " " ] . ( string ) , nil }

// GenerateReceiveAddress generates and returns a new bitcoin receive address


func (c Client) SendMoney(params *TransactionParams) (*transactionConfirmation, error) {
	return c.transactionRequest("POST", "send_money", params)
}

func ( c Client ) SendMoney ( params * TransactionParams ) ( * transactionConfirmation , error ) { return c . transactionRequest ( " " , " " , params ) }

// SendMoney to either a bitcoin or email address


func (c Client) RequestMoney(params *TransactionParams) (*transactionConfirmation, error) {
	return c.transactionRequest("POST", "request_money", params)
}

func ( c Client ) RequestMoney ( params * TransactionParams ) ( * transactionConfirmation , error ) { return c . transactionRequest ( " " , " " , params ) }

// RequestMoney from either a bitcoin or email address


func (c Client) ResendRequest(id string) (bool, error) {
	holder := map[string]interface{}{}
	if err := c.Put("transactions/"+id+"/resend_request", nil, &holder); err != nil {
		return false, err
	}
	if holder["success"].(bool) {
		return true, nil
	}
	return false, nil
}

func ( c Client ) ResendRequest ( id string ) ( bool , error ) { holder := map [ string ] interface { } { } if err := c . Put ( " " + id + " " , nil , & holder ) ; err != nil { return false , err } if holder [ " " ] . ( bool ) { return true , nil } return false , nil }

// ResendRequest resends a transaction request referenced by id


func (c Client) CancelRequest(id string) (bool, error) {
	holder := map[string]interface{}{}
	if err := c.Delete("transactions/"+id+"/cancel_request", nil, &holder); err != nil {
		return false, err
	}
	if holder["success"].(bool) {
		return true, nil
	}
	return false, nil
}

func ( c Client ) CancelRequest ( id string ) ( bool , error ) { holder := map [ string ] interface { } { } if err := c . Delete ( " " + id + " " , nil , & holder ) ; err != nil { return false , err } if holder [ " " ] . ( bool ) { return true , nil } return false , nil }

// CancelRequest cancels a transaction request referenced by id


func (c Client) CompleteRequest(id string) (*transactionConfirmation, error) {
	return c.transactionRequest("PUT", id+"/complete_request", nil)
}

func ( c Client ) CompleteRequest ( id string ) ( * transactionConfirmation , error ) { return c . transactionRequest ( " " , id + " " , nil ) }

// CompleteRequest completes a money request referenced by id


func (c Client) CreateButton(params *Button) (*Button, error) {
	finalParams := &struct {
		Button *Button `json:"button"`
	}{
		Button: params,
	}
	holder := buttonHolder{}
	if err := c.Post("buttons", finalParams, &holder); err != nil {
		return nil, err
	}
	if err := checkApiErrors(holder.response, "CreateButton"); err != nil {
		return nil, err
	}
	button := holder.Button
	button.EmbedHtml = "

"
	return &button, nil
}

func ( c Client ) CreateButton ( params * Button ) ( * Button , error ) { finalParams := & struct { Button * Button `json:"button"` } { Button : params , } holder := buttonHolder { } if err := c . Post ( " " , finalParams , & holder ) ; err != nil { return nil , err } if err := checkApiErrors ( holder . response , " " ) ; err != nil { return nil , err } button := holder . Button button . EmbedHtml = " \" \" \" " + button . Code + " \" \" \" \" \" " return & button , nil }

// CreateButton gets a new payment button including EmbedHtml as a field on button struct


func (c Client) CreateOrderFromButtonCode(buttonCode string) (*order, error) {
	holder := orderHolder{}
	if err := c.Post("buttons/"+buttonCode+"/create_order", nil, &holder); err != nil {
		return nil, err
	}
	if err := checkApiErrors(holder.response, "CreateOrderFromButtonCode"); err != nil {
		return nil, err
	}
	return &holder.Order, nil
}

func ( c Client ) CreateOrderFromButtonCode ( buttonCode string ) ( * order , error ) { holder := orderHolder { } if err := c . Post ( " " + buttonCode + " " , nil , & holder ) ; err != nil { return nil , err } if err := checkApiErrors ( holder . response , " " ) ; err != nil { return nil , err } return & holder . Order , nil }

// CreateOrderFromButtonCode creates an order for a given button code


func (c Client) CreateUser(email string, password string) (*user, error) {
	params := map[string]interface{}{
		"user[email]":    email,
		"user[password]": password,
	}
	holder := userHolder{}
	if err := c.Post("users", params, &holder); err != nil {
		return nil, err
	}
	if err := checkApiErrors(holder.response, "CreateUser"); err != nil {
		return nil, err
	}
	return &holder.User, nil
}

func ( c Client ) CreateUser ( email string , password string ) ( * user , error ) { params := map [ string ] interface { } { " " : email , " " : password , } holder := userHolder { } if err := c . Post ( " " , params , & holder ) ; err != nil { return nil , err } if err := checkApiErrors ( holder . response , " " ) ; err != nil { return nil , err } return & holder . User , nil }

// CreateUser creates a new user given an email and password


func (c Client) Buy(amount float64, agreeBtcAmountVaries bool) (*transfer, error) {
	params := map[string]interface{}{
		"qty": amount,
		"agree_btc_amount_varies": agreeBtcAmountVaries,
	}
	holder := transferHolder{}
	if err := c.Post("buys", params, &holder); err != nil {
		return nil, err
	}
	if err := checkApiErrors(holder.response, "Buy"); err != nil {
		return nil, err
	}
	return &holder.Transfer, nil
}

func ( c Client ) Buy ( amount float64 , agreeBtcAmountVaries bool ) ( * transfer , error ) { params := map [ string ] interface { } { " " : amount , " " : agreeBtcAmountVaries , } holder := transferHolder { } if err := c . Post ( " " , params , & holder ) ; err != nil { return nil , err } if err := checkApiErrors ( holder . response , " " ) ; err != nil { return nil , err } return & holder . Transfer , nil }

// Buy an amount of BTC and bypass rate limits by setting agreeBtcAmountVaries to true


func (c Client) GetContacts(params *ContactsParams) (*contactsHolder, error) {
	holder := contactsHolder{}
	if err := c.Get("contacts", params, &holder); err != nil {
		return nil, err
	}
	for _, contact := range holder.Contacts {
		if contact.Contact.Email != "" {
			holder.Emails = append(holder.Emails, contact.Contact.Email)
		}
	}
	return &holder, nil
}

func ( c Client ) GetContacts ( params * ContactsParams ) ( * contactsHolder , error ) { holder := contactsHolder { } if err := c . Get ( " " , params , & holder ) ; err != nil { return nil , err } for _ , contact := range holder . Contacts { if contact . Contact . Email != " " { holder . Emails = append ( holder . Emails , contact . Contact . Email ) } } return & holder , nil }


func (c Client) GetCurrencies() ([]currency, error) {
	holder := [][]string{}
	if err := c.Get("currencies", nil, &holder); err != nil {
		return nil, err
	}
	finalData := []currency{}
	for _, curr := range holder {
		class := currency{
			Name: curr[0],
			Iso:  curr[1],
		}
		finalData = append(finalData, class)
	}
	return finalData, nil
}

func ( c Client ) GetCurrencies ( ) ( [ ] currency , error ) { holder := [ ] [ ] string { } if err := c . Get ( " " , nil , & holder ) ; err != nil { return nil , err } finalData := [ ] currency { } for _ , curr := range holder { class := currency { Name : curr [ 0 ] , Iso : curr [ 1 ] , } finalData = append ( finalData , class ) } return finalData , nil }

// GetCurrencies gets all currency names and ISO's

GetCurrencies gets all currency names and ISO s


func (c Client) GetExchangeRates() (map[string]string, error) {
	holder := map[string]string{}
	if err := c.Get("currencies/exchange_rates", nil, &holder); err != nil {
		return nil, err
	}
	return holder, nil
}

func ( c Client ) GetExchangeRates ( ) ( map [ string ] string , error ) { holder := map [ string ] string { } if err := c . Get ( " " , nil , & holder ) ; err != nil { return nil , err } return holder , nil }

// GetExchangeRates gets the current exchange rates


func (c Client) GetExchangeRate(from string, to string) (float64, error) {
	exchanges, err := c.GetExchangeRates()
	if err != nil {
		return 0.0, err
	}
	key := from + "_to_" + to
	if exchanges[key] == "" {
		return 0.0, errors.New("The exchange rate does not exist for this currency pair")
	}
	exchangeFloat, err := strconv.ParseFloat(exchanges[key], 64)
	if err != nil {
		return 0.0, err
	}
	return exchangeFloat, nil
}

func ( c Client ) GetExchangeRate ( from string , to string ) ( float64 , error ) { exchanges , err := c . GetExchangeRates ( ) if err != nil { return 0.0 , err } key := from + " " + to if exchanges [ key ] == " " { return 0.0 , errors . New ( " " ) } exchangeFloat , err := strconv . ParseFloat ( exchanges [ key ] , 64 ) if err != nil { return 0.0 , err } return exchangeFloat , nil }

// GetExchangeRate gets the exchange rate between two specified currencies


func (c Client) GetTransactions(page int) (*transactions, error) {
	params := map[string]int{
		"page": page,
	}
	holder := transactionsHolder{}
	if err := c.Get("transactions", params, &holder); err != nil {
		return nil, err
	}
	transactions := transactions{
		paginationStats: holder.paginationStats,
	}
	// Remove one layer of nesting
	for _, tx := range holder.Transactions {
		transactions.Transactions = append(transactions.Transactions, tx.Transaction)
	}
	return &transactions, nil
}

func
(
c
Client
)
GetTransactions
(
page
int
)
(
*
transactions
,
error
)
{
params
:=
map
[
string
]
int
{
"
"
:
page
,
}
holder
:=
transactionsHolder
{
}
if
err
:=
c
.
Get
(
"
"
,
params
,
&
holder
)
;
err
!=
{
return
,
err
}
transactions
:=
transactions
{
paginationStats
:
holder
.
paginationStats
,
}
// Remove one layer of nesting
for
_
,
tx
:=
range
holder
.
Transactions
{
transactions
.
Transactions
=
append
(
transactions
.
Transactions
,
tx
.
Transaction
)
}
return
&
transactions
,
}

// GetTransactions gets transactions associated with an account


func (c Client) GetOrders(page int) (*orders, error) {
	holder := ordersHolder{}
	params := map[string]int{
		"page": page,
	}
	if err := c.Get("orders", params, &holder); err != nil {
		return nil, err
	}
	orders := orders{
		paginationStats: holder.paginationStats,
	}
	// Remove one layer of nesting
	for _, o := range holder.Orders {
		orders.Orders = append(orders.Orders, o.Order)
	}
	return &orders, nil
}

func
(
c
Client
)
GetOrders
(
page
int
)
(
*
orders
,
error
)
{
holder
:=
ordersHolder
{
}
params
:=
map
[
string
]
int
{
"
"
:
page
,
}
if
err
:=
c
.
Get
(
"
"
,
params
,
&
holder
)
;
err
!=
{
return
,
err
}
orders
:=
orders
{
paginationStats
:
holder
.
paginationStats
,
}
// Remove one layer of nesting
for
_
,
o
:=
range
holder
.
Orders
{
orders
.
Orders
=
append
(
orders
.
Orders
,
o
.
Order
)
}
return
&
orders
,
}

// GetOrders gets orders associated with an account


func (c Client) GetTransfers(page int) (*transfers, error) {
	params := map[string]int{
		"page": page,
	}
	holder := transfersHolder{}
	if err := c.Get("transfers", params, &holder); err != nil {
		return nil, err
	}
	transfers := transfers{
		paginationStats: holder.paginationStats,
	}
	// Remove one layer of nesting
	for _, t := range holder.Transfers {
		transfers.Transfers = append(transfers.Transfers, t.Transfer)
	}
	return &transfers, nil
}

func
(
c
Client
)
GetTransfers
(
page
int
)
(
*
transfers
,
error
)
{
params
:=
map
[
string
]
int
{
"
"
:
page
,
}
holder
:=
transfersHolder
{
}
if
err
:=
c
.
Get
(
"
"
,
params
,
&
holder
)
;
err
!=
{
return
,
err
}
transfers
:=
transfers
{
paginationStats
:
holder
.
paginationStats
,
}
// Remove one layer of nesting
for
_
,
t
:=
range
holder
.
Transfers
{
transfers
.
Transfers
=
append
(
transfers
.
Transfers
,
t
.
Transfer
)
}
return
&
transfers
,
}

// GetTransfers get transfers associated with an account


func (c Client) GetBuyPrice(qty int) (*pricesHolder, error) {
	return c.getPrice("buy", qty)
}

func ( c Client ) GetBuyPrice ( qty int ) ( * pricesHolder , error ) { return c . getPrice ( " " , qty ) }

// GetBuyPrice gets the current BTC buy price


func (c Client) GetSellPrice(qty int) (*pricesHolder, error) {
	return c.getPrice("sell", qty)
}

func ( c Client ) GetSellPrice ( qty int ) ( * pricesHolder , error ) { return c . getPrice ( " " , qty ) }

// GetSellPrice gets the current BTC sell price


func (c Client) GetTransaction(id string) (*transaction, error) {
	holder := transactionHolder{}
	if err := c.Get("transactions/"+id, nil, &holder); err != nil {
		return nil, err
	}
	if err := checkApiErrors(holder.response, "GetTransaction"); err != nil {
		return nil, err
	}
	return &holder.Transaction, nil
}

func ( c Client ) GetTransaction ( id string ) ( * transaction , error ) { holder := transactionHolder { } if err := c . Get ( " " + id , nil , & holder ) ; err != nil { return nil , err } if err := checkApiErrors ( holder . response , " " ) ; err != nil { return nil , err } return & holder . Transaction , nil }

// GetTransaction gets a particular transaction referenced by id


func (c Client) GetOrder(id string) (*order, error) {
	holder := orderHolder{}
	if err := c.Get("orders/"+id, nil, &holder); err != nil {
		return nil, err
	}
	if err := checkApiErrors(holder.response, "GetOrder"); err != nil {
		return nil, err
	}
	return &holder.Order, nil
}

func ( c Client ) GetOrder ( id string ) ( * order , error ) { holder := orderHolder { } if err := c . Get ( " " + id , nil , & holder ) ; err != nil { return nil , err } if err := checkApiErrors ( holder . response , " " ) ; err != nil { return nil , err } return & holder . Order , nil }

// GetOrder gets a particular order referenced by id


func (c Client) GetUser() (*user, error) {
	holder := usersHolder{}
	if err := c.Get("users", nil, &holder); err != nil {
		return nil, err
	}
	return &holder.Users[0].User, nil
}

func ( c Client ) GetUser ( ) ( * user , error ) { holder := usersHolder { } if err := c . Get ( " " , nil , & holder ) ; err != nil { return nil , err } return & holder . Users [ 0 ] . User , nil }

// GetUser gets the user associated with the authentication


func NewSerialDispatcher(handlers []Handler) Dispatcher {
	return &SerialDispatcher{
		handlers: handlers,
		mutex:    sync.RWMutex{},
	}
}

func NewSerialDispatcher ( handlers [ ] Handler ) Dispatcher { return & SerialDispatcher { handlers : handlers , mutex : sync . RWMutex { } , } }

// NewSerialDispatcher creates a new PrallelDispatcher with the given handlers


func (d *SerialDispatcher) AppendHandlers(handlers ...Handler) {
	d.mutex.Lock()
	defer d.mutex.Unlock()

Loop:
	for _, newHandler := range handlers {
		for _, existingHandler := range d.handlers {
			if newHandler == existingHandler {
				continue Loop
			}
		}
		d.handlers = append(d.handlers, newHandler)
	}
}

func ( d * SerialDispatcher ) AppendHandlers ( handlers ... Handler ) { d . mutex . Lock ( ) defer d . mutex . Unlock ( ) Loop : for _ , newHandler := range handlers { for _ , existingHandler := range d . handlers { if newHandler == existingHandler { continue Loop } } d . handlers = append ( d . handlers , newHandler ) } }

// AppendHandlers implements `Dispatcher.AppendHandlers`

AppendHandlers implements Dispatcher . AppendHandlers


func (d *SerialDispatcher) DispatchOptional(cmd interface{}) (err error) {
	d.mutex.RLock()
	defer d.mutex.RUnlock()

	err = d.Dispatch(cmd)
	switch err.(type) {
	case *NoHandlerFoundError:
		return nil
	default:
		return err
	}
}

func ( d * SerialDispatcher ) DispatchOptional ( cmd interface { } ) ( err error ) { d . mutex . RLock ( ) defer d . mutex . RUnlock ( ) err = d . Dispatch ( cmd ) switch err . ( type ) { case * NoHandlerFoundError : return nil default : return err } }

// DispatchOptional implements `Dispatcher.DispatchOptional`

DispatchOptional implements Dispatcher . DispatchOptional


func NewParallelDispatcher(handlers []Handler) Dispatcher {
	return &ParallelDispatcher{
		handlers: handlers,
		mutex:    sync.RWMutex{},
	}
}

func NewParallelDispatcher ( handlers [ ] Handler ) Dispatcher { return & ParallelDispatcher { handlers : handlers , mutex : sync . RWMutex { } , } }

// NewParallelDispatcher creates a new PrallelDispatcher with the given handlers


func (c *secureConn) ReleaseMsg(m []byte) {
	c.secure.ReadWriter().ReleaseMsg(m)
}

func ( c * secureConn ) ReleaseMsg ( m [ ] byte ) { c . secure . ReadWriter ( ) . ReleaseMsg ( m ) }


func ReleaseBuffer(b []byte) {
	log.Debugf("Releasing buffer! (cap,size = %d, %d)", cap(b), len(b))
	mpool.ByteSlicePool.Put(uint32(cap(b)), b)
}

func ReleaseBuffer ( b [ ] byte ) { log . Debugf ( " " , cap ( b ) , len ( b ) ) mpool . ByteSlicePool . Put ( uint32 ( cap ( b ) ) , b ) }

// ReleaseBuffer puts the given byte array back into the appropriate
// global buffer pool based on its capacity.

ReleaseBuffer puts the given byte array back into the appropriate global buffer pool based on its capacity .


func (c *singleConn) Close() error {
	c.eventMu.Lock()
	if c.event != nil {
		evt := c.event
		c.event = nil
		defer evt.Close()
	}
	c.eventMu.Unlock()

	// close underlying connection
	return c.maconn.Close()
}

func
(
c
*
singleConn
)
Close
(
)
error
{
c
.
eventMu
.
Lock
(
)
if
c
.
event
!=
{
evt
:=
c
.
event
c
.
event
=
defer
evt
.
Close
(
)
}
c
.
eventMu
.
Unlock
(
)
// close underlying connection
return
c
.
maconn
.
Close
(
)
}

// close is the internal close function, called by ContextCloser.Close

close is the internal close function called by ContextCloser . Close


func (c *singleConn) Write(buf []byte) (int, error) {
	return c.maconn.Write(buf)
}

func ( c * singleConn ) Write ( buf [ ] byte ) ( int , error ) { return c . maconn . Write ( buf ) }


func (l *listener) Accept() (transport.Conn, error) {
	if c, ok := <-l.incoming; ok {
		return c.conn, c.err
	}
	return nil, fmt.Errorf("listener is closed")
}

func ( l * listener ) Accept ( ) ( transport . Conn , error ) { if c , ok := <- l . incoming ; ok { return c . conn , c . err } return nil , fmt . Errorf ( " " ) }

// Accept waits for and returns the next connection to the listener.

Accept waits for and returns the next connection to the listener .


func (d *Dialer) AddDialer(pd transport.Dialer) {
	d.Dialers = append(d.Dialers, pd)
}

func ( d * Dialer ) AddDialer ( pd transport . Dialer ) { d . Dialers = append ( d . Dialers , pd ) }

// AddDialer adds a sub-dialer usable by this dialer.
// Dialers added first will be selected first, based on the address.

AddDialer adds a sub - dialer usable by this dialer . Dialers added first will be selected first based on the address .


func (d *Dialer) subDialerForAddr(raddr ma.Multiaddr) transport.Dialer {
	for _, pd := range d.Dialers {
		if pd.Matches(raddr) {
			return pd
		}
	}

	if d.fallback.Matches(raddr) {
		return d.fallback
	}

	return nil
}

func ( d * Dialer ) subDialerForAddr ( raddr ma . Multiaddr ) transport . Dialer { for _ , pd := range d . Dialers { if pd . Matches ( raddr ) { return pd } } if d . fallback . Matches ( raddr ) { return d . fallback } return nil }

// returns dialer that can dial the given address


func (d *Dialer) rawConnDial(ctx context.Context, raddr ma.Multiaddr, remote peer.ID) (transport.Conn, error) {
	if strings.HasPrefix(raddr.String(), "/ip4/0.0.0.0") {
		log.Event(ctx, "connDialZeroAddr", lgbl.Dial("conn", d.LocalPeer, remote, nil, raddr))
		return nil, fmt.Errorf("Attempted to connect to zero address: %s", raddr)
	}

	sd := d.subDialerForAddr(raddr)
	if sd == nil {
		return nil, fmt.Errorf("no dialer for %s", raddr)
	}

	return sd.DialContext(ctx, raddr)
}

func ( d * Dialer ) rawConnDial ( ctx context . Context , raddr ma . Multiaddr , remote peer . ID ) ( transport . Conn , error ) { if strings . HasPrefix ( raddr . String ( ) , " " ) { log . Event ( ctx , " " , lgbl . Dial ( " " , d . LocalPeer , remote , nil , raddr ) ) return nil , fmt . Errorf ( " " , raddr ) } sd := d . subDialerForAddr ( raddr ) if sd == nil { return nil , fmt . Errorf ( " " , raddr ) } return sd . DialContext ( ctx , raddr ) }

// rawConnDial dials the underlying net.Conn + manet.Conns

rawConnDial dials the underlying net . Conn + manet . Conns


func MultiaddrProtocolsMatch(a, b ma.Multiaddr) bool {
	ap := a.Protocols()
	bp := b.Protocols()

	if len(ap) != len(bp) {
		return false
	}

	for i, api := range ap {
		if api.Code != bp[i].Code {
			return false
		}
	}

	return true
}

func MultiaddrProtocolsMatch ( a , b ma . Multiaddr ) bool { ap := a . Protocols ( ) bp := b . Protocols ( ) if len ( ap ) != len ( bp ) { return false } for i , api := range ap { if api . Code != bp [ i ] . Code { return false } } return true }

// MultiaddrProtocolsMatch returns whether two multiaddrs match in protocol stacks.

MultiaddrProtocolsMatch returns whether two multiaddrs match in protocol stacks .


func MultiaddrNetMatch(tgt ma.Multiaddr, srcs []ma.Multiaddr) ma.Multiaddr {
	for _, a := range srcs {
		if MultiaddrProtocolsMatch(tgt, a) {
			return a
		}
	}
	return nil
}

func MultiaddrNetMatch ( tgt ma . Multiaddr , srcs [ ] ma . Multiaddr ) ma . Multiaddr { for _ , a := range srcs { if MultiaddrProtocolsMatch ( tgt , a ) { return a } } return nil }

// MultiaddrNetMatch returns the first Multiaddr found to match  network.

MultiaddrNetMatch returns the first Multiaddr found to match network .


func get(values map[string]interface{}, key string) interface{} {
	if len(key) == 0 || values == nil {
		return nil
	}

	key = strings.ToLower(key)
	val, ok := values[key]

	if ok {
		switch val.(type) {
		case []interface{}:
			return nil
		default:
			return val
		}
	}

	return nil
}

func get ( values map [ string ] interface { } , key string ) interface { } { if len ( key ) == 0 || values == nil { return nil } key = strings . ToLower ( key ) val , ok := values [ key ] if ok { switch val . ( type ) { case [ ] interface { } : return nil default : return val } } return nil }


func getArray(values map[string]interface{}, key string) []interface{} {
	if len(key) == 0 || values == nil {
		return nil
	}

	key = strings.ToLower(key)
	val, ok := values[key]

	if ok {
		switch v := val.(type) {
		case []interface{}:
			return v
		default:
			retVal := make([]interface{}, 1)
			retVal[0] = val
			return retVal
		}
	}

	return nil
}

func getArray ( values map [ string ] interface { } , key string ) [ ] interface { } { if len ( key ) == 0 || values == nil { return nil } key = strings . ToLower ( key ) val , ok := values [ key ] if ok { switch v := val . ( type ) { case [ ] interface { } : return v default : retVal := make ( [ ] interface { } , 1 ) retVal [ 0 ] = val return retVal } } return nil }


func buildParams(options *ImageOptions) ([]string, error) {
	a := []string{}

	if options.Input == "" {
		return []string{}, errors.New("Must provide input")
	}

	// silence extra wkhtmltoimage output
	// might want to add --javascript-delay too?
	a = append(a, "-q")
	a = append(a, "--disable-plugins")

	a = append(a, "--format")
	if options.Format != "" {
		a = append(a, options.Format)
	} else {
		a = append(a, "png")
	}

	if options.Height != 0 {
		a = append(a, "--height")
		a = append(a, strconv.Itoa(options.Height))
	}

	if options.Width != 0 {
		a = append(a, "--width")
		a = append(a, strconv.Itoa(options.Width))
	}

	if options.Quality != 0 {
		a = append(a, "--quality")
		a = append(a, strconv.Itoa(options.Quality))
	}

	// url and output come last
	if options.Input != "-" {
		// make sure we dont pass stdin if we aren't expecting it
		options.Html = ""
	}

	a = append(a, options.Input)

	if options.Output == "" {
		a = append(a, "-")
	} else {
		a = append(a, options.Output)
	}

	return a, nil
}

// buildParams takes the image options set by the user and turns them into command flags for wkhtmltoimage
// It returns an array of command flags.

buildParams takes the image options set by the user and turns them into command flags for wkhtmltoimage It returns an array of command flags .


func unsetenvGPGAgentInfo() {
	v := C.CString("GPG_AGENT_INFO=")
	defer C.free(unsafe.Pointer(v))
	C.putenv(v)
}

func unsetenvGPGAgentInfo ( ) { v := C . CString ( " " ) defer C . free ( unsafe . Pointer ( v ) ) C . putenv ( v ) }


func (c *Context) AssuanSend(
	cmd string,
	data AssuanDataCallback,
	inquiry AssuanInquireCallback,
	status AssuanStatusCallback,
) error {
	var operr C.gpgme_error_t

	dataPtr := callbackAdd(&data)
	inquiryPtr := callbackAdd(&inquiry)
	statusPtr := callbackAdd(&status)
	cmdCStr := C.CString(cmd)
	defer C.free(unsafe.Pointer(cmdCStr))
	err := C.gogpgme_op_assuan_transact_ext(
		c.ctx,
		cmdCStr,
		C.uintptr_t(dataPtr),
		C.uintptr_t(inquiryPtr),
		C.uintptr_t(statusPtr),
		&operr,
	)

	if handleError(operr) != nil {
		return handleError(operr)
	}
	return handleError(err)
}

func ( c * Context ) AssuanSend ( cmd string , data AssuanDataCallback , inquiry AssuanInquireCallback , status AssuanStatusCallback , ) error { var operr C . gpgme_error_t dataPtr := callbackAdd ( & data ) inquiryPtr := callbackAdd ( & inquiry ) statusPtr := callbackAdd ( & status ) cmdCStr := C . CString ( cmd ) defer C . free ( unsafe . Pointer ( cmdCStr ) ) err := C . gogpgme_op_assuan_transact_ext ( c . ctx , cmdCStr , C . uintptr_t ( dataPtr ) , C . uintptr_t ( inquiryPtr ) , C . uintptr_t ( statusPtr ) , & operr , ) if handleError ( operr ) != nil { return handleError ( operr ) } return handleError ( err ) }

// AssuanSend sends a raw Assuan command to gpg-agent

AssuanSend sends a raw Assuan command to gpg - agent


func NewData() (*Data, error) {
	d := newData()
	return d, handleError(C.gpgme_data_new(&d.dh))
}

func NewData ( ) ( * Data , error ) { d := newData ( ) return d , handleError ( C . gpgme_data_new ( & d . dh ) ) }

// NewData returns a new memory based data buffer


func NewDataFile(f *os.File) (*Data, error) {
	d := newData()
	return d, handleError(C.gpgme_data_new_from_fd(&d.dh, C.int(f.Fd())))
}

func NewDataFile ( f * os . File ) ( * Data , error ) { d := newData ( ) return d , handleError ( C . gpgme_data_new_from_fd ( & d . dh , C . int ( f . Fd ( ) ) ) ) }

// NewDataFile returns a new file based data buffer


func NewDataBytes(b []byte) (*Data, error) {
	d := newData()
	var cb *C.char
	if len(b) != 0 {
		cb = (*C.char)(unsafe.Pointer(&b[0]))
	}
	return d, handleError(C.gpgme_data_new_from_mem(&d.dh, cb, C.size_t(len(b)), 1))
}

func NewDataBytes ( b [ ] byte ) ( * Data , error ) { d := newData ( ) var cb * C . char if len ( b ) != 0 { cb = ( * C . char ) ( unsafe . Pointer ( & b [ 0 ] ) ) } return d , handleError ( C . gpgme_data_new_from_mem ( & d . dh , cb , C . size_t ( len ( b ) ) , 1 ) ) }

// NewDataBytes returns a new memory based data buffer that contains `b` bytes

NewDataBytes returns a new memory based data buffer that contains b bytes


func NewDataReader(r io.Reader) (*Data, error) {
	d := newData()
	d.r = r
	d.cbs.read = C.gpgme_data_read_cb_t(C.gogpgme_readfunc)
	cbc := callbackAdd(d)
	d.cbc = cbc
	return d, handleError(C.gogpgme_data_new_from_cbs(&d.dh, &d.cbs, C.uintptr_t(cbc)))
}

func NewDataReader ( r io . Reader ) ( * Data , error ) { d := newData ( ) d . r = r d . cbs . read = C . gpgme_data_read_cb_t ( C . gogpgme_readfunc ) cbc := callbackAdd ( d ) d . cbc = cbc return d , handleError ( C . gogpgme_data_new_from_cbs ( & d . dh , & d . cbs , C . uintptr_t ( cbc ) ) ) }

// NewDataReader returns a new callback based data buffer


func NewDataWriter(w io.Writer) (*Data, error) {
	d := newData()
	d.w = w
	d.cbs.write = C.gpgme_data_write_cb_t(C.gogpgme_writefunc)
	cbc := callbackAdd(d)
	d.cbc = cbc
	return d, handleError(C.gogpgme_data_new_from_cbs(&d.dh, &d.cbs, C.uintptr_t(cbc)))
}

func NewDataWriter ( w io . Writer ) ( * Data , error ) { d := newData ( ) d . w = w d . cbs . write = C . gpgme_data_write_cb_t ( C . gogpgme_writefunc ) cbc := callbackAdd ( d ) d . cbc = cbc return d , handleError ( C . gogpgme_data_new_from_cbs ( & d . dh , & d . cbs , C . uintptr_t ( cbc ) ) ) }

// NewDataWriter returns a new callback based data buffer


func NewDataReadWriter(rw io.ReadWriter) (*Data, error) {
	d := newData()
	d.r = rw
	d.w = rw
	d.cbs.read = C.gpgme_data_read_cb_t(C.gogpgme_readfunc)
	d.cbs.write = C.gpgme_data_write_cb_t(C.gogpgme_writefunc)
	cbc := callbackAdd(d)
	d.cbc = cbc
	return d, handleError(C.gogpgme_data_new_from_cbs(&d.dh, &d.cbs, C.uintptr_t(cbc)))
}

func NewDataReadWriter ( rw io . ReadWriter ) ( * Data , error ) { d := newData ( ) d . r = rw d . w = rw d . cbs . read = C . gpgme_data_read_cb_t ( C . gogpgme_readfunc ) d . cbs . write = C . gpgme_data_write_cb_t ( C . gogpgme_writefunc ) cbc := callbackAdd ( d ) d . cbc = cbc return d , handleError ( C . gogpgme_data_new_from_cbs ( & d . dh , & d . cbs , C . uintptr_t ( cbc ) ) ) }

// NewDataReadWriter returns a new callback based data buffer


func NewDataReadWriteSeeker(rw io.ReadWriteSeeker) (*Data, error) {
	d := newData()
	d.r = rw
	d.w = rw
	d.s = rw
	d.cbs.read = C.gpgme_data_read_cb_t(C.gogpgme_readfunc)
	d.cbs.write = C.gpgme_data_write_cb_t(C.gogpgme_writefunc)
	d.cbs.seek = C.gpgme_data_seek_cb_t(C.gogpgme_seekfunc)
	cbc := callbackAdd(d)
	d.cbc = cbc
	return d, handleError(C.gogpgme_data_new_from_cbs(&d.dh, &d.cbs, C.uintptr_t(cbc)))
}

func NewDataReadWriteSeeker ( rw io . ReadWriteSeeker ) ( * Data , error ) { d := newData ( ) d . r = rw d . w = rw d . s = rw d . cbs . read = C . gpgme_data_read_cb_t ( C . gogpgme_readfunc ) d . cbs . write = C . gpgme_data_write_cb_t ( C . gogpgme_writefunc ) d . cbs . seek = C . gpgme_data_seek_cb_t ( C . gogpgme_seekfunc ) cbc := callbackAdd ( d ) d . cbc = cbc return d , handleError ( C . gogpgme_data_new_from_cbs ( & d . dh , & d . cbs , C . uintptr_t ( cbc ) ) ) }

// NewDataReadWriteSeeker returns a new callback based data buffer


func (d *Data) Close() error {
	if d.dh == nil {
		return nil
	}
	if d.cbc > 0 {
		callbackDelete(d.cbc)
	}
	_, err := C.gpgme_data_release(d.dh)
	d.dh = nil
	return err
}

func ( d * Data ) Close ( ) error { if d . dh == nil { return nil } if d . cbc > 0 { callbackDelete ( d . cbc ) } _ , err := C . gpgme_data_release ( d . dh ) d . dh = nil return err }

// Close releases any resources associated with the data buffer


func (d *Data) Name() string {
	return C.GoString(C.gpgme_data_get_file_name(d.dh))
}

func ( d * Data ) Name ( ) string { return C . GoString ( C . gpgme_data_get_file_name ( d . dh ) ) }

// Name returns the associated filename if any


func NewCommand(name string, args ...string) *Command {
	return &Command{
		name: name,
		args: args,
	}
}

func NewCommand ( name string , args ... string ) * Command { return & Command { name : name , args : args , } }

// NewCommand creates a new Livestatus command instance.

NewCommand creates a new Livestatus command instance .


func (c *Command) Arg(v interface{}) *Command {
	c.args = append(c.args, fmt.Sprintf("%v", v))
	return c
}

func ( c * Command ) Arg ( v interface { } ) * Command { c . args = append ( c . args , fmt . Sprintf ( " " , v ) ) return c }

// Arg appends a new argument to the command.

Arg appends a new argument to the command .


func (c Command) String() string {
	s := fmt.Sprintf("COMMAND [%d] %s", time.Now().Unix(), c.name)
	if len(c.args) > 0 {
		s += ";" + strings.Join(c.args, ";")
	}
	s += "\n\n"

	return s
}

func ( c Command ) String ( ) string { s := fmt . Sprintf ( " " , time . Now ( ) . Unix ( ) , c . name ) if len ( c . args ) > 0 { s += " " + strings . Join ( c . args , " " ) } s += " \n \n " return s }

// String returns a string representation of the Livestatus command.

String returns a string representation of the Livestatus command .


func (r Record) Columns() []string {
	cols := []string{}
	for k := range r {
		cols = append(cols, k)
	}
	sort.Strings(cols)

	return cols
}

func ( r Record ) Columns ( ) [ ] string { cols := [ ] string { } for k := range r { cols = append ( cols , k ) } sort . Strings ( cols ) return cols }

// Columns returns the list of the record columns.

Columns returns the list of the record columns .


func (r Record) Get(column string) (interface{}, error) {
	v, ok := r[column]
	if !ok {
		return nil, ErrUnknownColumn
	}

	return v, nil
}

func ( r Record ) Get ( column string ) ( interface { } , error ) { v , ok := r [ column ] if ! ok { return nil , ErrUnknownColumn } return v , nil }

// Get returns an interface value for a specific column.

Get returns an interface value for a specific column .


func (r Record) GetBool(column string) (bool, error) {
	v, err := r.getKey(reflect.Float64, column)
	if err != nil {
		return false, err
	}

	return v == 1.0, nil
}

func ( r Record ) GetBool ( column string ) ( bool , error ) { v , err := r . getKey ( reflect . Float64 , column ) if err != nil { return false , err } return v == 1.0 , nil }

// GetBool returns a boolean value for a specific column.

GetBool returns a boolean value for a specific column .


func (r Record) GetInt(column string) (int64, error) {
	v, err := r.getKey(reflect.Float64, column)
	if err != nil {
		return 0, err
	}

	return int64(v.(float64)), nil
}

func ( r Record ) GetInt ( column string ) ( int64 , error ) { v , err := r . getKey ( reflect . Float64 , column ) if err != nil { return 0 , err } return int64 ( v . ( float64 ) ) , nil }

// GetInt returns an integer value for a specific column.

GetInt returns an integer value for a specific column .


func (r Record) GetSlice(column string) ([]interface{}, error) {
	v, err := r.getKey(reflect.Slice, column)
	if err != nil {
		return nil, err
	}

	rv := reflect.ValueOf(v)
	n := rv.Len()
	out := make([]interface{}, n)

	for i := 0; i < n; i++ {
		out[i] = rv.Index(i).Interface()
	}

	return out, nil
}

func ( r Record ) GetSlice ( column string ) ( [ ] interface { } , error ) { v , err := r . getKey ( reflect . Slice , column ) if err != nil { return nil , err } rv := reflect . ValueOf ( v ) n := rv . Len ( ) out := make ( [ ] interface { } , n ) for i := 0 ; i < n ; i ++ { out [ i ] = rv . Index ( i ) . Interface ( ) } return out , nil }

// GetSlice returns a slice of interface value for a specific column.

GetSlice returns a slice of interface value for a specific column .


func (r Record) GetString(column string) (string, error) {
	v, err := r.getKey(reflect.String, column)
	if err != nil {
		return "", err
	}

	return v.(string), nil
}

func ( r Record ) GetString ( column string ) ( string , error ) { v , err := r . getKey ( reflect . String , column ) if err != nil { return " " , err } return v . ( string ) , nil }

// GetString returns a string value for a specific column.

GetString returns a string value for a specific column .


func (r Record) GetTime(column string) (time.Time, error) {
	v, err := r.getKey(reflect.Float64, column)
	if err != nil {
		return time.Time{}, err
	}

	return time.Unix(int64(v.(float64)), 0), nil
}

func ( r Record ) GetTime ( column string ) ( time . Time , error ) { v , err := r . getKey ( reflect . Float64 , column ) if err != nil { return time . Time { } , err } return time . Unix ( int64 ( v . ( float64 ) ) , 0 ) , nil }

// GetTime returns a time struct value for a specific column.

GetTime returns a time struct value for a specific column .


func ChangeContactModattr(
	contact_name string,
	value string,
) *livestatus.Command {
	return livestatus.NewCommand(
		"CHANGE_CONTACT_MODATTR",
		stringifyArg("contact_name", "string", contact_name),
		stringifyArg("value", "string", value),
	)
}

func ChangeContactModattr ( contact_name string , value string , ) * livestatus . Command { return livestatus . NewCommand ( " " , stringifyArg ( " " , " " , contact_name ) , stringifyArg ( " " , " " , value ) , ) }

// ChangeContactModattr creates a new "CHANGE_CONTACT_MODATTR" Nagios command.
//
// This command changes the modified attributes value for the specified contact.
//
// Modified attributes values are used by Nagios to determine which object properties should be retained across program
// restarts.
//
// Thus, modifying the value of the attributes can affect data retention.
//
// This is an advanced option and should only be used by people who are intimately familiar with the data retention
// logic in Nagios.

ChangeContactModattr creates a new CHANGE_CONTACT_MODATTR Nagios command . This command changes the modified attributes value for the specified contact . Modified attributes values are used by Nagios to determine which object properties should be retained across program restarts . Thus modifying the value of the attributes can affect data retention . This is an advanced option and should only be used by people who are intimately familiar with the data retention logic in Nagios .


func ChangeContactModhattr(
	contact_name string,
	value string,
) *livestatus.Command {
	return livestatus.NewCommand(
		"CHANGE_CONTACT_MODHATTR",
		stringifyArg("contact_name", "string", contact_name),
		stringifyArg("value", "string", value),
	)
}

func ChangeContactModhattr ( contact_name string , value string , ) * livestatus . Command { return livestatus . NewCommand ( " " , stringifyArg ( " " , " " , contact_name ) , stringifyArg ( " " , " " , value ) , ) }

// ChangeContactModhattr creates a new "CHANGE_CONTACT_MODHATTR" Nagios command.
//
// This command changes the modified host attributes value for the specified contact.
//
// Modified attributes values are used by Nagios to determine which object properties should be retained across program
// restarts.
//
// Thus, modifying the value of the attributes can affect data retention.
//
// This is an advanced option and should only be used by people who are intimately familiar with the data retention
// logic in Nagios.

ChangeContactModhattr creates a new CHANGE_CONTACT_MODHATTR Nagios command . This command changes the modified host attributes value for the specified contact . Modified attributes values are used by Nagios to determine which object properties should be retained across program restarts . Thus modifying the value of the attributes can affect data retention . This is an advanced option and should only be used by people who are intimately familiar with the data retention logic in Nagios .


func ChangeContactModsattr(
	contact_name string,
	value string,
) *livestatus.Command {
	return livestatus.NewCommand(
		"CHANGE_CONTACT_MODSATTR",
		stringifyArg("contact_name", "string", contact_name),
		stringifyArg("value", "string", value),
	)
}

func ChangeContactModsattr ( contact_name string , value string , ) * livestatus . Command { return livestatus . NewCommand ( " " , stringifyArg ( " " , " " , contact_name ) , stringifyArg ( " " , " " , value ) , ) }

// ChangeContactModsattr creates a new "CHANGE_CONTACT_MODSATTR" Nagios command.
//
// This command changes the modified service attributes value for the specified contact.
//
// Modified attributes values are used by Nagios to determine which object properties should be retained across program
// restarts.
//
// Thus, modifying the value of the attributes can affect data retention.
//
// This is an advanced option and should only be used by people who are intimately familiar with the data retention
// logic in Nagios.

ChangeContactModsattr creates a new CHANGE_CONTACT_MODSATTR Nagios command . This command changes the modified service attributes value for the specified contact . Modified attributes values are used by Nagios to determine which object properties should be retained across program restarts . Thus modifying the value of the attributes can affect data retention . This is an advanced option and should only be used by people who are intimately familiar with the data retention logic in Nagios .


func ChangeCustomContactVar(
	contact_name string,
	varname string,
	varvalue string,
) *livestatus.Command {
	return livestatus.NewCommand(
		"CHANGE_CUSTOM_CONTACT_VAR",
		stringifyArg("contact_name", "string", contact_name),
		stringifyArg("varname", "string", varname),
		stringifyArg("varvalue", "string", varvalue),
	)
}

func ChangeCustomContactVar ( contact_name string , varname string , varvalue string , ) * livestatus . Command { return livestatus . NewCommand ( " " , stringifyArg ( " " , " " , contact_name ) , stringifyArg ( " " , " " , varname ) , stringifyArg ( " " , " " , varvalue ) , ) }

// ChangeCustomContactVar creates a new "CHANGE_CUSTOM_CONTACT_VAR" Nagios command.
//
// Changes the value of a custom contact variable.

ChangeCustomContactVar creates a new CHANGE_CUSTOM_CONTACT_VAR Nagios command . Changes the value of a custom contact variable .


func ChangeCustomHostVar(
	host_name string,
	varname string,
	varvalue string,
) *livestatus.Command {
	return livestatus.NewCommand(
		"CHANGE_CUSTOM_HOST_VAR",
		stringifyArg("host_name", "string", host_name),
		stringifyArg("varname", "string", varname),
		stringifyArg("varvalue", "string", varvalue),
	)
}

func ChangeCustomHostVar ( host_name string , varname string , varvalue string , ) * livestatus . Command { return livestatus . NewCommand ( " " , stringifyArg ( " " , " " , host_name ) , stringifyArg ( " " , " " , varname ) , stringifyArg ( " " , " " , varvalue ) , ) }

// ChangeCustomHostVar creates a new "CHANGE_CUSTOM_HOST_VAR" Nagios command.
//
// Changes the value of a custom host variable.

ChangeCustomHostVar creates a new CHANGE_CUSTOM_HOST_VAR Nagios command . Changes the value of a custom host variable .


func ChangeCustomSvcVar(
	host_name string,
	service_description string,
	varname string,
	varvalue string,
) *livestatus.Command {
	return livestatus.NewCommand(
		"CHANGE_CUSTOM_SVC_VAR",
		stringifyArg("host_name", "string", host_name),
		stringifyArg("service_description", "string", service_description),
		stringifyArg("varname", "string", varname),
		stringifyArg("varvalue", "string", varvalue),
	)
}

func ChangeCustomSvcVar ( host_name string , service_description string , varname string , varvalue string , ) * livestatus . Command { return livestatus . NewCommand ( " " , stringifyArg ( " " , " " , host_name ) , stringifyArg ( " " , " " , service_description ) , stringifyArg ( " " , " " , varname ) , stringifyArg ( " " , " " , varvalue ) , ) }

// ChangeCustomSvcVar creates a new "CHANGE_CUSTOM_SVC_VAR" Nagios command.
//
// Changes the value of a custom service variable.

ChangeCustomSvcVar creates a new CHANGE_CUSTOM_SVC_VAR Nagios command . Changes the value of a custom service variable .


func ChangeHostCheckTimeperiod(
	host_name string,
	timeperiod string,
) *livestatus.Command {
	return livestatus.NewCommand(
		"CHANGE_HOST_CHECK_TIMEPERIOD",
		stringifyArg("host_name", "string", host_name),
		stringifyArg("timeperiod", "string", timeperiod),
	)
}

func ChangeHostCheckTimeperiod ( host_name string , timeperiod string , ) * livestatus . Command { return livestatus . NewCommand ( " " , stringifyArg ( " " , " " , host_name ) , stringifyArg ( " " , " " , timeperiod ) , ) }

// ChangeHostCheckTimeperiod creates a new "CHANGE_HOST_CHECK_TIMEPERIOD" Nagios command.
//
// Changes the valid check period for the specified host.

ChangeHostCheckTimeperiod creates a new CHANGE_HOST_CHECK_TIMEPERIOD Nagios command . Changes the valid check period for the specified host .


func ChangeHostModattr(
	host_name string,
	value string,
) *livestatus.Command {
	return livestatus.NewCommand(
		"CHANGE_HOST_MODATTR",
		stringifyArg("host_name", "string", host_name),
		stringifyArg("value", "string", value),
	)
}

func ChangeHostModattr ( host_name string , value string , ) * livestatus . Command { return livestatus . NewCommand ( " " , stringifyArg ( " " , " " , host_name ) , stringifyArg ( " " , " " , value ) , ) }

// ChangeHostModattr creates a new "CHANGE_HOST_MODATTR" Nagios command.
//
// This command changes the modified attributes value for the specified host.
//
// Modified attributes values are used by Nagios to determine which object properties should be retained across program
// restarts.
//
// Thus, modifying the value of the attributes can affect data retention.
//
// This is an advanced option and should only be used by people who are intimately familiar with the data retention
// logic in Nagios.

ChangeHostModattr creates a new CHANGE_HOST_MODATTR Nagios command . This command changes the modified attributes value for the specified host . Modified attributes values are used by Nagios to determine which object properties should be retained across program restarts . Thus modifying the value of the attributes can affect data retention . This is an advanced option and should only be used by people who are intimately familiar with the data retention logic in Nagios .


func ChangeSvcModattr(
	host_name string,
	service_description string,
	value string,
) *livestatus.Command {
	return livestatus.NewCommand(
		"CHANGE_SVC_MODATTR",
		stringifyArg("host_name", "string", host_name),
		stringifyArg("service_description", "string", service_description),
		stringifyArg("value", "string", value),
	)
}

func ChangeSvcModattr ( host_name string , service_description string , value string , ) * livestatus . Command { return livestatus . NewCommand ( " " , stringifyArg ( " " , " " , host_name ) , stringifyArg ( " " , " " , service_description ) , stringifyArg ( " " , " " , value ) , ) }

// ChangeSvcModattr creates a new "CHANGE_SVC_MODATTR" Nagios command.
//
// This command changes the modified attributes value for the specified service.
//
// Modified attributes values are used by Nagios to determine which object properties should be retained across program
// restarts.
//
// Thus, modifying the value of the attributes can affect data retention.
//
// This is an advanced option and should only be used by people who are intimately familiar with the data retention
// logic in Nagios.

ChangeSvcModattr creates a new CHANGE_SVC_MODATTR Nagios command . This command changes the modified attributes value for the specified service . Modified attributes values are used by Nagios to determine which object properties should be retained across program restarts . Thus modifying the value of the attributes can affect data retention . This is an advanced option and should only be used by people who are intimately familiar with the data retention logic in Nagios .


func DelAllSvcComments(
	host_name string,
	service_description string,
) *livestatus.Command {
	return livestatus.NewCommand(
		"DEL_ALL_SVC_COMMENTS",
		stringifyArg("host_name", "string", host_name),
		stringifyArg("service_description", "string", service_description),
	)
}

func DelAllSvcComments ( host_name string , service_description string , ) * livestatus . Command { return livestatus . NewCommand ( " " , stringifyArg ( " " , " " , host_name ) , stringifyArg ( " " , " " , service_description ) , ) }

// DelAllSvcComments creates a new "DEL_ALL_SVC_COMMENTS" Nagios command.
//
// Deletes all comments associated with a particular service.

DelAllSvcComments creates a new DEL_ALL_SVC_COMMENTS Nagios command . Deletes all comments associated with a particular service .


func DisablePassiveSvcChecks(
	host_name string,
	service_description string,
) *livestatus.Command {
	return livestatus.NewCommand(
		"DISABLE_PASSIVE_SVC_CHECKS",
		stringifyArg("host_name", "string", host_name),
		stringifyArg("service_description", "string", service_description),
	)
}

func DisablePassiveSvcChecks ( host_name string , service_description string , ) * livestatus . Command { return livestatus . NewCommand ( " " , stringifyArg ( " " , " " , host_name ) , stringifyArg ( " " , " " , service_description ) , ) }

// DisablePassiveSvcChecks creates a new "DISABLE_PASSIVE_SVC_CHECKS" Nagios command.
//
// Disables passive checks for the specified service.

DisablePassiveSvcChecks creates a new DISABLE_PASSIVE_SVC_CHECKS Nagios command . Disables passive checks for the specified service .


func DisableServiceFlapDetection(
	host_name string,
	service_description string,
) *livestatus.Command {
	return livestatus.NewCommand(
		"DISABLE_SERVICE_FLAP_DETECTION",
		stringifyArg("host_name", "string", host_name),
		stringifyArg("service_description", "string", service_description),
	)
}

func DisableServiceFlapDetection ( host_name string , service_description string , ) * livestatus . Command { return livestatus . NewCommand ( " " , stringifyArg ( " " , " " , host_name ) , stringifyArg ( " " , " " , service_description ) , ) }

// DisableServiceFlapDetection creates a new "DISABLE_SERVICE_FLAP_DETECTION" Nagios command.
//
// Disables flap detection for the specified service.

DisableServiceFlapDetection creates a new DISABLE_SERVICE_FLAP_DETECTION Nagios command . Disables flap detection for the specified service .


func DisableSvcCheck(
	host_name string,
	service_description string,
) *livestatus.Command {
	return livestatus.NewCommand(
		"DISABLE_SVC_CHECK",
		stringifyArg("host_name", "string", host_name),
		stringifyArg("service_description", "string", service_description),
	)
}

func DisableSvcCheck ( host_name string , service_description string , ) * livestatus . Command { return livestatus . NewCommand ( " " , stringifyArg ( " " , " " , host_name ) , stringifyArg ( " " , " " , service_description ) , ) }

// DisableSvcCheck creates a new "DISABLE_SVC_CHECK" Nagios command.
//
// Disables active checks for a particular service.

DisableSvcCheck creates a new DISABLE_SVC_CHECK Nagios command . Disables active checks for a particular service .


func DisableSvcEventHandler(
	host_name string,
	service_description string,
) *livestatus.Command {
	return livestatus.NewCommand(
		"DISABLE_SVC_EVENT_HANDLER",
		stringifyArg("host_name", "string", host_name),
		stringifyArg("service_description", "string", service_description),
	)
}

func DisableSvcEventHandler ( host_name string , service_description string , ) * livestatus . Command { return livestatus . NewCommand ( " " , stringifyArg ( " " , " " , host_name ) , stringifyArg ( " " , " " , service_description ) , ) }

// DisableSvcEventHandler creates a new "DISABLE_SVC_EVENT_HANDLER" Nagios command.
//
// Disables the event handler for the specified service.

DisableSvcEventHandler creates a new DISABLE_SVC_EVENT_HANDLER Nagios command . Disables the event handler for the specified service .


func DisableSvcFlapDetection(
	host_name string,
	service_description string,
) *livestatus.Command {
	return livestatus.NewCommand(
		"DISABLE_SVC_FLAP_DETECTION",
		stringifyArg("host_name", "string", host_name),
		stringifyArg("service_description", "string", service_description),
	)
}

func DisableSvcFlapDetection ( host_name string , service_description string , ) * livestatus . Command { return livestatus . NewCommand ( " " , stringifyArg ( " " , " " , host_name ) , stringifyArg ( " " , " " , service_description ) , ) }

// DisableSvcFlapDetection creates a new "DISABLE_SVC_FLAP_DETECTION" Nagios command.
//
// Disables flap detection for the specified service.

DisableSvcFlapDetection creates a new DISABLE_SVC_FLAP_DETECTION Nagios command . Disables flap detection for the specified service .


func DisableSvcNotifications(
	host_name string,
	service_description string,
) *livestatus.Command {
	return livestatus.NewCommand(
		"DISABLE_SVC_NOTIFICATIONS",
		stringifyArg("host_name", "string", host_name),
		stringifyArg("service_description", "string", service_description),
	)
}

func DisableSvcNotifications ( host_name string , service_description string , ) * livestatus . Command { return livestatus . NewCommand ( " " , stringifyArg ( " " , " " , host_name ) , stringifyArg ( " " , " " , service_description ) , ) }

// DisableSvcNotifications creates a new "DISABLE_SVC_NOTIFICATIONS" Nagios command.
//
// Disables notifications for a particular service.

DisableSvcNotifications creates a new DISABLE_SVC_NOTIFICATIONS Nagios command . Disables notifications for a particular service .


func EnablePassiveSvcChecks(
	host_name string,
	service_description string,
) *livestatus.Command {
	return livestatus.NewCommand(
		"ENABLE_PASSIVE_SVC_CHECKS",
		stringifyArg("host_name", "string", host_name),
		stringifyArg("service_description", "string", service_description),
	)
}

func EnablePassiveSvcChecks ( host_name string , service_description string , ) * livestatus . Command { return livestatus . NewCommand ( " " , stringifyArg ( " " , " " , host_name ) , stringifyArg ( " " , " " , service_description ) , ) }

// EnablePassiveSvcChecks creates a new "ENABLE_PASSIVE_SVC_CHECKS" Nagios command.
//
// Enables passive checks for the specified service.

EnablePassiveSvcChecks creates a new ENABLE_PASSIVE_SVC_CHECKS Nagios command . Enables passive checks for the specified service .


func EnableSvcCheck(
	host_name string,
	service_description string,
) *livestatus.Command {
	return livestatus.NewCommand(
		"ENABLE_SVC_CHECK",
		stringifyArg("host_name", "string", host_name),
		stringifyArg("service_description", "string", service_description),
	)
}

func EnableSvcCheck ( host_name string , service_description string , ) * livestatus . Command { return livestatus . NewCommand ( " " , stringifyArg ( " " , " " , host_name ) , stringifyArg ( " " , " " , service_description ) , ) }

// EnableSvcCheck creates a new "ENABLE_SVC_CHECK" Nagios command.
//
// Enables active checks for a particular service.

EnableSvcCheck creates a new ENABLE_SVC_CHECK Nagios command . Enables active checks for a particular service .


func EnableSvcEventHandler(
	host_name string,
	service_description string,
) *livestatus.Command {
	return livestatus.NewCommand(
		"ENABLE_SVC_EVENT_HANDLER",
		stringifyArg("host_name", "string", host_name),
		stringifyArg("service_description", "string", service_description),
	)
}

func EnableSvcEventHandler ( host_name string , service_description string , ) * livestatus . Command { return livestatus . NewCommand ( " " , stringifyArg ( " " , " " , host_name ) , stringifyArg ( " " , " " , service_description ) , ) }

// EnableSvcEventHandler creates a new "ENABLE_SVC_EVENT_HANDLER" Nagios command.
//
// Enables the event handler for the specified service.

EnableSvcEventHandler creates a new ENABLE_SVC_EVENT_HANDLER Nagios command . Enables the event handler for the specified service .


func EnableSvcFlapDetection(
	host_name string,
	service_description string,
) *livestatus.Command {
	return livestatus.NewCommand(
		"ENABLE_SVC_FLAP_DETECTION",
		stringifyArg("host_name", "string", host_name),
		stringifyArg("service_description", "string", service_description),
	)
}

func EnableSvcFlapDetection ( host_name string , service_description string , ) * livestatus . Command { return livestatus . NewCommand ( " " , stringifyArg ( " " , " " , host_name ) , stringifyArg ( " " , " " , service_description ) , ) }

// EnableSvcFlapDetection creates a new "ENABLE_SVC_FLAP_DETECTION" Nagios command.
//
// Enables flap detection for the specified service.
//
// In order for the flap detection algorithms to be run for the service, flap detection must be enabled on a
// program-wide basis as well.

EnableSvcFlapDetection creates a new ENABLE_SVC_FLAP_DETECTION Nagios command . Enables flap detection for the specified service . In order for the flap detection algorithms to be run for the service flap detection must be enabled on a program - wide basis as well .


func EnableSvcNotifications(
	host_name string,
	service_description string,
) *livestatus.Command {
	return livestatus.NewCommand(
		"ENABLE_SVC_NOTIFICATIONS",
		stringifyArg("host_name", "string", host_name),
		stringifyArg("service_description", "string", service_description),
	)
}

func EnableSvcNotifications ( host_name string , service_description string , ) * livestatus . Command { return livestatus . NewCommand ( " " , stringifyArg ( " " , " " , host_name ) , stringifyArg ( " " , " " , service_description ) , ) }

// EnableSvcNotifications creates a new "ENABLE_SVC_NOTIFICATIONS" Nagios command.
//
// Enables notifications for a particular service.
//
// Notifications will be sent out for the service only if notifications are enabled on a program-wide basis as well.

EnableSvcNotifications creates a new ENABLE_SVC_NOTIFICATIONS Nagios command . Enables notifications for a particular service . Notifications will be sent out for the service only if notifications are enabled on a program - wide basis as well .


func RemoveSvcAcknowledgement(
	host_name string,
	service_description string,
) *livestatus.Command {
	return livestatus.NewCommand(
		"REMOVE_SVC_ACKNOWLEDGEMENT",
		stringifyArg("host_name", "string", host_name),
		stringifyArg("service_description", "string", service_description),
	)
}

func RemoveSvcAcknowledgement ( host_name string , service_description string , ) * livestatus . Command { return livestatus . NewCommand ( " " , stringifyArg ( " " , " " , host_name ) , stringifyArg ( " " , " " , service_description ) , ) }

// RemoveSvcAcknowledgement creates a new "REMOVE_SVC_ACKNOWLEDGEMENT" Nagios command.
//
// This removes the problem acknowledgement for a particular service.
//
// Once the acknowledgement has been removed, notifications can once again be sent out for the given service.

RemoveSvcAcknowledgement creates a new REMOVE_SVC_ACKNOWLEDGEMENT Nagios command . This removes the problem acknowledgement for a particular service . Once the acknowledgement has been removed notifications can once again be sent out for the given service .


func StartObsessingOverSvc(
	host_name string,
	service_description string,
) *livestatus.Command {
	return livestatus.NewCommand(
		"START_OBSESSING_OVER_SVC",
		stringifyArg("host_name", "string", host_name),
		stringifyArg("service_description", "string", service_description),
	)
}

func StartObsessingOverSvc ( host_name string , service_description string , ) * livestatus . Command { return livestatus . NewCommand ( " " , stringifyArg ( " " , " " , host_name ) , stringifyArg ( " " , " " , service_description ) , ) }

// StartObsessingOverSvc creates a new "START_OBSESSING_OVER_SVC" Nagios command.
//
// Enables processing of service checks via the OCSP command for the specified service.

StartObsessingOverSvc creates a new START_OBSESSING_OVER_SVC Nagios command . Enables processing of service checks via the OCSP command for the specified service .


func StopObsessingOverSvc(
	host_name string,
	service_description string,
) *livestatus.Command {
	return livestatus.NewCommand(
		"STOP_OBSESSING_OVER_SVC",
		stringifyArg("host_name", "string", host_name),
		stringifyArg("service_description", "string", service_description),
	)
}

func StopObsessingOverSvc ( host_name string , service_description string , ) * livestatus . Command { return livestatus . NewCommand ( " " , stringifyArg ( " " , " " , host_name ) , stringifyArg ( " " , " " , service_description ) , ) }

// StopObsessingOverSvc creates a new "STOP_OBSESSING_OVER_SVC" Nagios command.
//
// Disables processing of service checks via the OCSP command for the specified service.

StopObsessingOverSvc creates a new STOP_OBSESSING_OVER_SVC Nagios command . Disables processing of service checks via the OCSP command for the specified service .


func NewQuery(table string) *Query {
	return &Query{
		table:   table,
		headers: []string{},
		columns: []string{},
	}
}

func NewQuery ( table string ) * Query { return & Query { table : table , headers : [ ] string { } , columns : [ ] string { } , } }

// NewQuery creates a new Livestatus query instance.

NewQuery creates a new Livestatus query instance .


func (q *Query) Columns(names ...string) *Query {
	q.headers = append(q.headers, "Columns: "+strings.Join(names, " "))
	q.columns = names
	return q
}

func ( q * Query ) Columns ( names ... string ) * Query { q . headers = append ( q . headers , " " + strings . Join ( names , " " ) ) q . columns = names return q }

// Columns selects which columns to retrieve.

Columns selects which columns to retrieve .


func (q *Query) Filter(rule string) *Query {
	q.headers = append(q.headers, "Filter: "+rule)
	return q
}

func ( q * Query ) Filter ( rule string ) * Query { q . headers = append ( q . headers , " " + rule ) return q }

// Filter appends a new filter to the query.

Filter appends a new filter to the query .


func (q *Query) And(n int) *Query {
	q.headers = append(q.headers, fmt.Sprintf("And: %d", n))
	return q
}

func ( q * Query ) And ( n int ) * Query { q . headers = append ( q . headers , fmt . Sprintf ( " " , n ) ) return q }

// And combines the n last filters into a new filter using a `And` operation.

And combines the n last filters into a new filter using a And operation .


func (q *Query) Negate() *Query {
	q.headers = append(q.headers, "Negate:")
	return q
}

func ( q * Query ) Negate ( ) * Query { q . headers = append ( q . headers , " " ) return q }

// Negate negates the most recent filter.


func (q *Query) WaitObject(name string) *Query {
	q.headers = append(q.headers, "WaitObject: "+name)
	return q
}

func ( q * Query ) WaitObject ( name string ) * Query { q . headers = append ( q . headers , " " + name ) return q }

// WaitObject specifies an object from the table to wait on.
//
// For `hosts`, `hostgroups`, `servicegroups`, `contacts` and `contactgroups` tables this is simply the name of
// the object. For the `services` table it is the `hostname` and the service `description` separated by a space.

WaitObject specifies an object from the table to wait on . For hosts hostgroups servicegroups contacts and contactgroups tables this is simply the name of the object . For the services table it is the hostname and the service description separated by a space .


func (q *Query) WaitCondition(rule string) *Query {
	q.headers = append(q.headers, "WaitCondition: "+rule)
	return q
}

func ( q * Query ) WaitCondition ( rule string ) * Query { q . headers = append ( q . headers , " " + rule ) return q }

// WaitCondition appends a new wait condition to the query.

WaitCondition appends a new wait condition to the query .


func (q *Query) WaitConditionNegate() *Query {
	q.headers = append(q.headers, "WaitConditionNegate:")
	return q
}

func ( q * Query ) WaitConditionNegate ( ) * Query { q . headers = append ( q . headers , " " ) return q }

// WaitConditionNegate negates the most recent wait condition.

WaitConditionNegate negates the most recent wait condition .


func (q *Query) WaitTrigger(event string) *Query {
	q.headers = append(q.headers, "WaitTrigger: "+event)
	return q
}

func ( q * Query ) WaitTrigger ( event string ) * Query { q . headers = append ( q . headers , " " + event ) return q }

// WaitTrigger appends a new wait trigger to the query, waiting for a specific event broker message to recheck
// condition.

WaitTrigger appends a new wait trigger to the query waiting for a specific event broker message to recheck condition .


func (q *Query) WaitTimeout(d time.Duration) *Query {
	q.headers = append(q.headers, fmt.Sprintf("WaitTimeout: %d", d/time.Millisecond))
	return q
}

func ( q * Query ) WaitTimeout ( d time . Duration ) * Query { q . headers = append ( q . headers , fmt . Sprintf ( " " , d / time . Millisecond ) ) return q }

// WaitTimeout sets the upper limit on the time to wait before executing the query.

WaitTimeout sets the upper limit on the time to wait before executing the query .


func (q *Query) KeepAlive() *Query {
	q.headers = append(q.headers, "KeepAlive: on")
	q.keepalive = true
	return q
}

func ( q * Query ) KeepAlive ( ) * Query { q . headers = append ( q . headers , " " ) q . keepalive = true return q }

// KeepAlive keeps the connection open to reuse for additional requests.

KeepAlive keeps the connection open to reuse for additional requests .


func (q *Query) ReadTimeout(timeout time.Duration) *Query {
	q.readTimeout = timeout
	return q
}

func ( q * Query ) ReadTimeout ( timeout time . Duration ) * Query { q . readTimeout = timeout return q }

// ReadTimeout sets the connection timeout for read operations.
// Be careful when using a read timeout in conjunction with wait conditions.
// A value of 0 disables the timeout.

ReadTimeout sets the connection timeout for read operations . Be careful when using a read timeout in conjunction with wait conditions . A value of 0 disables the timeout .


func (q Query) String() string {
	s := "GET " + q.table
	if len(q.headers) > 0 {
		s += "\n" + strings.Join(q.headers, "\n")
	}
	s += "\nResponseHeader: fixed16\nOutputFormat: json\n\n"

	return s
}

func ( q Query ) String ( ) string { s := " " + q . table if len ( q . headers ) > 0 { s += " \n " + strings . Join ( q . headers , " \n " ) } s += " \n \n \n \n " return s }

// String returns a string representation of the Livestatus query.

String returns a string representation of the Livestatus query .