<commit_before>package main

import (
	"bytes"
	"errors"
	"fmt"
	"image"
	"io"
	"io/ioutil"
	"net/http"
	"reflect"
	"strings"

	"github.com/cosmos72/gomacro/base"

	"github.com/cosmos72/gomacro/xreflect"
)

// Support an interface similar - but not identical - to the IPython (canonical Jupyter kernel).
// See http://ipython.readthedocs.io/en/stable/api/generated/IPython.display.html#IPython.display.display
// for a good overview of the support types.

const (
	MIMETypeHTML       = "text/html"
	MIMETypeJavaScript = "application/javascript"
	MIMETypeJPEG       = "image/jpeg"
	MIMETypeJSON       = "application/json"
	MIMETypeLatex      = "text/latex"
	MIMETypeMarkdown   = "text/markdown"
	MIMETypePNG        = "image/png"
	MIMETypePDF        = "application/pdf"
	MIMETypeSVG        = "image/svg+xml"
	MIMETypeText       = "text/plain"
)

/**
 * general interface, allows libraries to fully specify
 * how their data is displayed by Jupyter.
 * Supports multiple MIME formats.
 *
 * Note that Data defined above is an alias:
 * libraries can implement Renderer without importing gophernotes
 */
type Renderer = interface {
	Render() Data
}

/**
 * simplified interface, allows libraries to specify
 * how their data is displayed by Jupyter.
 * Supports multiple MIME formats.
 *
 * Note that MIMEMap defined above is an alias:
 * libraries can implement SimpleRenderer without importing gophernotes
 */
type SimpleRenderer = interface {
	SimpleRender() MIMEMap
}

/**
 * specialized interfaces, each is dedicated to a specific MIME type.
 *
 * They are type aliases to emphasize that method signatures
 * are the only important thing, not the interface names.
 * Thus libraries can implement them without importing gophernotes
 */
type HTMLer = interface {
	HTML() string
}
type JavaScripter = interface {
	JavaScript() string
}
type JPEGer = interface {
	JPEG() []byte
}
type JSONer = interface {
	JSON() map[string]interface{}
}
type Latexer = interface {
	Latex() string
}
type Markdowner = interface {
	Markdown() string
}
type PNGer = interface {
	PNG() []byte
}
type PDFer = interface {
	PDF() []byte
}
type SVGer = interface {
	SVG() string
}

// injected as placeholder in the interpreter, it's then replaced at runtime
// by a closure that knows how to talk with Jupyter
func stubDisplay(Data) error {
	return errors.New("cannot display: connection with Jupyter not available")
}

// fill kernel.renderer map used to convert interpreted types
// to known rendering interfaces
func (kernel *Kernel) initRenderers() {
	kernel.render = make(map[string]xreflect.Type)
	for name, typ := range kernel.display.Types {
		if typ.Kind() == reflect.Interface {
			kernel.render[name] = typ
		}
	}
}

// if vals[] contain a single non-nil value which is auto-renderable,
// convert it to Data and return it.
// otherwise return MakeData("text/plain", fmt.Sprint(vals...))
func (kernel *Kernel) autoRenderResults(vals []interface{}, types []xreflect.Type) Data {
	var nilcount int
	var obj interface{}
	var typ xreflect.Type
	for i, val := range vals {
		if kernel.canAutoRender(val, types[i]) {
			obj = val
			typ = types[i]
		} else if val == nil {
			nilcount++
		}
	}
	if obj != nil && nilcount == len(vals)-1 {
		return kernel.autoRender("", obj, typ)
	}
	if nilcount == len(vals) {
		// if all values are nil, return empty Data
		return Data{}
	}
	return MakeData(MIMETypeText, fmt.Sprint(vals...))
}

// return true if data type should be auto-rendered graphically
func (kernel *Kernel) canAutoRender(data interface{}, typ xreflect.Type) bool {
	switch data.(type) {
	case Data, Renderer, SimpleRenderer, HTMLer, JavaScripter, JPEGer, JSONer,
		Latexer, Markdowner, PNGer, PDFer, SVGer, image.Image:
		return true
	}
	if kernel == nil || typ == nil {
		return false
	}
	// in gomacro, methods of interpreted types are emulated,
	// thus type-asserting them to interface types as done above cannot succeed.
	// Manually check if emulated type "pretends" to implement
	// at least one of the interfaces above
	for _, xtyp := range kernel.render {
		if typ.Implements(xtyp) {
			return true
		}
	}
	return false
}

var autoRenderers = map[string]func(Data, interface{}) Data{
	"Renderer": func(d Data, i interface{}) Data {
		if r, ok := i.(Renderer); ok {
			x := r.Render()
			d.Data = merge(d.Data, x.Data)
			d.Metadata = merge(d.Metadata, x.Metadata)
			d.Transient = merge(d.Transient, x.Transient)
		}
		return d
	},
	"SimpleRenderer": func(d Data, i interface{}) Data {
		if r, ok := i.(SimpleRenderer); ok {
			x := r.SimpleRender()
			d.Data = merge(d.Data, x)
		}
		return d
	},
	"HTMLer": func(d Data, i interface{}) Data {
		if r, ok := i.(HTMLer); ok {
			d.Data = ensure(d.Data)
			d.Data[MIMETypeHTML] = r.HTML()
		}
		return d
	},
	"JavaScripter": func(d Data, i interface{}) Data {
		if r, ok := i.(JavaScripter); ok {
			d.Data = ensure(d.Data)
			d.Data[MIMETypeJavaScript] = r.JavaScript()
		}
		return d
	},
	"JPEGer": func(d Data, i interface{}) Data {
		if r, ok := i.(JPEGer); ok {
			d.Data = ensure(d.Data)
			d.Data[MIMETypeJPEG] = r.JPEG()
		}
		return d
	},
	"JSONer": func(d Data, i interface{}) Data {
		if r, ok := i.(JSONer); ok {
			d.Data = ensure(d.Data)
			d.Data[MIMETypeJSON] = r.JSON()
		}
		return d
	},
	"Latexer": func(d Data, i interface{}) Data {
		if r, ok := i.(Latexer); ok {
			d.Data = ensure(d.Data)
			d.Data[MIMETypeLatex] = r.Latex()
		}
		return d
	},
	"Markdowner": func(d Data, i interface{}) Data {
		if r, ok := i.(Markdowner); ok {
			d.Data = ensure(d.Data)
			d.Data[MIMETypeMarkdown] = r.Markdown()
		}
		return d
	},
	"PNGer": func(d Data, i interface{}) Data {
		if r, ok := i.(PNGer); ok {
			d.Data = ensure(d.Data)
			d.Data[MIMETypePNG] = r.PNG()
		}
		return d
	},
	"PDFer": func(d Data, i interface{}) Data {
		if r, ok := i.(PDFer); ok {
			d.Data = ensure(d.Data)
			d.Data[MIMETypePDF] = r.PDF()
		}
		return d
	},
	"SVGer": func(d Data, i interface{}) Data {
		if r, ok := i.(SVGer); ok {
			d.Data = ensure(d.Data)
			d.Data[MIMETypeSVG] = r.SVG()
		}
		return d
	},
	"Image": func(d Data, i interface{}) Data {
		if r, ok := i.(image.Image); ok {
			b, mimeType, err := encodePng(r)
			if err != nil {
				d = makeDataErr(err)
			} else {
				d.Data = ensure(d.Data)
				d.Data[mimeType] = b
				d.Metadata = merge(d.Metadata, imageMetadata(r))
			}
		}
		return d
	},
}

// detect and render data types that should be auto-rendered graphically
func (kernel *Kernel) autoRender(mimeType string, arg interface{}, typ xreflect.Type) Data {
	var data Data
	// try Data
	if x, ok := arg.(Data); ok {
		data = x
	}

	if kernel == nil || typ == nil {
		// try all autoRenderers
		for _, fun := range autoRenderers {
			data = fun(data, arg)
		}
	} else {
		// in gomacro, methods of interpreted types are emulated.
		// Thus type-asserting them to interface types as done by autoRenderer functions above cannot succeed.
		// Manually check if emulated type "pretends" to implement one or more of the above interfaces
		// and, in case, tell the interpreter to convert to them
		for name, xtyp := range kernel.render {
			fun := autoRenderers[name]
			if fun == nil || !typ.Implements(xtyp) {
				continue
			}
			conv := kernel.ir.Comp.Converter(typ, xtyp)
			x := base.ValueInterface(conv(reflect.ValueOf(arg)))
			if x == nil {
				continue
			}
			data = fun(data, x)
		}
	}
	return fillDefaults(data, arg, "", nil, "", nil)
}

func fillDefaults(data Data, arg interface{}, s string, b []byte, mimeType string, err error) Data {
	if err != nil {
		return makeDataErr(err)
	}
	if data.Data == nil {
		data.Data = make(MIMEMap)
	}
	// cannot autodetect the mime type of a string
	if len(s) != 0 && len(mimeType) != 0 {
		data.Data[mimeType] = s
	}
	// ensure plain text is set
	if data.Data[MIMETypeText] == "" {
		if len(s) == 0 {
			s = fmt.Sprint(arg)
		}
		data.Data[MIMETypeText] = s
	}
	// if []byte is available, use it
	if len(b) != 0 {
		if len(mimeType) == 0 {
			mimeType = http.DetectContentType(b)
		}
		if len(mimeType) != 0 && mimeType != MIMETypeText {
			data.Data[mimeType] = b
		}
	}
	return data
}

// do our best to render data graphically
func render(mimeType string, data interface{}) Data {
	var kernel *Kernel // intentionally nil
	if kernel.canAutoRender(data, nil) {
		return kernel.autoRender(mimeType, data, nil)
	}
	var s string
	var b []byte
	var err error
	switch data := data.(type) {
	case string:
		s = data
	case []byte:
		b = data
	case io.Reader:
		b, err = ioutil.ReadAll(data)
	case io.WriterTo:
		var buf bytes.Buffer
		data.WriteTo(&buf)
		b = buf.Bytes()
	default:
		panic(fmt.Errorf("unsupported type, cannot render: %T", data))
	}
	return fillDefaults(Data{}, data, s, b, mimeType, err)
}

func makeDataErr(err error) Data {
	return Data{
		Data: MIMEMap{
			"ename":     "ERROR",
			"evalue":    err.Error(),
			"traceback": nil,
			"status":    "error",
		},
	}
}

func Any(mimeType string, data interface{}) Data {
	return render(mimeType, data)
}

// same as Any("", data), autodetects MIME type
func Auto(data interface{}) Data {
	return render("", data)
}

func MakeData(mimeType string, data interface{}) Data {
	d := Data{
		Data: MIMEMap{
			mimeType: data,
		},
	}
	if mimeType != MIMETypeText {
		d.Data[MIMETypeText] = fmt.Sprint(data)
	}
	return d
}

func MakeData3(mimeType string, plaintext string, data interface{}) Data {
	return Data{
		Data: MIMEMap{
			MIMETypeText: plaintext,
			mimeType:     data,
		},
	}
}

func File(mimeType string, path string) Data {
	bytes, err := ioutil.ReadFile(path)
	if err != nil {
		panic(err)
	}
	return Any(mimeType, bytes)
}

func HTML(html string) Data {
	return MakeData(MIMETypeHTML, html)
}

func JavaScript(javascript string) Data {
	return MakeData(MIMETypeJavaScript, javascript)
}

func JPEG(jpeg []byte) Data {
	return MakeData(MIMETypeJPEG, jpeg)
}

func JSON(json map[string]interface{}) Data {
	return MakeData(MIMETypeJSON, json)
}

func Latex(latex string) Data {
	return MakeData3(MIMETypeLatex, latex, "$"+strings.Trim(latex, "$")+"$")
}

func Markdown(markdown string) Data {
	return MakeData(MIMETypeMarkdown, markdown)
}

func Math(latex string) Data {
	return MakeData3(MIMETypeLatex, latex, "$$"+strings.Trim(latex, "$")+"$$")
}

func PDF(pdf []byte) Data {
	return MakeData(MIMETypePDF, pdf)
}

func PNG(png []byte) Data {
	return MakeData(MIMETypePNG, png)
}

func SVG(svg string) Data {
	return MakeData(MIMETypeSVG, svg)
}

// MIME encapsulates the data and metadata into a Data.
// The 'data' map is expected to contain at least one {key,value} pair,
// with value being a string, []byte or some other JSON serializable representation,
// and key equal to the MIME type of such value.
// The exact structure of value is determined by what the frontend expects.
// Some easier-to-use functions for common formats supported by the Jupyter frontend
// are provided by the various functions above.
func MIME(data, metadata MIMEMap) Data {
	return Data{data, metadata, nil}
}
<commit_msg>Fix display<commit_after>package main

import (
	"bytes"
	"errors"
	"fmt"
	"image"
	"io"
	"io/ioutil"
	"net/http"
	"reflect"
	"strings"

	"github.com/cosmos72/gomacro/base"

	"github.com/cosmos72/gomacro/xreflect"
)

// Support an interface similar - but not identical - to the IPython (canonical Jupyter kernel).
// See http://ipython.readthedocs.io/en/stable/api/generated/IPython.display.html#IPython.display.display
// for a good overview of the support types.

const (
	MIMETypeHTML       = "text/html"
	MIMETypeJavaScript = "application/javascript"
	MIMETypeJPEG       = "image/jpeg"
	MIMETypeJSON       = "application/json"
	MIMETypeLatex      = "text/latex"
	MIMETypeMarkdown   = "text/markdown"
	MIMETypePNG        = "image/png"
	MIMETypePDF        = "application/pdf"
	MIMETypeSVG        = "image/svg+xml"
	MIMETypeText       = "text/plain"
)

/**
 * general interface, allows libraries to fully specify
 * how their data is displayed by Jupyter.
 * Supports multiple MIME formats.
 *
 * Note that Data defined above is an alias:
 * libraries can implement Renderer without importing gophernotes
 */
type Renderer = interface {
	Render() Data
}

/**
 * simplified interface, allows libraries to specify
 * how their data is displayed by Jupyter.
 * Supports multiple MIME formats.
 *
 * Note that MIMEMap defined above is an alias:
 * libraries can implement SimpleRenderer without importing gophernotes
 */
type SimpleRenderer = interface {
	SimpleRender() MIMEMap
}

/**
 * specialized interfaces, each is dedicated to a specific MIME type.
 *
 * They are type aliases to emphasize that method signatures
 * are the only important thing, not the interface names.
 * Thus libraries can implement them without importing gophernotes
 */
type HTMLer = interface {
	HTML() string
}
type JavaScripter = interface {
	JavaScript() string
}
type JPEGer = interface {
	JPEG() []byte
}
type JSONer = interface {
	JSON() map[string]interface{}
}
type Latexer = interface {
	Latex() string
}
type Markdowner = interface {
	Markdown() string
}
type PNGer = interface {
	PNG() []byte
}
type PDFer = interface {
	PDF() []byte
}
type SVGer = interface {
	SVG() string
}

// injected as placeholder in the interpreter, it's then replaced at runtime
// by a closure that knows how to talk with Jupyter
func stubDisplay(Data) error {
	return errors.New("cannot display: connection with Jupyter not available")
}

// fill kernel.renderer map used to convert interpreted types
// to known rendering interfaces
func (kernel *Kernel) initRenderers() {
	kernel.render = make(map[string]xreflect.Type)
	for name, typ := range kernel.display.Types {
		if typ.Kind() == reflect.Interface {
			kernel.render[name] = typ
		}
	}
}

// if vals[] contain a single non-nil value which is auto-renderable,
// convert it to Data and return it.
// otherwise return MakeData("text/plain", fmt.Sprint(vals...))
func (kernel *Kernel) autoRenderResults(vals []interface{}, types []xreflect.Type) Data {
	var nilcount int
	var obj interface{}
	var typ xreflect.Type
	for i, val := range vals {
		if kernel.canAutoRender(val, types[i]) {
			obj = val
			typ = types[i]
		} else if val == nil {
			nilcount++
		}
	}
	if obj != nil && nilcount == len(vals)-1 {
		return kernel.autoRender("", obj, typ)
	}
	if nilcount == len(vals) {
		// if all values are nil, return empty Data
		return Data{}
	}
	return MakeData(MIMETypeText, fmt.Sprint(vals...))
}

// return true if data type should be auto-rendered graphically
func (kernel *Kernel) canAutoRender(data interface{}, typ xreflect.Type) bool {
	switch data.(type) {
	case Data, Renderer, SimpleRenderer, HTMLer, JavaScripter, JPEGer, JSONer,
		Latexer, Markdowner, PNGer, PDFer, SVGer, image.Image:
		return true
	}
	if kernel == nil || typ == nil {
		return false
	}
	// in gomacro, methods of interpreted types are emulated,
	// thus type-asserting them to interface types as done above cannot succeed.
	// Manually check if emulated type "pretends" to implement
	// at least one of the interfaces above
	for _, xtyp := range kernel.render {
		if typ.Implements(xtyp) {
			return true
		}
	}
	return false
}

var autoRenderers = map[string]func(Data, interface{}) Data{
	"Renderer": func(d Data, i interface{}) Data {
		if r, ok := i.(Renderer); ok {
			x := r.Render()
			d.Data = merge(d.Data, x.Data)
			d.Metadata = merge(d.Metadata, x.Metadata)
			d.Transient = merge(d.Transient, x.Transient)
		}
		return d
	},
	"SimpleRenderer": func(d Data, i interface{}) Data {
		if r, ok := i.(SimpleRenderer); ok {
			x := r.SimpleRender()
			d.Data = merge(d.Data, x)
		}
		return d
	},
	"HTMLer": func(d Data, i interface{}) Data {
		if r, ok := i.(HTMLer); ok {
			d.Data = ensure(d.Data)
			d.Data[MIMETypeHTML] = r.HTML()
		}
		return d
	},
	"JavaScripter": func(d Data, i interface{}) Data {
		if r, ok := i.(JavaScripter); ok {
			d.Data = ensure(d.Data)
			d.Data[MIMETypeJavaScript] = r.JavaScript()
		}
		return d
	},
	"JPEGer": func(d Data, i interface{}) Data {
		if r, ok := i.(JPEGer); ok {
			d.Data = ensure(d.Data)
			d.Data[MIMETypeJPEG] = r.JPEG()
		}
		return d
	},
	"JSONer": func(d Data, i interface{}) Data {
		if r, ok := i.(JSONer); ok {
			d.Data = ensure(d.Data)
			d.Data[MIMETypeJSON] = r.JSON()
		}
		return d
	},
	"Latexer": func(d Data, i interface{}) Data {
		if r, ok := i.(Latexer); ok {
			d.Data = ensure(d.Data)
			d.Data[MIMETypeLatex] = r.Latex()
		}
		return d
	},
	"Markdowner": func(d Data, i interface{}) Data {
		if r, ok := i.(Markdowner); ok {
			d.Data = ensure(d.Data)
			d.Data[MIMETypeMarkdown] = r.Markdown()
		}
		return d
	},
	"PNGer": func(d Data, i interface{}) Data {
		if r, ok := i.(PNGer); ok {
			d.Data = ensure(d.Data)
			d.Data[MIMETypePNG] = r.PNG()
		}
		return d
	},
	"PDFer": func(d Data, i interface{}) Data {
		if r, ok := i.(PDFer); ok {
			d.Data = ensure(d.Data)
			d.Data[MIMETypePDF] = r.PDF()
		}
		return d
	},
	"SVGer": func(d Data, i interface{}) Data {
		if r, ok := i.(SVGer); ok {
			d.Data = ensure(d.Data)
			d.Data[MIMETypeSVG] = r.SVG()
		}
		return d
	},
	"Image": func(d Data, i interface{}) Data {
		if r, ok := i.(image.Image); ok {
			b, mimeType, err := encodePng(r)
			if err != nil {
				d = makeDataErr(err)
			} else {
				d.Data = ensure(d.Data)
				d.Data[mimeType] = b
				d.Metadata = merge(d.Metadata, imageMetadata(r))
			}
		}
		return d
	},
}

// detect and render data types that should be auto-rendered graphically
func (kernel *Kernel) autoRender(mimeType string, arg interface{}, typ xreflect.Type) Data {
	var data Data
	// try Data
	if x, ok := arg.(Data); ok {
		data = x
	}

	if kernel == nil || typ == nil {
		// try all autoRenderers
		for _, fun := range autoRenderers {
			data = fun(data, arg)
		}
	} else {
		// in gomacro, methods of interpreted types are emulated.
		// Thus type-asserting them to interface types as done by autoRenderer functions above cannot succeed.
		// Manually check if emulated type "pretends" to implement one or more of the above interfaces
		// and, in case, tell the interpreter to convert to them
		for name, xtyp := range kernel.render {
			fun := autoRenderers[name]
			if fun == nil || !typ.Implements(xtyp) {
				continue
			}
			conv := kernel.ir.Comp.Converter(typ, xtyp)
			x := arg
			if conv != nil {
				x = base.ValueInterface(conv(reflect.ValueOf(x)))
				if x == nil {
					continue
				}
			}
			data = fun(data, x)
		}
	}
	return fillDefaults(data, arg, "", nil, "", nil)
}

func fillDefaults(data Data, arg interface{}, s string, b []byte, mimeType string, err error) Data {
	if err != nil {
		return makeDataErr(err)
	}
	if data.Data == nil {
		data.Data = make(MIMEMap)
	}
	// cannot autodetect the mime type of a string
	if len(s) != 0 && len(mimeType) != 0 {
		data.Data[mimeType] = s
	}
	// ensure plain text is set
	if data.Data[MIMETypeText] == "" {
		if len(s) == 0 {
			s = fmt.Sprint(arg)
		}
		data.Data[MIMETypeText] = s
	}
	// if []byte is available, use it
	if len(b) != 0 {
		if len(mimeType) == 0 {
			mimeType = http.DetectContentType(b)
		}
		if len(mimeType) != 0 && mimeType != MIMETypeText {
			data.Data[mimeType] = b
		}
	}
	return data
}

// do our best to render data graphically
func render(mimeType string, data interface{}) Data {
	var kernel *Kernel // intentionally nil
	if kernel.canAutoRender(data, nil) {
		return kernel.autoRender(mimeType, data, nil)
	}
	var s string
	var b []byte
	var err error
	switch data := data.(type) {
	case string:
		s = data
	case []byte:
		b = data
	case io.Reader:
		b, err = ioutil.ReadAll(data)
	case io.WriterTo:
		var buf bytes.Buffer
		data.WriteTo(&buf)
		b = buf.Bytes()
	default:
		panic(fmt.Errorf("unsupported type, cannot render: %T", data))
	}
	return fillDefaults(Data{}, data, s, b, mimeType, err)
}

func makeDataErr(err error) Data {
	return Data{
		Data: MIMEMap{
			"ename":     "ERROR",
			"evalue":    err.Error(),
			"traceback": nil,
			"status":    "error",
		},
	}
}

func Any(mimeType string, data interface{}) Data {
	return render(mimeType, data)
}

// same as Any("", data), autodetects MIME type
func Auto(data interface{}) Data {
	return render("", data)
}

func MakeData(mimeType string, data interface{}) Data {
	d := Data{
		Data: MIMEMap{
			mimeType: data,
		},
	}
	if mimeType != MIMETypeText {
		d.Data[MIMETypeText] = fmt.Sprint(data)
	}
	return d
}

func MakeData3(mimeType string, plaintext string, data interface{}) Data {
	return Data{
		Data: MIMEMap{
			MIMETypeText: plaintext,
			mimeType:     data,
		},
	}
}

func File(mimeType string, path string) Data {
	bytes, err := ioutil.ReadFile(path)
	if err != nil {
		panic(err)
	}
	return Any(mimeType, bytes)
}

func HTML(html string) Data {
	return MakeData(MIMETypeHTML, html)
}

func JavaScript(javascript string) Data {
	return MakeData(MIMETypeJavaScript, javascript)
}

func JPEG(jpeg []byte) Data {
	return MakeData(MIMETypeJPEG, jpeg)
}

func JSON(json map[string]interface{}) Data {
	return MakeData(MIMETypeJSON, json)
}

func Latex(latex string) Data {
	return MakeData3(MIMETypeLatex, latex, "$"+strings.Trim(latex, "$")+"$")
}

func Markdown(markdown string) Data {
	return MakeData(MIMETypeMarkdown, markdown)
}

func Math(latex string) Data {
	return MakeData3(MIMETypeLatex, latex, "$$"+strings.Trim(latex, "$")+"$$")
}

func PDF(pdf []byte) Data {
	return MakeData(MIMETypePDF, pdf)
}

func PNG(png []byte) Data {
	return MakeData(MIMETypePNG, png)
}

func SVG(svg string) Data {
	return MakeData(MIMETypeSVG, svg)
}

// MIME encapsulates the data and metadata into a Data.
// The 'data' map is expected to contain at least one {key,value} pair,
// with value being a string, []byte or some other JSON serializable representation,
// and key equal to the MIME type of such value.
// The exact structure of value is determined by what the frontend expects.
// Some easier-to-use functions for common formats supported by the Jupyter frontend
// are provided by the various functions above.
func MIME(data, metadata MIMEMap) Data {
	return Data{data, metadata, nil}
}
<|endoftext|>


<commit_before>package gobcy

import "time"

//Blockchain represents information about
//the state of a blockchain.
type Blockchain struct {
	Name             string    `json:"name"`
	Height           int       `json:"height"`
	Hash             string    `json:"hash"`
	Time             time.Time `json:"time"`
	PrevHash         string    `json:"previous_hash"`
	PeerCount        int       `json:"peer_count"`
	HighFee          int       `json:"high_fee_per_kb"`
	MediumFee        int       `json:"medium_fee_per_kb"`
	LowFee           int       `json:"low_fee_per_kb"`
	UnconfirmedCount int       `json:"unconfirmed_count"`
	LastForkHeight   int       `json:"last_fork_height"`
	LastForkHash     string    `json:"last_fork_hash"`
}

//Block represents information about the state
//of a given block in a blockchain.
type Block struct {
	Hash         string    `json:"hash"`
	Height       int       `json:"height"`
	Depth        int       `json:"depth"`
	Chain        string    `json:"chain"`
	Total        int       `json:"total"`
	Fees         int       `json:"fees"`
	Ver          int       `json:"ver"`
	Time         time.Time `json:"time"`
	ReceivedTime time.Time `json:"received_time"`
	RelayedBy    string    `json:"relayed_by,omitempty"`
	Bits         int       `json:"bits"`
	Nonce        int       `json:"nonce"`
	NumTX        int       `json:"n_tx"`
	PrevBlock    string    `json:"prev_block"`
	MerkleRoot   string    `json:"mrkl_root"`
	TXids        []string  `json:"txids"`
	NextTXs      string    `json:"next_txids"`
}

//TX represents information about the state
//of a given transaction in a blockchain.
type TX struct {
	BlockHash     string     `json:"block_hash,omitempty"`
	BlockHeight   int        `json:"block_height,omitempty"`
	Hash          string     `json:"hash,omitempty"`
	Addresses     []string   `json:"addresses,omitempty"`
	Total         int        `json:"total,omitempty"`
	Fees          int        `json:"fees,omitempty"`
	Size          int        `json:"size"`
	Preference    string     `json:"preference,omitempty"`
	RelayedBy     string     `json:"relayed_by,omitempty"`
	Received      time.Time  `json:"received,omitempty"`
	Confirmed     time.Time  `json:"confirmed,omitempty"`
	Confirmations int        `json:"confirmations,omitempty"`
	Confidence    float64    `json:"confidence,omitempty"`
	Ver           int        `json:"ver,omitempty"`
	LockTime      int        `json:"lock_time,omitempty"`
	DoubleSpend   bool       `json:"double_spend,omitempty"`
	DoubleOf      string     `json:"double_of,omitempty"`
	ReceiveCount  int        `json:"receive_count,omitempty"`
	VinSize       int        `json:"vin_sz,omitempty"`
	VoutSize      int        `json:"vout_sz,omitempty"`
	Hex           string     `json:"hex,omitempty"`
	DataProtocol  string     `json:"data_protocol,omitempty"`
	ChangeAddress string     `json:"change_address,omitempty"`
	NextInputs    string     `json:"next_inputs,omitempty"`
	NextOutputs   string     `json:"next_outputs,omitempty"`
	Inputs        []TXInput  `json:"inputs"`
	Outputs       []TXOutput `json:"outputs"`
}

//TXInput represents the state of a transaction input
type TXInput struct {
	PrevHash    string   `json:"prev_hash,omitempty"`
	OutputIndex int      `json:"output_index,omitempty"`
	OutputValue int      `json:"output_value,omitempty"`
	Addresses   []string `json:"addresses"`
	Sequence    int      `json:"sequence,omitempty"`
	ScriptType  string   `json:"script_type,omitempty"`
	Script      string   `json:"script,omitempty"`
	Age         int      `json:"age,omitempty"`
	WalletName  string   `json:"wallet_name,omitempty"`
}

//TXOutput represents the state of a transaction output
type TXOutput struct {
	SpentBy    string   `json:"spent_by,omitempty"`
	Value      int      `json:"value"`
	Addresses  []string `json:"addresses"`
	ScriptType string   `json:"script_type,omitempty"`
	Script     string   `json:"script,omitempty"`
	DataHex    string   `json:"data_hex,omitempty"`
	DataString string   `json:"data_string,omitempty"`
}

//TXConf represents information about the
//confidence of an unconfirmed transaction.
type TXConf struct {
	Age          int     `json:"age_millis"`
	ReceiveCount int     `json:"receive_count,omitempty"`
	Confidence   float64 `json:"confidence"`
	TXHash       string  `json:"txhash"`
}

//TXRef represents summarized data about a
//transaction input or output.
type TXRef struct {
	Address       string    `json:"address,omitempty"`
	BlockHeight   int       `json:"block_height"`
	TXHash        string    `json:"tx_hash"`
	TXInputN      int       `json:"tx_input_n"`
	TXOutputN     int       `json:"tx_output_n"`
	Value         int       `json:"value"`
	Pref          string    `json:"preference"`
	Spent         bool      `json:"spent"`
	DoubleSpend   bool      `json:"double_spend"`
	DoubleOf      string    `json:"double_of,omitempty"`
	Confirmations int       `json:"confirmations"`
	RefBalance    int       `json:"ref_balance,omitempty"`
	Confidence    float64   `json:"confidence,omitempty"`
	Confirmed     time.Time `json:"confirmed,omitempty"`
	SpentBy       string    `json:"spent_by,omitempty"`
	Received      time.Time `json:"received,omitempty"`
	ReceivedCount int       `json:"received_count,omitempty"`
}

//TXSkel represents the return call to BlockCypher's
//txs/new endpoint, and includes error information,
//hex transactions that need to be signed, and space
//for the signed transactions and associated public keys.
type TXSkel struct {
	Trans      TX       `json:"tx"`
	ToSign     []string `json:"tosign"`
	Signatures []string `json:"signatures"`
	PubKeys    []string `json:"pubkeys,omitempty"`
	ToSignTX   []string `json:"tosign_tx,omitempty"`
	Errors     []struct {
		Error string `json:"error,omitempty"`
	} `json:"errors,omitempty"`
}

//NullData represents the call and return to BlockCypher's
//Data API, allowing you to embed up to 80 bytes into
//a blockchain via an OP_RETURN.
type NullData struct {
	Data     string `json:"data"`
	Encoding string `json:"encoding,omitempty"`
	Hash     string `json:"hash,omitempty"`
}

//MicroTX represents a microtransaction. For small-value
//transactions, BlockCypher will sign the transaction
//on your behalf, with your private key (if provided).
//Setting a separate change address is recommended.
//Where your application model allows it, consider
//only using public keys with microtransactions,
//and sign the microtransaction with your private key
//(without sending to BlockCypher's server).
type MicroTX struct {
	//Only one of Pubkey/Private/Wif is required
	Pubkey     string   `json:"from_pubkey,omitempty"`
	Priv       string   `json:"from_private,omitempty"`
	Wif        string   `json:"from_wif,omitempty"`
	ToAddr     string   `json:"to_address"`
	Value      int      `json:"value_satoshis"`
	ChangeAddr string   `json:"change_address,omitempty"`
	Wait       bool     `json:"wait_guarantee,omitempty"`
	ToSign     []string `json:"tosign,omitempty"`
	Signatures []string `json:"signatures,omitempty"`
	Hash       string   `json:"hash,omitempty"`
	Inputs     []struct {
		PrevHash    string `json:"prev_hash"`
		OutputIndex int    `json:"output_index"`
	} `json:"inputs,omitempty"`
	Outputs []struct {
		Value   int    `json:"value"`
		Address string `json:"address"`
	} `json:"outputs,omitempty"`
	Fees int `json:"fees,omitempty"`
}

//Addr represents information about the state
//of a public address.
type Addr struct {
	Address            string   `json:"address,omitempty"`
	Wallet             Wallet   `json:"wallet,omitempty"`
	HDWallet           HDWallet `json:"hd_wallet,omitempty"`
	TotalReceived      int      `json:"total_received"`
	TotalSent          int      `json:"total_sent"`
	Balance            int      `json:"balance"`
	UnconfirmedBalance int      `json:"unconfirmed_balance"`
	FinalBalance       int      `json:"final_balance"`
	NumTX              int      `json:"n_tx"`
	UnconfirmedNumTX   int      `json:"unconfirmed_n_tx"`
	FinalNumTX         int      `json:"final_n_tx"`
	TXs                []TX     `json:"txs,omitempty"`
	TXRefs             []TXRef  `json:"txrefs,omitempty"`
	UnconfirmedTXRefs  []TXRef  `json:"unconfirmed_txrefs,omitempty"`
	HasMore            bool     `json:"hasMore,omitempty"`
}

//AddrKeychain represents information about a generated
//public-private key pair from BlockCypher's address
//generation API. Large amounts are not recommended to be
//stored with these addresses.
type AddrKeychain struct {
	Address    string   `json:"address,omitempty"`
	Private    string   `json:"private,omitempty"`
	Public     string   `json:"public,omitempty"`
	Wif        string   `json:"wif,omitempty"`
	PubKeys    []string `json:"pubkeys,omitempty"`
	ScriptType string   `json:"script_type,omitempty"`
}

//Wallet represents information about a standard wallet.
//Typically, wallets can be used wherever an address can be
//used within the API.
type Wallet struct {
	Name      string   `json:"name,omitempty"`
	Addresses []string `json:"addresses,omitempty"`
}

//HDWallet represents information about a Hierarchical Deterministic
//(HD) wallet. Like regular Wallets, HDWallets can be used wherever an
//address can be used within the API.
type HDWallet struct {
	Name            string `json:"name,omitempty"`
	ExtPubKey       string `json:"extended_public_key,omitempty"`
	SubchainIndexes []int  `json:"subchain_indexes,omitempty"`
	Chains          []struct {
		ChainAddr []struct {
			Address string `json:"address,omitempty"`
			Path    string `json:"path,omitempty"`
			Public  string `json:"public,omitempty"`
		} `json:"chain_addresses,omitempty"`
		Index int `json:"index,omitempty"`
	} `json:"chains,omitempty"`
}

//Hook represents a WebHook/WebSockets event.
//BlockCypher supports the following events:
//	Event = "unconfirmed-tx"
//	Event = "new-block"
//	Event = "confirmed-tx"
//	Event = "tx-confirmation"
//	Event = "double-spend-tx"
//  Event = "tx-confidence"
//Hash, Address, and Script are all optional; creating
//a WebHook with any of them will filter the resulting
//notifications, if appropriate. ID is returned by
//BlockCyphers servers after Posting a new WebHook; you
//shouldn't manually generate this field.
type Hook struct {
	ID            string  `json:"id,omitempty"`
	Event         string  `json:"event"`
	Hash          string  `json:"hash,omitempty"`
	WalletName    string  `json:"wallet_name,omitempty"`
	Address       string  `json:"address,omitempty"`
	Confirmations int     `json:"confirmations,omitempty"`
	Confidence    float32 `json:"confidence,omitempty"`
	Script        string  `json:"script,omitempty"`
	URL           string  `json:"url,omitempty"`
	CallbackErrs  int     `json:"callback_errors,omitempty"`
}

//PayFwd represents a reference to
//a Payment Forwarding request.
type PayFwd struct {
	ID             string   `json:"id,omitempty"`
	Destination    string   `json:"destination"`
	InputAddr      string   `json:"input_address,omitempty"`
	ProcessAddr    string   `json:"process_fees_address,omitempty"`
	ProcessPercent float64  `json:"process_fees_percent,omitempty"`
	ProcessValue   int      `json:"process_fees_satoshis,omitempty"`
	CallbackURL    string   `json:"callback_url,omitempty"`
	EnableConfirm  bool     `json:"enable_confirmations,omitempty"`
	MiningFees     int      `json:"mining_fees_satoshis,omitempty"`
	TXHistory      []string `json:"transactions,omitempty"`
}

//Payback represents a Payment Forwarding Callback.
//It's more fun to call it a "payback."
type Payback struct {
	Value       int    `json:"value"`
	Destination string `json:"destination"`
	DestHash    string `json:"transaction_hash"`
	InputAddr   string `json:"input_address"`
	InputHash   string `json:"input_transaction_hash"`
}
<commit_msg>add script to TXRef<commit_after>package gobcy

import "time"

//Blockchain represents information about
//the state of a blockchain.
type Blockchain struct {
	Name             string    `json:"name"`
	Height           int       `json:"height"`
	Hash             string    `json:"hash"`
	Time             time.Time `json:"time"`
	PrevHash         string    `json:"previous_hash"`
	PeerCount        int       `json:"peer_count"`
	HighFee          int       `json:"high_fee_per_kb"`
	MediumFee        int       `json:"medium_fee_per_kb"`
	LowFee           int       `json:"low_fee_per_kb"`
	UnconfirmedCount int       `json:"unconfirmed_count"`
	LastForkHeight   int       `json:"last_fork_height"`
	LastForkHash     string    `json:"last_fork_hash"`
}

//Block represents information about the state
//of a given block in a blockchain.
type Block struct {
	Hash         string    `json:"hash"`
	Height       int       `json:"height"`
	Depth        int       `json:"depth"`
	Chain        string    `json:"chain"`
	Total        int       `json:"total"`
	Fees         int       `json:"fees"`
	Ver          int       `json:"ver"`
	Time         time.Time `json:"time"`
	ReceivedTime time.Time `json:"received_time"`
	RelayedBy    string    `json:"relayed_by,omitempty"`
	Bits         int       `json:"bits"`
	Nonce        int       `json:"nonce"`
	NumTX        int       `json:"n_tx"`
	PrevBlock    string    `json:"prev_block"`
	MerkleRoot   string    `json:"mrkl_root"`
	TXids        []string  `json:"txids"`
	NextTXs      string    `json:"next_txids"`
}

//TX represents information about the state
//of a given transaction in a blockchain.
type TX struct {
	BlockHash     string     `json:"block_hash,omitempty"`
	BlockHeight   int        `json:"block_height,omitempty"`
	Hash          string     `json:"hash,omitempty"`
	Addresses     []string   `json:"addresses,omitempty"`
	Total         int        `json:"total,omitempty"`
	Fees          int        `json:"fees,omitempty"`
	Size          int        `json:"size"`
	Preference    string     `json:"preference,omitempty"`
	RelayedBy     string     `json:"relayed_by,omitempty"`
	Received      time.Time  `json:"received,omitempty"`
	Confirmed     time.Time  `json:"confirmed,omitempty"`
	Confirmations int        `json:"confirmations,omitempty"`
	Confidence    float64    `json:"confidence,omitempty"`
	Ver           int        `json:"ver,omitempty"`
	LockTime      int        `json:"lock_time,omitempty"`
	DoubleSpend   bool       `json:"double_spend,omitempty"`
	DoubleOf      string     `json:"double_of,omitempty"`
	ReceiveCount  int        `json:"receive_count,omitempty"`
	VinSize       int        `json:"vin_sz,omitempty"`
	VoutSize      int        `json:"vout_sz,omitempty"`
	Hex           string     `json:"hex,omitempty"`
	DataProtocol  string     `json:"data_protocol,omitempty"`
	ChangeAddress string     `json:"change_address,omitempty"`
	NextInputs    string     `json:"next_inputs,omitempty"`
	NextOutputs   string     `json:"next_outputs,omitempty"`
	Inputs        []TXInput  `json:"inputs"`
	Outputs       []TXOutput `json:"outputs"`
}

//TXInput represents the state of a transaction input
type TXInput struct {
	PrevHash    string   `json:"prev_hash,omitempty"`
	OutputIndex int      `json:"output_index,omitempty"`
	OutputValue int      `json:"output_value,omitempty"`
	Addresses   []string `json:"addresses"`
	Sequence    int      `json:"sequence,omitempty"`
	ScriptType  string   `json:"script_type,omitempty"`
	Script      string   `json:"script,omitempty"`
	Age         int      `json:"age,omitempty"`
	WalletName  string   `json:"wallet_name,omitempty"`
}

//TXOutput represents the state of a transaction output
type TXOutput struct {
	SpentBy    string   `json:"spent_by,omitempty"`
	Value      int      `json:"value"`
	Addresses  []string `json:"addresses"`
	ScriptType string   `json:"script_type,omitempty"`
	Script     string   `json:"script,omitempty"`
	DataHex    string   `json:"data_hex,omitempty"`
	DataString string   `json:"data_string,omitempty"`
}

//TXConf represents information about the
//confidence of an unconfirmed transaction.
type TXConf struct {
	Age          int     `json:"age_millis"`
	ReceiveCount int     `json:"receive_count,omitempty"`
	Confidence   float64 `json:"confidence"`
	TXHash       string  `json:"txhash"`
}

//TXRef represents summarized data about a
//transaction input or output.
type TXRef struct {
	Address       string    `json:"address,omitempty"`
	BlockHeight   int       `json:"block_height"`
	TXHash        string    `json:"tx_hash"`
	TXInputN      int       `json:"tx_input_n"`
	TXOutputN     int       `json:"tx_output_n"`
	Value         int       `json:"value"`
	Pref          string    `json:"preference"`
	Spent         bool      `json:"spent"`
	DoubleSpend   bool      `json:"double_spend"`
	DoubleOf      string    `json:"double_of,omitempty"`
	Confirmations int       `json:"confirmations"`
	Script        string    `json:"script,omitempty"`
	RefBalance    int       `json:"ref_balance,omitempty"`
	Confidence    float64   `json:"confidence,omitempty"`
	Confirmed     time.Time `json:"confirmed,omitempty"`
	SpentBy       string    `json:"spent_by,omitempty"`
	Received      time.Time `json:"received,omitempty"`
	ReceivedCount int       `json:"received_count,omitempty"`
}

//TXSkel represents the return call to BlockCypher's
//txs/new endpoint, and includes error information,
//hex transactions that need to be signed, and space
//for the signed transactions and associated public keys.
type TXSkel struct {
	Trans      TX       `json:"tx"`
	ToSign     []string `json:"tosign"`
	Signatures []string `json:"signatures"`
	PubKeys    []string `json:"pubkeys,omitempty"`
	ToSignTX   []string `json:"tosign_tx,omitempty"`
	Errors     []struct {
		Error string `json:"error,omitempty"`
	} `json:"errors,omitempty"`
}

//NullData represents the call and return to BlockCypher's
//Data API, allowing you to embed up to 80 bytes into
//a blockchain via an OP_RETURN.
type NullData struct {
	Data     string `json:"data"`
	Encoding string `json:"encoding,omitempty"`
	Hash     string `json:"hash,omitempty"`
}

//MicroTX represents a microtransaction. For small-value
//transactions, BlockCypher will sign the transaction
//on your behalf, with your private key (if provided).
//Setting a separate change address is recommended.
//Where your application model allows it, consider
//only using public keys with microtransactions,
//and sign the microtransaction with your private key
//(without sending to BlockCypher's server).
type MicroTX struct {
	//Only one of Pubkey/Private/Wif is required
	Pubkey     string   `json:"from_pubkey,omitempty"`
	Priv       string   `json:"from_private,omitempty"`
	Wif        string   `json:"from_wif,omitempty"`
	ToAddr     string   `json:"to_address"`
	Value      int      `json:"value_satoshis"`
	ChangeAddr string   `json:"change_address,omitempty"`
	Wait       bool     `json:"wait_guarantee,omitempty"`
	ToSign     []string `json:"tosign,omitempty"`
	Signatures []string `json:"signatures,omitempty"`
	Hash       string   `json:"hash,omitempty"`
	Inputs     []struct {
		PrevHash    string `json:"prev_hash"`
		OutputIndex int    `json:"output_index"`
	} `json:"inputs,omitempty"`
	Outputs []struct {
		Value   int    `json:"value"`
		Address string `json:"address"`
	} `json:"outputs,omitempty"`
	Fees int `json:"fees,omitempty"`
}

//Addr represents information about the state
//of a public address.
type Addr struct {
	Address            string   `json:"address,omitempty"`
	Wallet             Wallet   `json:"wallet,omitempty"`
	HDWallet           HDWallet `json:"hd_wallet,omitempty"`
	TotalReceived      int      `json:"total_received"`
	TotalSent          int      `json:"total_sent"`
	Balance            int      `json:"balance"`
	UnconfirmedBalance int      `json:"unconfirmed_balance"`
	FinalBalance       int      `json:"final_balance"`
	NumTX              int      `json:"n_tx"`
	UnconfirmedNumTX   int      `json:"unconfirmed_n_tx"`
	FinalNumTX         int      `json:"final_n_tx"`
	TXs                []TX     `json:"txs,omitempty"`
	TXRefs             []TXRef  `json:"txrefs,omitempty"`
	UnconfirmedTXRefs  []TXRef  `json:"unconfirmed_txrefs,omitempty"`
	HasMore            bool     `json:"hasMore,omitempty"`
}

//AddrKeychain represents information about a generated
//public-private key pair from BlockCypher's address
//generation API. Large amounts are not recommended to be
//stored with these addresses.
type AddrKeychain struct {
	Address    string   `json:"address,omitempty"`
	Private    string   `json:"private,omitempty"`
	Public     string   `json:"public,omitempty"`
	Wif        string   `json:"wif,omitempty"`
	PubKeys    []string `json:"pubkeys,omitempty"`
	ScriptType string   `json:"script_type,omitempty"`
}

//Wallet represents information about a standard wallet.
//Typically, wallets can be used wherever an address can be
//used within the API.
type Wallet struct {
	Name      string   `json:"name,omitempty"`
	Addresses []string `json:"addresses,omitempty"`
}

//HDWallet represents information about a Hierarchical Deterministic
//(HD) wallet. Like regular Wallets, HDWallets can be used wherever an
//address can be used within the API.
type HDWallet struct {
	Name            string `json:"name,omitempty"`
	ExtPubKey       string `json:"extended_public_key,omitempty"`
	SubchainIndexes []int  `json:"subchain_indexes,omitempty"`
	Chains          []struct {
		ChainAddr []struct {
			Address string `json:"address,omitempty"`
			Path    string `json:"path,omitempty"`
			Public  string `json:"public,omitempty"`
		} `json:"chain_addresses,omitempty"`
		Index int `json:"index,omitempty"`
	} `json:"chains,omitempty"`
}

//Hook represents a WebHook/WebSockets event.
//BlockCypher supports the following events:
//	Event = "unconfirmed-tx"
//	Event = "new-block"
//	Event = "confirmed-tx"
//	Event = "tx-confirmation"
//	Event = "double-spend-tx"
//  Event = "tx-confidence"
//Hash, Address, and Script are all optional; creating
//a WebHook with any of them will filter the resulting
//notifications, if appropriate. ID is returned by
//BlockCyphers servers after Posting a new WebHook; you
//shouldn't manually generate this field.
type Hook struct {
	ID            string  `json:"id,omitempty"`
	Event         string  `json:"event"`
	Hash          string  `json:"hash,omitempty"`
	WalletName    string  `json:"wallet_name,omitempty"`
	Address       string  `json:"address,omitempty"`
	Confirmations int     `json:"confirmations,omitempty"`
	Confidence    float32 `json:"confidence,omitempty"`
	Script        string  `json:"script,omitempty"`
	URL           string  `json:"url,omitempty"`
	CallbackErrs  int     `json:"callback_errors,omitempty"`
}

//PayFwd represents a reference to
//a Payment Forwarding request.
type PayFwd struct {
	ID             string   `json:"id,omitempty"`
	Destination    string   `json:"destination"`
	InputAddr      string   `json:"input_address,omitempty"`
	ProcessAddr    string   `json:"process_fees_address,omitempty"`
	ProcessPercent float64  `json:"process_fees_percent,omitempty"`
	ProcessValue   int      `json:"process_fees_satoshis,omitempty"`
	CallbackURL    string   `json:"callback_url,omitempty"`
	EnableConfirm  bool     `json:"enable_confirmations,omitempty"`
	MiningFees     int      `json:"mining_fees_satoshis,omitempty"`
	TXHistory      []string `json:"transactions,omitempty"`
}

//Payback represents a Payment Forwarding Callback.
//It's more fun to call it a "payback."
type Payback struct {
	Value       int    `json:"value"`
	Destination string `json:"destination"`
	DestHash    string `json:"transaction_hash"`
	InputAddr   string `json:"input_address"`
	InputHash   string `json:"input_transaction_hash"`
}
<|endoftext|>


<commit_before>package goinsta

import (
	"fmt"
	"net/http"
)

// ConfigFile is a structure to store the session information so that can be exported or imported.
type ConfigFile struct {
	ID        int64          `json:"id"`
	User      string         `json:"username"`
	DeviceID  string         `json:"device_id"`
	UUID      string         `json:"uuid"`
	RankToken string         `json:"rank_token"`
	Token     string         `json:"token"`
	PhoneID   string         `json:"phone_id"`
	Cookies   []*http.Cookie `json:"cookies"`
}

// School is void structure (yet).
type School struct {
}

// PicURLInfo repre
type PicURLInfo struct {
	Height int    `json:"height"`
	URL    string `json:"url"`
	Width  int    `json:"width"`
}

// ErrorN is general instagram error
type ErrorN struct {
	Message   string `json:"message"`
	Status    string `json:"status"`
	ErrorType string `json:"error_type"`
}

// Error503 is instagram API error
type Error503 struct {
	Message string
}

func (e Error503) Error() string {
	return e.Message
}

func (e ErrorN) Error() string {
	return fmt.Sprintf("%s: %s (%s)", e.Status, e.Message, e.ErrorType)
}

// Error400 is error returned by HTTP 400 status code.
type Error400 struct {
	Action     string `json:"action"`
	StatusCode string `json:"status_code"`
	Payload    struct {
		ClientContext string `json:"client_context"`
		Message       string `json:"message"`
	} `json:"payload"`
	Status string `json:"status"`
}

func (e Error400) Error() string {
	return fmt.Sprintf("%s: %s", e.Status, e.Payload.Message)
}

// Nametag is part of the account information.
type Nametag struct {
	Mode          int64       `json:"mode"`
	Gradient      int64       `json:"gradient"`
	Emoji         string      `json:"emoji"`
	SelfieSticker interface{} `json:"selfie_sticker"`
}

type friendResp struct {
	Status     string     `json:"status"`
	Friendship Friendship `json:"friendship_status"`
}

// Location stores media location information.
type Location struct {
	Pk               int64   `json:"pk"`
	Name             string  `json:"name"`
	Address          string  `json:"address"`
	City             string  `json:"city"`
	ShortName        string  `json:"short_name"`
	Lng              float64 `json:"lng"`
	Lat              float64 `json:"lat"`
	ExternalSource   string  `json:"external_source"`
	FacebookPlacesID int64   `json:"facebook_places_id"`
}

// SuggestedUsers stores the information about user suggestions.
type SuggestedUsers struct {
	Type        int `json:"type"`
	Suggestions []struct {
		User            User          `json:"user"`
		Algorithm       string        `json:"algorithm"`
		SocialContext   string        `json:"social_context"`
		Icon            string        `json:"icon"`
		Caption         string        `json:"caption"`
		MediaIds        []interface{} `json:"media_ids"`
		ThumbnailUrls   []interface{} `json:"thumbnail_urls"`
		LargeUrls       []interface{} `json:"large_urls"`
		MediaInfos      []interface{} `json:"media_infos"`
		Value           float64       `json:"value"`
		IsNewSuggestion bool          `json:"is_new_suggestion"`
	} `json:"suggestions"`
	LandingSiteType  string `json:"landing_site_type"`
	Title            string `json:"title"`
	ViewAllText      string `json:"view_all_text"`
	LandingSiteTitle string `json:"landing_site_title"`
	NetegoType       string `json:"netego_type"`
	UpsellFbPos      string `json:"upsell_fb_pos"`
	AutoDvance       string `json:"auto_dvance"`
	ID               string `json:"id"`
	TrackingToken    string `json:"tracking_token"`
}

// Friendship stores the details of the relationship between two users.
type Friendship struct {
	IncomingRequest bool `json:"incoming_request"`
	FollowedBy      bool `json:"followed_by"`
	OutgoingRequest bool `json:"outgoing_request"`
	Following       bool `json:"following"`
	Blocking        bool `json:"blocking"`
	IsPrivate       bool `json:"is_private"`
	Muting          bool `json:"muting"`
	IsMutingReel    bool `json:"is_muting_reel"`
}

// SavedMedia stores the information about media being saved before in my account.
type SavedMedia struct {
	Items []struct {
		Media Item `json:"media"`
	} `json:"items"`
	NumResults          int    `json:"num_results"`
	MoreAvailable       bool   `json:"more_available"`
	AutoLoadMoreEnabled bool   `json:"auto_load_more_enabled"`
	Status              string `json:"status"`
}

// Images are different quality images
type Images struct {
	Versions []Candidate `json:"candidates"`
}

// GetBest returns the URL of the image with the best quality.
func (img Images) GetBest() string {
	best := ""
	var mh, mw int
	for _, v := range img.Versions {
		if v.Width > mw || v.Height > mh {
			best = v.URL
			mh, mw = v.Height, v.Width
		}
	}
	return best
}

// Candidate is something that I really have no idea what it is.
type Candidate struct {
	Width  int    `json:"width"`
	Height int    `json:"height"`
	URL    string `json:"url"`
}

// Tag is the information of an user being tagged on any media.
type Tag struct {
	In []struct {
		User                  User        `json:"user"`
		Position              []float64   `json:"position"`
		StartTimeInVideoInSec interface{} `json:"start_time_in_video_in_sec"`
		DurationInVideoInSec  interface{} `json:"duration_in_video_in_sec"`
	} `json:"in"`
}

// Caption is media caption
type Caption struct {
	ID              int64  `json:"pk"`
	UserID          int64  `json:"user_id"`
	Text            string `json:"text"`
	Type            int    `json:"type"`
	CreatedAt       int64  `json:"created_at"`
	CreatedAtUtc    int64  `json:"created_at_utc"`
	ContentType     string `json:"content_type"`
	Status          string `json:"status"`
	BitFlags        int    `json:"bit_flags"`
	User            User   `json:"user"`
	DidReportAsSpam bool   `json:"did_report_as_spam"`
	MediaID         int64  `json:"media_id"`
	HasTranslation  bool   `json:"has_translation"`
}

// Mentions is a user being mentioned on media.
type Mentions struct {
	X        float64 `json:"x"`
	Y        float64 `json:"y"`
	Z        int64   `json:"z"`
	Width    float64 `json:"width"`
	Height   float64 `json:"height"`
	Rotation float64 `json:"rotation"`
	IsPinned int     `json:"is_pinned"`
	User     User    `json:"user"`
}

// Video are different quality videos
type Video struct {
	Type   int    `json:"type"`
	Width  int    `json:"width"`
	Height int    `json:"height"`
	URL    string `json:"url"`
	ID     string `json:"id"`
}

type timeStoryResp struct {
	Status string       `json:"status"`
	Media  []StoryMedia `json:"tray"`
}

type trayResp struct {
	Reels  map[string]StoryMedia `json:"reels"`
	Status string                `json:"status"`
}

// Tray is a set of story media received from timeline calls.
type Tray struct {
	Stories []StoryMedia `json:"tray"`
	Lives   struct {
		LiveItems []LiveItems `json:"post_live_items"`
	} `json:"post_live"`
	StoryRankingToken    string      `json:"story_ranking_token"`
	Broadcasts           []Broadcast `json:"broadcasts"`
	FaceFilterNuxVersion int         `json:"face_filter_nux_version"`
	HasNewNuxStory       bool        `json:"has_new_nux_story"`
	Status               string      `json:"status"`
}

func (tray *Tray) set(inst *Instagram, url string) {
	for i := range tray.Stories {
		tray.Stories[i].inst = inst
		tray.Stories[i].endpoint = url
		tray.Stories[i].setValues()
	}
	for i := range tray.Lives.LiveItems {
		tray.Lives.LiveItems[i].User.inst = inst
		for j := range tray.Lives.LiveItems[i].Broadcasts {
			tray.Lives.LiveItems[i].Broadcasts[j].BroadcastOwner.inst = inst
		}
	}
	for i := range tray.Broadcasts {
		tray.Broadcasts[i].BroadcastOwner.inst = inst
	}
}

// LiveItems are Live media items
type LiveItems struct {
	ID                  string      `json:"pk"`
	User                User        `json:"user"`
	Broadcasts          []Broadcast `json:"broadcasts"`
	LastSeenBroadcastTs int64       `json:"last_seen_broadcast_ts"`
	RankedPosition      int64       `json:"ranked_position"`
	SeenRankedPosition  int64       `json:"seen_ranked_position"`
	Muted               bool        `json:"muted"`
	CanReply            bool        `json:"can_reply"`
	CanReshare          bool        `json:"can_reshare"`
}

// Broadcast is live videos.
type Broadcast struct {
	ID                   int64  `json:"id"`
	BroadcastStatus      string `json:"broadcast_status"`
	DashManifest         string `json:"dash_manifest"`
	ExpireAt             int64  `json:"expire_at"`
	EncodingTag          string `json:"encoding_tag"`
	InternalOnly         bool   `json:"internal_only"`
	NumberOfQualities    int    `json:"number_of_qualities"`
	CoverFrameURL        string `json:"cover_frame_url"`
	BroadcastOwner       User   `json:"broadcast_owner"`
	PublishedTime        int64  `json:"published_time"`
	MediaID              string `json:"media_id"`
	BroadcastMessage     string `json:"broadcast_message"`
	OrganicTrackingToken string `json:"organic_tracking_token"`
}

// BlockedUser stores information about a used that has been blocked before.
type BlockedUser struct {
	// TODO: Convert to user
	UserID        int64  `json:"user_id"`
	Username      string `json:"username"`
	FullName      string `json:"full_name"`
	ProfilePicURL string `json:"profile_pic_url"`
	BlockAt       int64  `json:"block_at"`
}

// Unblock unblocks blocked user.
func (b *BlockedUser) Unblock() error {
	u := User{ID: b.UserID}
	return u.Unblock()
}

type blockedListResp struct {
	BlockedList []BlockedUser `json:"blocked_list"`
	PageSize    int           `json:"page_size"`
	Status      string        `json:"status"`
}

// InboxItemMedia is inbox media item
type InboxItemMedia struct {
	ClientContext              string `json:"client_context"`
	ExpiringMediaActionSummary struct {
		Count     int    `json:"count"`
		Timestamp int64  `json:"timestamp"`
		Type      string `json:"type"`
	} `json:"expiring_media_action_summary"`
	ItemID     string `json:"item_id"`
	ItemType   string `json:"item_type"`
	RavenMedia struct {
		MediaType int64 `json:"media_type"`
	} `json:"raven_media"`
	ReplyChainCount int           `json:"reply_chain_count"`
	SeenUserIds     []interface{} `json:"seen_user_ids"`
	Timestamp       int64         `json:"timestamp"`
	UserID          int64         `json:"user_id"`
	ViewMode        string        `json:"view_mode"`
}

//InboxItemLike is the heart sent during a conversation.
type InboxItemLike struct {
	ItemID    string `json:"item_id"`
	ItemType  string `json:"item_type"`
	Timestamp int64  `json:"timestamp"`
	UserID    int64  `json:"user_id"`
}

type respLikers struct {
	Users     []User `json:"users"`
	UserCount int64  `json:"user_count"`
	Status    string `json:"status"`
}

type threadResp struct {
	Conversation Conversation `json:"thread"`
	Status       string       `json:"status"`
}
<commit_msg>Update types.go fix Nametag problem (#177)<commit_after>package goinsta

import (
	"fmt"
	"net/http"
)

// ConfigFile is a structure to store the session information so that can be exported or imported.
type ConfigFile struct {
	ID        int64          `json:"id"`
	User      string         `json:"username"`
	DeviceID  string         `json:"device_id"`
	UUID      string         `json:"uuid"`
	RankToken string         `json:"rank_token"`
	Token     string         `json:"token"`
	PhoneID   string         `json:"phone_id"`
	Cookies   []*http.Cookie `json:"cookies"`
}

// School is void structure (yet).
type School struct {
}

// PicURLInfo repre
type PicURLInfo struct {
	Height int    `json:"height"`
	URL    string `json:"url"`
	Width  int    `json:"width"`
}

// ErrorN is general instagram error
type ErrorN struct {
	Message   string `json:"message"`
	Status    string `json:"status"`
	ErrorType string `json:"error_type"`
}

// Error503 is instagram API error
type Error503 struct {
	Message string
}

func (e Error503) Error() string {
	return e.Message
}

func (e ErrorN) Error() string {
	return fmt.Sprintf("%s: %s (%s)", e.Status, e.Message, e.ErrorType)
}

// Error400 is error returned by HTTP 400 status code.
type Error400 struct {
	Action     string `json:"action"`
	StatusCode string `json:"status_code"`
	Payload    struct {
		ClientContext string `json:"client_context"`
		Message       string `json:"message"`
	} `json:"payload"`
	Status string `json:"status"`
}

func (e Error400) Error() string {
	return fmt.Sprintf("%s: %s", e.Status, e.Payload.Message)
}

// Nametag is part of the account information.
type Nametag struct {
	Mode          int64       `json:"mode"`
	Gradient      string      `json:"gradient"`
	Emoji         string      `json:"emoji"`
	SelfieSticker interface{} `json:"selfie_sticker"`
}

type friendResp struct {
	Status     string     `json:"status"`
	Friendship Friendship `json:"friendship_status"`
}

// Location stores media location information.
type Location struct {
	Pk               int64   `json:"pk"`
	Name             string  `json:"name"`
	Address          string  `json:"address"`
	City             string  `json:"city"`
	ShortName        string  `json:"short_name"`
	Lng              float64 `json:"lng"`
	Lat              float64 `json:"lat"`
	ExternalSource   string  `json:"external_source"`
	FacebookPlacesID int64   `json:"facebook_places_id"`
}

// SuggestedUsers stores the information about user suggestions.
type SuggestedUsers struct {
	Type        int `json:"type"`
	Suggestions []struct {
		User            User          `json:"user"`
		Algorithm       string        `json:"algorithm"`
		SocialContext   string        `json:"social_context"`
		Icon            string        `json:"icon"`
		Caption         string        `json:"caption"`
		MediaIds        []interface{} `json:"media_ids"`
		ThumbnailUrls   []interface{} `json:"thumbnail_urls"`
		LargeUrls       []interface{} `json:"large_urls"`
		MediaInfos      []interface{} `json:"media_infos"`
		Value           float64       `json:"value"`
		IsNewSuggestion bool          `json:"is_new_suggestion"`
	} `json:"suggestions"`
	LandingSiteType  string `json:"landing_site_type"`
	Title            string `json:"title"`
	ViewAllText      string `json:"view_all_text"`
	LandingSiteTitle string `json:"landing_site_title"`
	NetegoType       string `json:"netego_type"`
	UpsellFbPos      string `json:"upsell_fb_pos"`
	AutoDvance       string `json:"auto_dvance"`
	ID               string `json:"id"`
	TrackingToken    string `json:"tracking_token"`
}

// Friendship stores the details of the relationship between two users.
type Friendship struct {
	IncomingRequest bool `json:"incoming_request"`
	FollowedBy      bool `json:"followed_by"`
	OutgoingRequest bool `json:"outgoing_request"`
	Following       bool `json:"following"`
	Blocking        bool `json:"blocking"`
	IsPrivate       bool `json:"is_private"`
	Muting          bool `json:"muting"`
	IsMutingReel    bool `json:"is_muting_reel"`
}

// SavedMedia stores the information about media being saved before in my account.
type SavedMedia struct {
	Items []struct {
		Media Item `json:"media"`
	} `json:"items"`
	NumResults          int    `json:"num_results"`
	MoreAvailable       bool   `json:"more_available"`
	AutoLoadMoreEnabled bool   `json:"auto_load_more_enabled"`
	Status              string `json:"status"`
}

// Images are different quality images
type Images struct {
	Versions []Candidate `json:"candidates"`
}

// GetBest returns the URL of the image with the best quality.
func (img Images) GetBest() string {
	best := ""
	var mh, mw int
	for _, v := range img.Versions {
		if v.Width > mw || v.Height > mh {
			best = v.URL
			mh, mw = v.Height, v.Width
		}
	}
	return best
}

// Candidate is something that I really have no idea what it is.
type Candidate struct {
	Width  int    `json:"width"`
	Height int    `json:"height"`
	URL    string `json:"url"`
}

// Tag is the information of an user being tagged on any media.
type Tag struct {
	In []struct {
		User                  User        `json:"user"`
		Position              []float64   `json:"position"`
		StartTimeInVideoInSec interface{} `json:"start_time_in_video_in_sec"`
		DurationInVideoInSec  interface{} `json:"duration_in_video_in_sec"`
	} `json:"in"`
}

// Caption is media caption
type Caption struct {
	ID              int64  `json:"pk"`
	UserID          int64  `json:"user_id"`
	Text            string `json:"text"`
	Type            int    `json:"type"`
	CreatedAt       int64  `json:"created_at"`
	CreatedAtUtc    int64  `json:"created_at_utc"`
	ContentType     string `json:"content_type"`
	Status          string `json:"status"`
	BitFlags        int    `json:"bit_flags"`
	User            User   `json:"user"`
	DidReportAsSpam bool   `json:"did_report_as_spam"`
	MediaID         int64  `json:"media_id"`
	HasTranslation  bool   `json:"has_translation"`
}

// Mentions is a user being mentioned on media.
type Mentions struct {
	X        float64 `json:"x"`
	Y        float64 `json:"y"`
	Z        int64   `json:"z"`
	Width    float64 `json:"width"`
	Height   float64 `json:"height"`
	Rotation float64 `json:"rotation"`
	IsPinned int     `json:"is_pinned"`
	User     User    `json:"user"`
}

// Video are different quality videos
type Video struct {
	Type   int    `json:"type"`
	Width  int    `json:"width"`
	Height int    `json:"height"`
	URL    string `json:"url"`
	ID     string `json:"id"`
}

type timeStoryResp struct {
	Status string       `json:"status"`
	Media  []StoryMedia `json:"tray"`
}

type trayResp struct {
	Reels  map[string]StoryMedia `json:"reels"`
	Status string                `json:"status"`
}

// Tray is a set of story media received from timeline calls.
type Tray struct {
	Stories []StoryMedia `json:"tray"`
	Lives   struct {
		LiveItems []LiveItems `json:"post_live_items"`
	} `json:"post_live"`
	StoryRankingToken    string      `json:"story_ranking_token"`
	Broadcasts           []Broadcast `json:"broadcasts"`
	FaceFilterNuxVersion int         `json:"face_filter_nux_version"`
	HasNewNuxStory       bool        `json:"has_new_nux_story"`
	Status               string      `json:"status"`
}

func (tray *Tray) set(inst *Instagram, url string) {
	for i := range tray.Stories {
		tray.Stories[i].inst = inst
		tray.Stories[i].endpoint = url
		tray.Stories[i].setValues()
	}
	for i := range tray.Lives.LiveItems {
		tray.Lives.LiveItems[i].User.inst = inst
		for j := range tray.Lives.LiveItems[i].Broadcasts {
			tray.Lives.LiveItems[i].Broadcasts[j].BroadcastOwner.inst = inst
		}
	}
	for i := range tray.Broadcasts {
		tray.Broadcasts[i].BroadcastOwner.inst = inst
	}
}

// LiveItems are Live media items
type LiveItems struct {
	ID                  string      `json:"pk"`
	User                User        `json:"user"`
	Broadcasts          []Broadcast `json:"broadcasts"`
	LastSeenBroadcastTs int64       `json:"last_seen_broadcast_ts"`
	RankedPosition      int64       `json:"ranked_position"`
	SeenRankedPosition  int64       `json:"seen_ranked_position"`
	Muted               bool        `json:"muted"`
	CanReply            bool        `json:"can_reply"`
	CanReshare          bool        `json:"can_reshare"`
}

// Broadcast is live videos.
type Broadcast struct {
	ID                   int64  `json:"id"`
	BroadcastStatus      string `json:"broadcast_status"`
	DashManifest         string `json:"dash_manifest"`
	ExpireAt             int64  `json:"expire_at"`
	EncodingTag          string `json:"encoding_tag"`
	InternalOnly         bool   `json:"internal_only"`
	NumberOfQualities    int    `json:"number_of_qualities"`
	CoverFrameURL        string `json:"cover_frame_url"`
	BroadcastOwner       User   `json:"broadcast_owner"`
	PublishedTime        int64  `json:"published_time"`
	MediaID              string `json:"media_id"`
	BroadcastMessage     string `json:"broadcast_message"`
	OrganicTrackingToken string `json:"organic_tracking_token"`
}

// BlockedUser stores information about a used that has been blocked before.
type BlockedUser struct {
	// TODO: Convert to user
	UserID        int64  `json:"user_id"`
	Username      string `json:"username"`
	FullName      string `json:"full_name"`
	ProfilePicURL string `json:"profile_pic_url"`
	BlockAt       int64  `json:"block_at"`
}

// Unblock unblocks blocked user.
func (b *BlockedUser) Unblock() error {
	u := User{ID: b.UserID}
	return u.Unblock()
}

type blockedListResp struct {
	BlockedList []BlockedUser `json:"blocked_list"`
	PageSize    int           `json:"page_size"`
	Status      string        `json:"status"`
}

// InboxItemMedia is inbox media item
type InboxItemMedia struct {
	ClientContext              string `json:"client_context"`
	ExpiringMediaActionSummary struct {
		Count     int    `json:"count"`
		Timestamp int64  `json:"timestamp"`
		Type      string `json:"type"`
	} `json:"expiring_media_action_summary"`
	ItemID     string `json:"item_id"`
	ItemType   string `json:"item_type"`
	RavenMedia struct {
		MediaType int64 `json:"media_type"`
	} `json:"raven_media"`
	ReplyChainCount int           `json:"reply_chain_count"`
	SeenUserIds     []interface{} `json:"seen_user_ids"`
	Timestamp       int64         `json:"timestamp"`
	UserID          int64         `json:"user_id"`
	ViewMode        string        `json:"view_mode"`
}

//InboxItemLike is the heart sent during a conversation.
type InboxItemLike struct {
	ItemID    string `json:"item_id"`
	ItemType  string `json:"item_type"`
	Timestamp int64  `json:"timestamp"`
	UserID    int64  `json:"user_id"`
}

type respLikers struct {
	Users     []User `json:"users"`
	UserCount int64  `json:"user_count"`
	Status    string `json:"status"`
}

type threadResp struct {
	Conversation Conversation `json:"thread"`
	Status       string       `json:"status"`
}
<|endoftext|>


<commit_before>package gomarathon

// RequestOptions passed for query api
type RequestOptions struct {
	Method string
	Path   string
	Datas  interface{}
	Params *Parameters
}

// Parameters to build url query
type Parameters struct {
	Cmd         string
	Host        string
	Scale       bool
	CallbackURL string
}

// Response representation of a full marathon response
type Response struct {
	Code     int
	Apps     []*Application `json:"apps,omitempty"`
	App      *Application   `json:"app,omitempty"`
	Leader   string         `json:"leader,omitempty"`
	Message  string         `json:"message,omitempty"`
	Versions []string       `json:",omitempty"`
	Tasks    []*Task        `json:"tasks,omitempty"`
}

// Application marathon application see :
// https://github.com/mesosphere/marathon/blob/master/REST.md#apps
type Application struct {
	ID              string            `json:"id"`
	Cmd             string            `json:"cmd,omitempty"`
	Constraints     [][]string        `json:"constraints,omitempty"`
	Container       *Container        `json:"container,omitempty"`
	CPUs            float32           `json:"cpus,omitempty"`
	Deployments     []*Deployment     `json:"deployments,omitempty"`
	Env             map[string]string `json:"env,omitempty"`
	Executor        string            `json:"executor,omitempty"`
	HealthChecks    []*HealthCheck    `json:"healthChecks,omitempty"`
	Instances       int               `json:"instances,omitemptys"`
	Mem             float32           `json:"mem,omitempty"`
	Tasks           []*Task           `json:"tasks,omitempty"`
	Ports           []int             `json:"ports,omitempty"`
	RequirePorts    bool              `json:"requirePorts,omitempty"`
	BackoffFactor   float32           `json:"backoffFactor,omitempty"`
	TasksRunning    int               `json:"tasksRunning,omitempty"`
	TasksStaged     int               `json:"tasksStaged,omitempty"`
	UpgradeStrategy *UpgradeStrategy  `json:"upgradeStrategy,omitempty"`
	Uris            []string          `json:"uris,omitempty"`
	Version         string            `json:"version,omitempty"`
}

// Container is docker parameters
type Container struct {
	Type    string    `json:"type,omitempty"`
	Docker  *Docker   `json:"docker,omitempty"`
	Volumes []*Volume `json:"volumes,omitempty"`
}

// Docker options
type Docker struct {
	Image        string         `json:"image,omitempty"`
	Network      string         `json:"network,omitempty"`
	PortMappings []*PortMapping `json:"portMappings,omitempty"`
}

// Volume is used for mounting a host directory as a container volume
type Volume struct {
	ContainerPath string `json:"containerPath,omitempty"`
	HostPath      string `json:"hostPath,omitempty"`
	Mode          string `json:"mode,omitempty"`
}

// Container PortMappings
type PortMapping struct {
	ContainerPort int    `json:"containerPort,omitempty"`
	HostPort      int    `json:"hostPort,omitempty"`
	ServicePort   int    `json:"servicePort,omitempty"`
	Protocol      string `json:"protocol,omitempty"`
}

// UpgradeStrategy has a minimumHealthCapacity which defines the minimum number of healty nodes
type UpgradeStrategy struct {
	MinimumHealthCapacity float32 `json:"minimumHealthCapacity,omitempty"`
}

// HealthCheck is described here:
// https://github.com/mesosphere/marathon/blob/master/REST.md#healthchecks
type HealthCheck struct {
	Protocol           string `json:"protocol,omitempty"`
	Path               string `json:"path,omitempty"`
	GracePeriodSeconds int    `json:"gracePeriodSeconds,omitempty"`
	IntervalSeconds    int    `json:"intervalSeconds,omitempty"`
	PortIndex          int    `json:"portIndex,omitempty"`
	TimeoutSeconds     int    `json:"timeoutSeconds,omitempty"`
}

// Task is described here:
// https://github.com/mesosphere/marathon/blob/master/REST.md#tasks
type Task struct {
	AppID     string `json:"appId"`
	Host      string `json:"host"`
	ID        string `json:"id"`
	Ports     []int  `json:"ports"`
	StagedAt  string `json:"stagedAt"`
	StartedAt string `json:"startedAt"`
	Version   string `json:"version"`
}

// Deployment is described here:
// https://mesosphere.github.io/marathon/docs/rest-api.html#get-/v2/deployments
type Deployment struct {
	AffectedApps   []string          `json:"affectedApps"`
	ID             string            `json:"id"`
	Steps          []*DeploymentStep `json:"steps"`
	CurrentActions []*DeploymentStep `json:"currentActions"`
	CurrentStep    int               `json:"currentStep"`
	TotalSteps     int               `json:"totalSteps"`
	Version        string            `json:"version"`
}

// Deployment steps
type DeploymentStep struct {
	Action string `json:"action"`
	App    string `json:"app"`
}

// EventSubscription is described here:
// https://github.com/mesosphere/marathon/blob/master/REST.md#event-subscriptions
type EventSubscription struct {
	CallbackURL  string   `json:"CallbackUrl"`
	ClientIP     string   `json:"ClientIp"`
	EventType    string   `json:"eventType"`
	CallbackURLs []string `json:"CallbackUrls"`
}
<commit_msg>Add types for the /v2/Info endpoint<commit_after>package gomarathon

// RequestOptions passed for query api
type RequestOptions struct {
	Method string
	Path   string
	Datas  interface{}
	Params *Parameters
}

// Parameters to build url query
type Parameters struct {
	Cmd         string
	Host        string
	Scale       bool
	CallbackURL string
}

// Response representation of a full marathon response
type Response struct {
	Code     int
	Apps     []*Application `json:"apps,omitempty"`
	App      *Application   `json:"app,omitempty"`
	Leader   string         `json:"leader,omitempty"`
	Message  string         `json:"message,omitempty"`
	Versions []string       `json:",omitempty"`
	Tasks    []*Task        `json:"tasks,omitempty"`

	// See ServerInfo below
	FrameworkId    string              `json:"frameworkId,omitempty"`
	EventSub       *InfoEventSub       `json:"event_subscriber,omitempty"`
	HttpConfig     *InfoHttpConfig     `json:"http_config,omitempty"`
	MarathonConfig *InfoMarathonConfig `json:"marathon_config,omitempty"`
	Name           string              `json:"name,omitempty"`
	Version        string              `json:"version,omitempty"`
	ZkConfig       *InfoZkConfig       `json:"zookeeper_config,omitempty"`
}

// Application marathon application see :
// https://github.com/mesosphere/marathon/blob/master/REST.md#apps
type Application struct {
	ID              string            `json:"id"`
	Cmd             string            `json:"cmd,omitempty"`
	Constraints     [][]string        `json:"constraints,omitempty"`
	Container       *Container        `json:"container,omitempty"`
	CPUs            float32           `json:"cpus,omitempty"`
	Deployments     []*Deployment     `json:"deployments,omitempty"`
	Env             map[string]string `json:"env,omitempty"`
	Executor        string            `json:"executor,omitempty"`
	HealthChecks    []*HealthCheck    `json:"healthChecks,omitempty"`
	Instances       int               `json:"instances,omitemptys"`
	Mem             float32           `json:"mem,omitempty"`
	Tasks           []*Task           `json:"tasks,omitempty"`
	Ports           []int             `json:"ports,omitempty"`
	RequirePorts    bool              `json:"requirePorts,omitempty"`
	BackoffFactor   float32           `json:"backoffFactor,omitempty"`
	TasksRunning    int               `json:"tasksRunning,omitempty"`
	TasksStaged     int               `json:"tasksStaged,omitempty"`
	UpgradeStrategy *UpgradeStrategy  `json:"upgradeStrategy,omitempty"`
	Uris            []string          `json:"uris,omitempty"`
	Version         string            `json:"version,omitempty"`
}

// Container is docker parameters
type Container struct {
	Type    string    `json:"type,omitempty"`
	Docker  *Docker   `json:"docker,omitempty"`
	Volumes []*Volume `json:"volumes,omitempty"`
}

// Docker options
type Docker struct {
	Image        string         `json:"image,omitempty"`
	Network      string         `json:"network,omitempty"`
	PortMappings []*PortMapping `json:"portMappings,omitempty"`
}

// Volume is used for mounting a host directory as a container volume
type Volume struct {
	ContainerPath string `json:"containerPath,omitempty"`
	HostPath      string `json:"hostPath,omitempty"`
	Mode          string `json:"mode,omitempty"`
}

// Container PortMappings
type PortMapping struct {
	ContainerPort int    `json:"containerPort,omitempty"`
	HostPort      int    `json:"hostPort,omitempty"`
	ServicePort   int    `json:"servicePort,omitempty"`
	Protocol      string `json:"protocol,omitempty"`
}

// UpgradeStrategy has a minimumHealthCapacity which defines the minimum number of healty nodes
type UpgradeStrategy struct {
	MinimumHealthCapacity float32 `json:"minimumHealthCapacity,omitempty"`
}

// HealthCheck is described here:
// https://github.com/mesosphere/marathon/blob/master/REST.md#healthchecks
type HealthCheck struct {
	Protocol           string `json:"protocol,omitempty"`
	Path               string `json:"path,omitempty"`
	GracePeriodSeconds int    `json:"gracePeriodSeconds,omitempty"`
	IntervalSeconds    int    `json:"intervalSeconds,omitempty"`
	PortIndex          int    `json:"portIndex,omitempty"`
	TimeoutSeconds     int    `json:"timeoutSeconds,omitempty"`
}

// Task is described here:
// https://github.com/mesosphere/marathon/blob/master/REST.md#tasks
type Task struct {
	AppID     string `json:"appId"`
	Host      string `json:"host"`
	ID        string `json:"id"`
	Ports     []int  `json:"ports"`
	StagedAt  string `json:"stagedAt"`
	StartedAt string `json:"startedAt"`
	Version   string `json:"version"`
}

// Deployment is described here:
// https://mesosphere.github.io/marathon/docs/rest-api.html#get-/v2/deployments
type Deployment struct {
	AffectedApps   []string          `json:"affectedApps"`
	ID             string            `json:"id"`
	Steps          []*DeploymentStep `json:"steps"`
	CurrentActions []*DeploymentStep `json:"currentActions"`
	CurrentStep    int               `json:"currentStep"`
	TotalSteps     int               `json:"totalSteps"`
	Version        string            `json:"version"`
}

// Deployment steps
type DeploymentStep struct {
	Action string `json:"action"`
	App    string `json:"app"`
}

// EventSubscription is described here:
// https://github.com/mesosphere/marathon/blob/master/REST.md#event-subscriptions
type EventSubscription struct {
	CallbackURL  string   `json:"CallbackUrl"`
	ClientIP     string   `json:"ClientIp"`
	EventType    string   `json:"eventType"`
	CallbackURLs []string `json:"CallbackUrls"`
}

// ServerInfo is described here:
// https://mesosphere.github.io/marathon/docs/rest-api.html#server-info

type InfoEventSub struct {
	Type          string   `json:"type"`
	HttpEndpoints []string `json:"http_endpoints,omitempty"`
}

type InfoMarathonConfig struct {
	Checkpoint        bool   `json:"checkpoint"`
	Executor          string `json:"executor"`
	FailoverTimeout   int    `json:"failover_timeout"`
	HA                bool   `json:"ha"`
	Hostname          string `json:"hostname"`
	LocalPortMin      int    `json:"local_port_min"`
	LocalPortMax      int    `json:"local_port_max"`
	Master            string `json:"master"`
	MesosRole         string `json:"mesos_role"`
	MesosUser         string `json:"mesos-user"`
	RecInitialDelay   int    `json:"reconciliation_initial_delay"`
	RecInterval       int    `json:"reconciliation_interval"`
	TaskLaunchTimeout int    `json:"task_launch_timeout"`
}

type InfoHttpConfig struct {
	AssetsPath string `json:"assets_path,omitempty"`
	HttpPort   int    `json:"http_port"`
	HttpsPort  int    `json:"https_port"`
}

type InfoZkConfig struct {
	Zk              string           `json:"zk"`
	ZkFutureTimeout *ZkFutureTimeout `json:"zk_future_timeout"`
	ZkHosts         string           `json:"zk_hosts"`
	ZkPath          string           `json:"zk_path"`
	ZkState         string           `json:"zk_state"`
	ZkTimeout       int              `json:"zk_timeout"`
}

type ZkFutureTimeout struct {
	Duration int `json:"duration"`
}
<|endoftext|>


<commit_before>package stockfighter

import (
	"fmt"
	"time"
)

type OrderType int

const (
	Limit OrderType = iota
	Market
	FillOrKill
	ImmediateOrCancel
)

type Symbol struct {
	Symbol string
	Name   string
}

type Order struct {
	Price    uint64
	Quantity uint64 `json:"qty"`
	IsBuy    bool
}

type OrderBook struct {
	Venue     string
	Symbol    string
	Asks      []Order
	Bids      []Order
	TimeStamp time.Time
}

type Fill struct {
	Price     uint64
	Quantity  uint64    `json:"qty"`
	TimeStamp time.Time `json:"ts"`
}

type OrderState struct {
	Venue            string
	Symbol           string
	Price            uint64
	OriginalQuantity uint64 `json:"originalQty"`
	Quantity         uint64 `json:"qty"`
	Direction        string
	Type             OrderType
	Id               uint64
	Account          string
	Timestamp        time.Time `json:"ts"`
	Fills            []Fill
	TotalFilled      uint64
	Open             bool
}

type Quote struct {
	Venue     string
	Symbol    string
	Bid       uint64
	BidSize   uint64
	BidDepth  uint64
	Ask       uint64
	AskSize   uint64
	AskDepth  uint64
	Last      uint64
	LastSize  uint64
	LastTrade time.Time
	QuoteTime time.Time
}

type Execution struct {
	Account          string
	Venue            string
	Symbol           string
	Order            OrderState
	StandingId       uint64
	Price            uint64
	Filled           uint64
	FilledAt         time.Time
	StandingComplete bool
	IncomingComplete bool
}

var orderTypes = [...]string{
	Limit:             "limit",
	Market:            "market",
	FillOrKill:        "fill-or-kill",
	ImmediateOrCancel: "immediate-or-cancel",
}

func (o *OrderType) MarshalText() ([]byte, error) {
	return []byte(orderTypes[o]), nil
}

var orderTypeMap = map[string]OrderType{
	"limit":               Limit,
	"market":              Market,
	"fill-or-kill":        FillOrKill,
	"immediate-or-cancel": ImmediateOrCancel,
}

func (o *OrderType) UnmarshalText(text []byte) error {
	typ, ok := orderTypeMap[string(text)]
	if ok {
		*o = typ
		return nil
	}
	return fmt.Errorf("Unknown order type: %s", text)
}
<commit_msg>Fix OrderType MarshalText<commit_after>package stockfighter

import (
	"fmt"
	"time"
)

type OrderType int

const (
	Limit OrderType = iota
	Market
	FillOrKill
	ImmediateOrCancel
)

type Symbol struct {
	Symbol string
	Name   string
}

type Order struct {
	Price    uint64
	Quantity uint64 `json:"qty"`
	IsBuy    bool
}

type OrderBook struct {
	Venue     string
	Symbol    string
	Asks      []Order
	Bids      []Order
	TimeStamp time.Time
}

type Fill struct {
	Price     uint64
	Quantity  uint64    `json:"qty"`
	TimeStamp time.Time `json:"ts"`
}

type OrderState struct {
	Venue            string
	Symbol           string
	Price            uint64
	OriginalQuantity uint64 `json:"originalQty"`
	Quantity         uint64 `json:"qty"`
	Direction        string
	Type             OrderType
	Id               uint64
	Account          string
	Timestamp        time.Time `json:"ts"`
	Fills            []Fill
	TotalFilled      uint64
	Open             bool
}

type Quote struct {
	Venue     string
	Symbol    string
	Bid       uint64
	BidSize   uint64
	BidDepth  uint64
	Ask       uint64
	AskSize   uint64
	AskDepth  uint64
	Last      uint64
	LastSize  uint64
	LastTrade time.Time
	QuoteTime time.Time
}

type Execution struct {
	Account          string
	Venue            string
	Symbol           string
	Order            OrderState
	StandingId       uint64
	Price            uint64
	Filled           uint64
	FilledAt         time.Time
	StandingComplete bool
	IncomingComplete bool
}

var orderTypes = [...]string{
	Limit:             "limit",
	Market:            "market",
	FillOrKill:        "fill-or-kill",
	ImmediateOrCancel: "immediate-or-cancel",
}

func (o OrderType) MarshalText() ([]byte, error) {
	return []byte(orderTypes[o]), nil
}

var orderTypeMap = map[string]OrderType{
	"limit":               Limit,
	"market":              Market,
	"fill-or-kill":        FillOrKill,
	"immediate-or-cancel": ImmediateOrCancel,
}

func (o *OrderType) UnmarshalText(text []byte) error {
	typ, ok := orderTypeMap[string(text)]
	if ok {
		*o = typ
		return nil
	}
	return fmt.Errorf("Unknown order type: %s", text)
}
<|endoftext|>


<commit_before>package onecache

import (
	"errors"
	"time"
)

const (
	EXPIRES_DEFAULT = time.Duration(0)
	EXPIRES_FOREVER = time.Duration(-1)
)

var (
	ErrCacheMiss         = errors.New("Key not found")
	ErrCacheNotStored    = errors.New("Data not stored")
	ErrCacheNotSupported = errors.New("Operation not supported")
)

//identifes a cached piece of data
type Item struct {
	ExpiresAt time.Time
	Data      interface{}
}

//Interface for all onecache store implementations
type CacheStore interface {
	Set(key string, data interface{}, expires time.Duration) error
	Get(key string) (interface{}, error)
}
<commit_msg>Added Delete method to the cache interface..<commit_after>package onecache

import (
	"errors"
	"time"
)

const (
	EXPIRES_DEFAULT = time.Duration(0)
	EXPIRES_FOREVER = time.Duration(-1)
)

var (
	ErrCacheMiss         = errors.New("Key not found")
	ErrCacheNotStored    = errors.New("Data not stored")
	ErrCacheNotSupported = errors.New("Operation not supported")
)

//identifes a cached piece of data
type Item struct {
	ExpiresAt time.Time
	Data      interface{}
}

//Interface for all onecache store implementations
type CacheStore interface {
	Set(key string, data interface{}, expires time.Duration) error
	Get(key string) (interface{}, error)
	Delete(key string) error
}
<|endoftext|>


<commit_before>package telebot

import "strconv"

// Recipient is basically any possible endpoint you can send
// messages to. It's usually a distinct user or a chat.
type Recipient interface {
	// ID of user or group chat, @Username for channel
	Destination() string
}

// User object represents a Telegram user, bot
//
// object represents a group chat if Title is empty.
type User struct {
	ID        int    `json:"id"`
	FirstName string `json:"first_name"`

	LastName string `json:"last_name"`
	Username string `json:"username"`
}

// Destination is internal user ID.
func (u User) Destination() string {
	return strconv.Itoa(u.ID)
}

// Chat object represents a Telegram user, bot or group chat.
// Title for channels and group chats
// Type of chat, can be either “private”, “group”, "supergroup" or “channel”
type Chat struct {
	ID   int64  `json:"id"`
	Type string `json:"type"`

	Title     string `json:"title"`
	FirstName string `json:"first_name"`
	LastName  string `json:"last_name"`
	Username  string `json:"username"`
}

// Destination is internal chat ID.
func (c Chat) Destination() string {
	ret := "@" + c.Username
	if c.Type != "channel" {
		ret = strconv.FormatInt(c.ID, 10)
	}
	return ret
}

// IsGroupChat returns true if chat object represents a group chat.
func (c Chat) IsGroupChat() bool {
	return c.Type != "private"
}

// Update object represents an incoming update.
type Update struct {
	ID      int      `json:"update_id"`
	Payload *Message `json:"message"`

	// optional
	Callback *Callback `json:"callback_query"`
	Query    *Query    `json:"inline_query"`
}

// Thumbnail object represents an image/sticker of a particular size.
type Thumbnail struct {
	File

	Width  int `json:"width"`
	Height int `json:"height"`
}

// Photo object represents a photo with caption.
type Photo struct {
	File

	Thumbnail

	Caption string
}

// Audio object represents an audio file (voice note).
type Audio struct {
	File

	// Duration of the recording in seconds as defined by sender.
	Duration int `json:"duration"`

	// MIME type of the file as defined by sender.
	Mime string `json:"mime_type"`
}

// Document object represents a general file (as opposed to Photo or Audio).
// Telegram users can send files of any type of up to 1.5 GB in size.
type Document struct {
	File

	// Document thumbnail as defined by sender.
	Preview Thumbnail `json:"thumb"`

	// Original filename as defined by sender.
	FileName string `json:"file_name"`

	// MIME type of the file as defined by sender.
	Mime string `json:"mime_type"`
}

// Sticker object represents a WebP image, so-called sticker.
type Sticker struct {
	File

	Width  int `json:"width"`
	Height int `json:"height"`

	// Sticker thumbnail in .webp or .jpg format.
	Preview Thumbnail `json:"thumb"`
}

// Video object represents an MP4-encoded video.
type Video struct {
	Audio

	Width  int `json:"width"`
	Height int `json:"height"`

	// Text description of the video as defined by sender (usually empty).
	Caption string `json:"caption"`

	// Video thumbnail.
	Preview Thumbnail `json:"thumb"`
}

// KeyboardButton represents a button displayed on in a message.
type KeyboardButton struct {
	Text        string `json:"text"`
	URL         string `json:"url,omitempty"`
	Data        string `json:"callback_data,omitempty"`
	InlineQuery string `json:"switch_inline_query,omitempty"`
}

// InlineKeyboardMarkup represents an inline keyboard that appears right next
// to the message it belongs to.
type InlineKeyboardMarkup struct {
	// Array of button rows, each represented by an Array of KeyboardButton objects.
	InlineKeyboard [][]KeyboardButton `json:"inline_keyboard,omitempty"`
}

// Contact object represents a contact to Telegram user
type Contact struct {
	UserID      int    `json:"user_id"`
	PhoneNumber string `json:"phone_number"`
	FirstName   string `json:"first_name"`
	LastName    string `json:"last_name"`
}

// Location object represents geographic position.
type Location struct {
	Latitude  float32 `json:"latitude"`
	Longitude float32 `json:"longitude"`
}

// Callback object represents a query from a callback button in an
// inline keyboard.
type Callback struct {
	ID string `json:"id"`

	// For message sent to channels, Sender may be empty
	Sender User `json:"from"`

	// Message will be set if the button that originated the query
	// was attached to a message sent by a bot.
	Message Message `json:"message"`

	// MessageID will be set if the button was attached to a message
	// sent via the bot in inline mode.
	MessageID string `json:"inline_message_id"`
	Data      string `json:"data"`
}

// CallbackResponse builds a response to an Callback query.
// See also: https://core.telegram.org/bots/api#answerCallbackQuery
type CallbackResponse struct {
	// The ID of the callback to which this is a response.
	// It is not necessary to specify this field manually.
	CallbackID string `json:"callback_query_id"`

	// Text of the notification. If not specified, nothing will be shown to the user.
	Text string `json:"text,omitempty"`

	// (Optional) If true, an alert will be shown by the client instead
	// of a notification at the top of the chat screen. Defaults to false.
	ShowAlert bool `json:"show_alert,omitempty"`
}

// Venue object represents a venue location with name, address and optional foursquare id.
type Venue struct {
	Location      Location `json:"location"`
	Title         string   `json:"title"`
	Address       string   `json:"address"`
	Foursquare_id string   `json:"foursquare_id",omitempty`
}

// MessageEntity
// This object represents one special entity in a text message.
// For example, hashtags, usernames, URLs, etc
type MessageEntity struct {

	// type Type of the entity. Can be mention (@username), hashtag,
	// bot_command, url, email, bold (bold text), italic (italic text),
	// code (monowidth string), pre (monowidth block), text_link (for clickable text URLs),
	// text_mention (for users without usernames)
	Type string `json:"type"`

	// offset Offset in UTF-16 code units to the start of the entity
	Offset int `json:"offset"`

	//length Length of the entity in UTF-16 code units
	Length int `json:"length"`

	//url	Optional. For “text_link” only, url that will be opened after user taps on the text
	Url string `json:"url",omitempty`

	//user	Optional. For “text_mention” only, the mentioned user
	User User `json:"user",omitempty`
}

// ChatMember ,
// This struct contains information about one member of the chat.
type ChatMember struct {
	User   User   `json:"user"`
	Status string `json:"status"`
}

// UserProfilePhotos ,
// This struct represent a user's profile pictures.
//
// Count : Total number of profile pictures the target user has
//
// Photos : Array of Array of PhotoSize	, Requested profile pictures (in up to 4 sizes each)
type UserProfilePhotos struct {
	Count  int       `json:"total_count"`
	Photos [][]Photo `json:"photos"`
}
<commit_msg>URL in CallbackResponse Type added<commit_after>package telebot

import "strconv"

// Recipient is basically any possible endpoint you can send
// messages to. It's usually a distinct user or a chat.
type Recipient interface {
	// ID of user or group chat, @Username for channel
	Destination() string
}

// User object represents a Telegram user, bot
//
// object represents a group chat if Title is empty.
type User struct {
	ID        int    `json:"id"`
	FirstName string `json:"first_name"`

	LastName string `json:"last_name"`
	Username string `json:"username"`
}

// Destination is internal user ID.
func (u User) Destination() string {
	return strconv.Itoa(u.ID)
}

// Chat object represents a Telegram user, bot or group chat.
// Title for channels and group chats
// Type of chat, can be either “private”, “group”, "supergroup" or “channel”
type Chat struct {
	ID   int64  `json:"id"`
	Type string `json:"type"`

	Title     string `json:"title"`
	FirstName string `json:"first_name"`
	LastName  string `json:"last_name"`
	Username  string `json:"username"`
}

// Destination is internal chat ID.
func (c Chat) Destination() string {
	ret := "@" + c.Username
	if c.Type != "channel" {
		ret = strconv.FormatInt(c.ID, 10)
	}
	return ret
}

// IsGroupChat returns true if chat object represents a group chat.
func (c Chat) IsGroupChat() bool {
	return c.Type != "private"
}

// Update object represents an incoming update.
type Update struct {
	ID      int      `json:"update_id"`
	Payload *Message `json:"message"`

	// optional
	Callback *Callback `json:"callback_query"`
	Query    *Query    `json:"inline_query"`
}

// Thumbnail object represents an image/sticker of a particular size.
type Thumbnail struct {
	File

	Width  int `json:"width"`
	Height int `json:"height"`
}

// Photo object represents a photo with caption.
type Photo struct {
	File

	Thumbnail

	Caption string
}

// Audio object represents an audio file (voice note).
type Audio struct {
	File

	// Duration of the recording in seconds as defined by sender.
	Duration int `json:"duration"`

	// MIME type of the file as defined by sender.
	Mime string `json:"mime_type"`
}

// Document object represents a general file (as opposed to Photo or Audio).
// Telegram users can send files of any type of up to 1.5 GB in size.
type Document struct {
	File

	// Document thumbnail as defined by sender.
	Preview Thumbnail `json:"thumb"`

	// Original filename as defined by sender.
	FileName string `json:"file_name"`

	// MIME type of the file as defined by sender.
	Mime string `json:"mime_type"`
}

// Sticker object represents a WebP image, so-called sticker.
type Sticker struct {
	File

	Width  int `json:"width"`
	Height int `json:"height"`

	// Sticker thumbnail in .webp or .jpg format.
	Preview Thumbnail `json:"thumb"`
}

// Video object represents an MP4-encoded video.
type Video struct {
	Audio

	Width  int `json:"width"`
	Height int `json:"height"`

	// Text description of the video as defined by sender (usually empty).
	Caption string `json:"caption"`

	// Video thumbnail.
	Preview Thumbnail `json:"thumb"`
}

// KeyboardButton represents a button displayed on in a message.
type KeyboardButton struct {
	Text        string `json:"text"`
	URL         string `json:"url,omitempty"`
	Data        string `json:"callback_data,omitempty"`
	InlineQuery string `json:"switch_inline_query,omitempty"`
}

// InlineKeyboardMarkup represents an inline keyboard that appears right next
// to the message it belongs to.
type InlineKeyboardMarkup struct {
	// Array of button rows, each represented by an Array of KeyboardButton objects.
	InlineKeyboard [][]KeyboardButton `json:"inline_keyboard,omitempty"`
}

// Contact object represents a contact to Telegram user
type Contact struct {
	UserID      int    `json:"user_id"`
	PhoneNumber string `json:"phone_number"`
	FirstName   string `json:"first_name"`
	LastName    string `json:"last_name"`
}

// Location object represents geographic position.
type Location struct {
	Latitude  float32 `json:"latitude"`
	Longitude float32 `json:"longitude"`
}

// Callback object represents a query from a callback button in an
// inline keyboard.
type Callback struct {
	ID string `json:"id"`

	// For message sent to channels, Sender may be empty
	Sender User `json:"from"`

	// Message will be set if the button that originated the query
	// was attached to a message sent by a bot.
	Message Message `json:"message"`

	// MessageID will be set if the button was attached to a message
	// sent via the bot in inline mode.
	MessageID string `json:"inline_message_id"`
	Data      string `json:"data"`
}

// CallbackResponse builds a response to an Callback query.
// See also: https://core.telegram.org/bots/api#answerCallbackQuery
type CallbackResponse struct {
	// The ID of the callback to which this is a response.
	// It is not necessary to specify this field manually.
	CallbackID string `json:"callback_query_id"`

	// Text of the notification. If not specified, nothing will be shown to the user.
	Text string `json:"text,omitempty"`

	// (Optional) If true, an alert will be shown by the client instead
	// of a notification at the top of the chat screen. Defaults to false.
	ShowAlert bool `json:"show_alert,omitempty"`

	// (Optional) URL that will be opened by the user's client.
	// If you have created a Game and accepted the conditions via @Botfather
	// specify the URL that opens your game
	// note that this will only work if the query comes from a callback_game button.
	// Otherwise, you may use links like telegram.me/your_bot?start=XXXX that open your bot with a parameter.
	URL string `json:"url,omitempty"`
}

// Venue object represents a venue location with name, address and optional foursquare id.
type Venue struct {
	Location      Location `json:"location"`
	Title         string   `json:"title"`
	Address       string   `json:"address"`
	Foursquare_id string   `json:"foursquare_id",omitempty`
}

// MessageEntity
// This object represents one special entity in a text message.
// For example, hashtags, usernames, URLs, etc
type MessageEntity struct {

	// type Type of the entity. Can be mention (@username), hashtag,
	// bot_command, url, email, bold (bold text), italic (italic text),
	// code (monowidth string), pre (monowidth block), text_link (for clickable text URLs),
	// text_mention (for users without usernames)
	Type string `json:"type"`

	// offset Offset in UTF-16 code units to the start of the entity
	Offset int `json:"offset"`

	//length Length of the entity in UTF-16 code units
	Length int `json:"length"`

	//url	Optional. For “text_link” only, url that will be opened after user taps on the text
	Url string `json:"url",omitempty`

	//user	Optional. For “text_mention” only, the mentioned user
	User User `json:"user",omitempty`
}

// ChatMember ,
// This struct contains information about one member of the chat.
type ChatMember struct {
	User   User   `json:"user"`
	Status string `json:"status"`
}

// UserProfilePhotos ,
// This struct represent a user's profile pictures.
//
// Count : Total number of profile pictures the target user has
//
// Photos : Array of Array of PhotoSize	, Requested profile pictures (in up to 4 sizes each)
type UserProfilePhotos struct {
	Count  int       `json:"total_count"`
	Photos [][]Photo `json:"photos"`
}
<|endoftext|>