<commit_before>// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package types

import (
	"go/ast"
	"sort"
)

// TODO(gri) Revisit factory functions - make sure they have all relevant parameters.

// A Type represents a type of Go.
// All types implement the Type interface.
type Type interface {
	// Underlying returns the underlying type of a type.
	Underlying() Type

	// MethodSet returns the method set of a type.
	MethodSet() *MethodSet

	// String returns a string representation of a type.
	String() string
}

// BasicKind describes the kind of basic type.
type BasicKind int

const (
	Invalid BasicKind = iota // type is invalid

	// predeclared types
	Bool
	Int
	Int8
	Int16
	Int32
	Int64
	Uint
	Uint8
	Uint16
	Uint32
	Uint64
	Uintptr
	Float32
	Float64
	Complex64
	Complex128
	String
	UnsafePointer

	// types for untyped values
	UntypedBool
	UntypedInt
	UntypedRune
	UntypedFloat
	UntypedComplex
	UntypedString
	UntypedNil

	// aliases
	Byte = Uint8
	Rune = Int32
)

// BasicInfo is a set of flags describing properties of a basic type.
type BasicInfo int

// Properties of basic types.
const (
	IsBoolean BasicInfo = 1 << iota
	IsInteger
	IsUnsigned
	IsFloat
	IsComplex
	IsString
	IsUntyped

	IsOrdered   = IsInteger | IsFloat | IsString
	IsNumeric   = IsInteger | IsFloat | IsComplex
	IsConstType = IsBoolean | IsNumeric | IsString
)

// A Basic represents a basic type.
type Basic struct {
	kind BasicKind
	info BasicInfo
	size int64 // use DefaultSizeof to get size
	name string
}

// Kind returns the kind of basic type b.
func (b *Basic) Kind() BasicKind { return b.kind }

// Info returns information about properties of basic type b.
func (b *Basic) Info() BasicInfo { return b.info }

// Name returns the name of basic type b.
func (b *Basic) Name() string { return b.name }

// An Array represents an array type.
type Array struct {
	len  int64
	elem Type
}

// NewArray returns a new array type for the given element type and length.
func NewArray(elem Type, len int64) *Array { return &Array{len, elem} }

// Len returns the length of array a.
func (a *Array) Len() int64 { return a.len }

// Elem returns element type of array a.
func (a *Array) Elem() Type { return a.elem }

// A Slice represents a slice type.
type Slice struct {
	elem Type
}

// NewSlice returns a new slice type for the given element type.
func NewSlice(elem Type) *Slice { return &Slice{elem} }

// Elem returns the element type of slice s.
func (s *Slice) Elem() Type { return s.elem }

// A Struct represents a struct type.
type Struct struct {
	fields []*Var
	tags   []string // field tags; nil if there are no tags
	// TODO(gri) access to offsets is not threadsafe - fix this
	offsets []int64         // field offsets in bytes, lazily initialized
	mset    cachedMethodSet // method set, lazily initialized
}

// NewStruct returns a new struct with the given fields and corresponding field tags.
// If a field with index i has a tag, tags[i] must be that tag, but len(tags) may be
// only as long as required to hold the tag with the largest index i. Consequently,
// if no field has a tag, tags may be nil.
func NewStruct(fields []*Var, tags []string) *Struct {
	return &Struct{fields: fields, tags: tags}
}

// NumFields returns the number of fields in the struct (including blank and anonymous fields).
func (s *Struct) NumFields() int { return len(s.fields) }

// Field returns the i'th field for 0 <= i < NumFields().
func (s *Struct) Field(i int) *Var { return s.fields[i] }

// Tag returns the i'th field tag for 0 <= i < NumFields().
func (s *Struct) Tag(i int) string {
	if i < len(s.tags) {
		return s.tags[i]
	}
	return ""
}

// A Pointer represents a pointer type.
type Pointer struct {
	base Type            // element type
	mset cachedMethodSet // method set, lazily initialized
}

// NewPointer returns a new pointer type for the given element (base) type.
func NewPointer(elem Type) *Pointer { return &Pointer{base: elem} }

// Elem returns the element type for the given pointer p.
func (p *Pointer) Elem() Type { return p.base }

// A Tuple represents an ordered list of variables; a nil *Tuple is a valid (empty) tuple.
// Tuples are used as components of signatures and to represent the type of multiple
// assignments; they are not first class types of Go.
type Tuple struct {
	vars []*Var
}

// NewTuple returns a new tuple for the given variables.
func NewTuple(x ...*Var) *Tuple {
	if len(x) > 0 {
		return &Tuple{x}
	}
	return nil
}

// Len returns the number variables of tuple t.
func (t *Tuple) Len() int {
	if t != nil {
		return len(t.vars)
	}
	return 0
}

// At returns the i'th variable of tuple t.
func (t *Tuple) At(i int) *Var { return t.vars[i] }

// A Signature represents a (non-builtin) function or method type.
type Signature struct {
	scope      *Scope // function scope, always present
	recv       *Var   // nil if not a method
	params     *Tuple // (incoming) parameters from left to right; or nil
	results    *Tuple // (outgoing) results from left to right; or nil
	isVariadic bool   // true if the last parameter's type is of the form ...T
}

// NewSignature returns a new function type for the given receiver, parameters,
// and results, either of which may be nil. If isVariadic is set, the function
// is variadic, it must have at least one parameter, and the last parameter
// must be of unnamed slice type.
func NewSignature(scope *Scope, recv *Var, params, results *Tuple, isVariadic bool) *Signature {
	// TODO(gri) Should we rely on the correct (non-nil) incoming scope
	//           or should this function allocate and populate a scope?
	if isVariadic {
		n := params.Len()
		if n == 0 {
			panic("types.NewSignature: variadic function must have at least one parameter")
		}
		if _, ok := params.At(n - 1).typ.(*Slice); !ok {
			panic("types.NewSignature: variadic parameter must be of unnamed slice type")
		}
	}
	return &Signature{scope, recv, params, results, isVariadic}
}

// Recv returns the receiver of signature s (if a method), or nil if a
// function.
//
// For an abstract method, Recv returns the enclosing interface either
// as a *Named or an *Interface.  Due to embedding, an interface may
// contain methods whose receiver type is a different interface.
func (s *Signature) Recv() *Var { return s.recv }

// Params returns the parameters of signature s, or nil.
func (s *Signature) Params() *Tuple { return s.params }

// Results returns the results of signature s, or nil.
func (s *Signature) Results() *Tuple { return s.results }

// IsVariadic reports whether the signature s is variadic.
func (s *Signature) IsVariadic() bool { return s.isVariadic }

// An Interface represents an interface type.
type Interface struct {
	methods []*Func  // explicitly declared methods
	types   []*Named // explicitly embedded types

	allMethods []*Func         // ordered list of methods declared with or embedded in this interface (TODO(gri): replace with mset)
	mset       cachedMethodSet // method set for interface, lazily initialized
}

// NewInterface returns a new interface for the given methods.
func NewInterface(methods []*Func) *Interface {
	// TODO(gri) should provide receiver to all methods
	sort.Sort(byUniqueMethodName(methods))
	return &Interface{methods: methods, allMethods: methods}
}

// NumMethods returns the number of methods of interface t.
func (t *Interface) NumMethods() int { return len(t.allMethods) }

// Method returns the i'th method of interface t for 0 <= i < t.NumMethods().
func (t *Interface) Method(i int) *Func { return t.allMethods[i] }

// A Map represents a map type.
type Map struct {
	key, elem Type
}

// NewMap returns a new map for the given key and element types.
func NewMap(key, elem Type) *Map {
	return &Map{key, elem}
}

// Key returns the key type of map m.
func (m *Map) Key() Type { return m.key }

// Elem returns the element type of map m.
func (m *Map) Elem() Type { return m.elem }

// A Chan represents a channel type.
type Chan struct {
	dir  ast.ChanDir
	elem Type
}

// NewChan returns a new channel type for the given direction and element type.
func NewChan(dir ast.ChanDir, elem Type) *Chan {
	return &Chan{dir, elem}
}

// Dir returns the direction of channel c.
func (c *Chan) Dir() ast.ChanDir { return c.dir }

// Elem returns the element type of channel c.
func (c *Chan) Elem() Type { return c.elem }

// A Named represents a named type.
type Named struct {
	obj        *TypeName       // corresponding declared object
	underlying Type            // possibly a *Named if !complete; never a *Named if complete
	complete   bool            // if set, the underlying type has been determined
	methods    []*Func         // methods declared for this type (not the method set of this type)
	mset       cachedMethodSet // method set for this type, lazily initialized
}

// NewNamed returns a new named type for the given type name, underlying type, and associated methods.
// The underlying type must exist and not be a *Named, and the methods scope entries must be *Func
// objects if the scope is not empty.
func NewNamed(obj *TypeName, underlying Type, methods []*Func) *Named {
	if _, ok := underlying.(*Named); ok {
		panic("types.NewNamed: underlying type must not be *Named")
	}
	typ := &Named{obj: obj, underlying: underlying, complete: true, methods: methods}
	if obj.typ == nil {
		obj.typ = typ
	}
	return typ
}

// TypeName returns the type name for the named type t.
func (t *Named) Obj() *TypeName { return t.obj }

// NumMethods returns the number of explicit methods whose receiver is named type t.
func (t *Named) NumMethods() int { return len(t.methods) }

// Method returns the i'th method of named type t for 0 <= i < t.NumMethods().
func (t *Named) Method(i int) *Func { return t.methods[i] }

// Implementations for Type methods.

func (t *Basic) Underlying() Type     { return t }
func (t *Array) Underlying() Type     { return t }
func (t *Slice) Underlying() Type     { return t }
func (t *Struct) Underlying() Type    { return t }
func (t *Pointer) Underlying() Type   { return t }
func (t *Tuple) Underlying() Type     { return t }
func (t *Signature) Underlying() Type { return t }
func (t *Builtin) Underlying() Type   { return t }
func (t *Interface) Underlying() Type { return t }
func (t *Map) Underlying() Type       { return t }
func (t *Chan) Underlying() Type      { return t }
func (t *Named) Underlying() Type     { return t.underlying }

func (t *Basic) MethodSet() *MethodSet     { return &emptyMethodSet }
func (t *Array) MethodSet() *MethodSet     { return &emptyMethodSet }
func (t *Slice) MethodSet() *MethodSet     { return &emptyMethodSet }
func (t *Struct) MethodSet() *MethodSet    { return t.mset.of(t) }
func (t *Pointer) MethodSet() *MethodSet   { return t.mset.of(t) }
func (t *Tuple) MethodSet() *MethodSet     { return &emptyMethodSet }
func (t *Signature) MethodSet() *MethodSet { return &emptyMethodSet }
func (t *Builtin) MethodSet() *MethodSet   { return &emptyMethodSet }
func (t *Interface) MethodSet() *MethodSet { return t.mset.of(t) }
func (t *Map) MethodSet() *MethodSet       { return &emptyMethodSet }
func (t *Chan) MethodSet() *MethodSet      { return &emptyMethodSet }
func (t *Named) MethodSet() *MethodSet     { return t.mset.of(t) }

func (t *Basic) String() string     { return typeString(t) }
func (t *Array) String() string     { return typeString(t) }
func (t *Slice) String() string     { return typeString(t) }
func (t *Struct) String() string    { return typeString(t) }
func (t *Pointer) String() string   { return typeString(t) }
func (t *Tuple) String() string     { return typeString(t) }
func (t *Signature) String() string { return typeString(t) }
func (t *Builtin) String() string   { return typeString(t) }
func (t *Interface) String() string { return typeString(t) }
func (t *Map) String() string       { return typeString(t) }
func (t *Chan) String() string      { return typeString(t) }
func (t *Named) String() string     { return typeString(t) }
<commit_msg>go.tools/go/types: cache method set for pointer-to-named in the Named.<commit_after>// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package types

import (
	"go/ast"
	"sort"
)

// TODO(gri) Revisit factory functions - make sure they have all relevant parameters.

// A Type represents a type of Go.
// All types implement the Type interface.
type Type interface {
	// Underlying returns the underlying type of a type.
	Underlying() Type

	// MethodSet returns the method set of a type.
	MethodSet() *MethodSet

	// String returns a string representation of a type.
	String() string
}

// BasicKind describes the kind of basic type.
type BasicKind int

const (
	Invalid BasicKind = iota // type is invalid

	// predeclared types
	Bool
	Int
	Int8
	Int16
	Int32
	Int64
	Uint
	Uint8
	Uint16
	Uint32
	Uint64
	Uintptr
	Float32
	Float64
	Complex64
	Complex128
	String
	UnsafePointer

	// types for untyped values
	UntypedBool
	UntypedInt
	UntypedRune
	UntypedFloat
	UntypedComplex
	UntypedString
	UntypedNil

	// aliases
	Byte = Uint8
	Rune = Int32
)

// BasicInfo is a set of flags describing properties of a basic type.
type BasicInfo int

// Properties of basic types.
const (
	IsBoolean BasicInfo = 1 << iota
	IsInteger
	IsUnsigned
	IsFloat
	IsComplex
	IsString
	IsUntyped

	IsOrdered   = IsInteger | IsFloat | IsString
	IsNumeric   = IsInteger | IsFloat | IsComplex
	IsConstType = IsBoolean | IsNumeric | IsString
)

// A Basic represents a basic type.
type Basic struct {
	kind BasicKind
	info BasicInfo
	size int64 // use DefaultSizeof to get size
	name string
}

// Kind returns the kind of basic type b.
func (b *Basic) Kind() BasicKind { return b.kind }

// Info returns information about properties of basic type b.
func (b *Basic) Info() BasicInfo { return b.info }

// Name returns the name of basic type b.
func (b *Basic) Name() string { return b.name }

// An Array represents an array type.
type Array struct {
	len  int64
	elem Type
}

// NewArray returns a new array type for the given element type and length.
func NewArray(elem Type, len int64) *Array { return &Array{len, elem} }

// Len returns the length of array a.
func (a *Array) Len() int64 { return a.len }

// Elem returns element type of array a.
func (a *Array) Elem() Type { return a.elem }

// A Slice represents a slice type.
type Slice struct {
	elem Type
}

// NewSlice returns a new slice type for the given element type.
func NewSlice(elem Type) *Slice { return &Slice{elem} }

// Elem returns the element type of slice s.
func (s *Slice) Elem() Type { return s.elem }

// A Struct represents a struct type.
type Struct struct {
	fields []*Var
	tags   []string // field tags; nil if there are no tags
	// TODO(gri) access to offsets is not threadsafe - fix this
	offsets []int64         // field offsets in bytes, lazily initialized
	mset    cachedMethodSet // method set, lazily initialized
}

// NewStruct returns a new struct with the given fields and corresponding field tags.
// If a field with index i has a tag, tags[i] must be that tag, but len(tags) may be
// only as long as required to hold the tag with the largest index i. Consequently,
// if no field has a tag, tags may be nil.
func NewStruct(fields []*Var, tags []string) *Struct {
	return &Struct{fields: fields, tags: tags}
}

// NumFields returns the number of fields in the struct (including blank and anonymous fields).
func (s *Struct) NumFields() int { return len(s.fields) }

// Field returns the i'th field for 0 <= i < NumFields().
func (s *Struct) Field(i int) *Var { return s.fields[i] }

// Tag returns the i'th field tag for 0 <= i < NumFields().
func (s *Struct) Tag(i int) string {
	if i < len(s.tags) {
		return s.tags[i]
	}
	return ""
}

// A Pointer represents a pointer type.
type Pointer struct {
	base Type            // element type
	mset cachedMethodSet // method set, lazily initialized
}

// NewPointer returns a new pointer type for the given element (base) type.
func NewPointer(elem Type) *Pointer { return &Pointer{base: elem} }

// Elem returns the element type for the given pointer p.
func (p *Pointer) Elem() Type { return p.base }

// A Tuple represents an ordered list of variables; a nil *Tuple is a valid (empty) tuple.
// Tuples are used as components of signatures and to represent the type of multiple
// assignments; they are not first class types of Go.
type Tuple struct {
	vars []*Var
}

// NewTuple returns a new tuple for the given variables.
func NewTuple(x ...*Var) *Tuple {
	if len(x) > 0 {
		return &Tuple{x}
	}
	return nil
}

// Len returns the number variables of tuple t.
func (t *Tuple) Len() int {
	if t != nil {
		return len(t.vars)
	}
	return 0
}

// At returns the i'th variable of tuple t.
func (t *Tuple) At(i int) *Var { return t.vars[i] }

// A Signature represents a (non-builtin) function or method type.
type Signature struct {
	scope      *Scope // function scope, always present
	recv       *Var   // nil if not a method
	params     *Tuple // (incoming) parameters from left to right; or nil
	results    *Tuple // (outgoing) results from left to right; or nil
	isVariadic bool   // true if the last parameter's type is of the form ...T
}

// NewSignature returns a new function type for the given receiver, parameters,
// and results, either of which may be nil. If isVariadic is set, the function
// is variadic, it must have at least one parameter, and the last parameter
// must be of unnamed slice type.
func NewSignature(scope *Scope, recv *Var, params, results *Tuple, isVariadic bool) *Signature {
	// TODO(gri) Should we rely on the correct (non-nil) incoming scope
	//           or should this function allocate and populate a scope?
	if isVariadic {
		n := params.Len()
		if n == 0 {
			panic("types.NewSignature: variadic function must have at least one parameter")
		}
		if _, ok := params.At(n - 1).typ.(*Slice); !ok {
			panic("types.NewSignature: variadic parameter must be of unnamed slice type")
		}
	}
	return &Signature{scope, recv, params, results, isVariadic}
}

// Recv returns the receiver of signature s (if a method), or nil if a
// function.
//
// For an abstract method, Recv returns the enclosing interface either
// as a *Named or an *Interface.  Due to embedding, an interface may
// contain methods whose receiver type is a different interface.
func (s *Signature) Recv() *Var { return s.recv }

// Params returns the parameters of signature s, or nil.
func (s *Signature) Params() *Tuple { return s.params }

// Results returns the results of signature s, or nil.
func (s *Signature) Results() *Tuple { return s.results }

// IsVariadic reports whether the signature s is variadic.
func (s *Signature) IsVariadic() bool { return s.isVariadic }

// An Interface represents an interface type.
type Interface struct {
	methods []*Func  // explicitly declared methods
	types   []*Named // explicitly embedded types

	allMethods []*Func         // ordered list of methods declared with or embedded in this interface (TODO(gri): replace with mset)
	mset       cachedMethodSet // method set for interface, lazily initialized
}

// NewInterface returns a new interface for the given methods.
func NewInterface(methods []*Func) *Interface {
	// TODO(gri) should provide receiver to all methods
	sort.Sort(byUniqueMethodName(methods))
	return &Interface{methods: methods, allMethods: methods}
}

// NumMethods returns the number of methods of interface t.
func (t *Interface) NumMethods() int { return len(t.allMethods) }

// Method returns the i'th method of interface t for 0 <= i < t.NumMethods().
func (t *Interface) Method(i int) *Func { return t.allMethods[i] }

// A Map represents a map type.
type Map struct {
	key, elem Type
}

// NewMap returns a new map for the given key and element types.
func NewMap(key, elem Type) *Map {
	return &Map{key, elem}
}

// Key returns the key type of map m.
func (m *Map) Key() Type { return m.key }

// Elem returns the element type of map m.
func (m *Map) Elem() Type { return m.elem }

// A Chan represents a channel type.
type Chan struct {
	dir  ast.ChanDir
	elem Type
}

// NewChan returns a new channel type for the given direction and element type.
func NewChan(dir ast.ChanDir, elem Type) *Chan {
	return &Chan{dir, elem}
}

// Dir returns the direction of channel c.
func (c *Chan) Dir() ast.ChanDir { return c.dir }

// Elem returns the element type of channel c.
func (c *Chan) Elem() Type { return c.elem }

// A Named represents a named type.
type Named struct {
	obj         *TypeName       // corresponding declared object
	underlying  Type            // possibly a *Named if !complete; never a *Named if complete
	complete    bool            // if set, the underlying type has been determined
	methods     []*Func         // methods declared for this type (not the method set of this type)
	mset, pmset cachedMethodSet // method set for T, *T, lazily initialized
}

// NewNamed returns a new named type for the given type name, underlying type, and associated methods.
// The underlying type must exist and not be a *Named, and the methods scope entries must be *Func
// objects if the scope is not empty.
func NewNamed(obj *TypeName, underlying Type, methods []*Func) *Named {
	if _, ok := underlying.(*Named); ok {
		panic("types.NewNamed: underlying type must not be *Named")
	}
	typ := &Named{obj: obj, underlying: underlying, complete: true, methods: methods}
	if obj.typ == nil {
		obj.typ = typ
	}
	return typ
}

// TypeName returns the type name for the named type t.
func (t *Named) Obj() *TypeName { return t.obj }

// NumMethods returns the number of explicit methods whose receiver is named type t.
func (t *Named) NumMethods() int { return len(t.methods) }

// Method returns the i'th method of named type t for 0 <= i < t.NumMethods().
func (t *Named) Method(i int) *Func { return t.methods[i] }

// Implementations for Type methods.

func (t *Basic) Underlying() Type     { return t }
func (t *Array) Underlying() Type     { return t }
func (t *Slice) Underlying() Type     { return t }
func (t *Struct) Underlying() Type    { return t }
func (t *Pointer) Underlying() Type   { return t }
func (t *Tuple) Underlying() Type     { return t }
func (t *Signature) Underlying() Type { return t }
func (t *Builtin) Underlying() Type   { return t }
func (t *Interface) Underlying() Type { return t }
func (t *Map) Underlying() Type       { return t }
func (t *Chan) Underlying() Type      { return t }
func (t *Named) Underlying() Type     { return t.underlying }

func (t *Basic) MethodSet() *MethodSet  { return &emptyMethodSet }
func (t *Array) MethodSet() *MethodSet  { return &emptyMethodSet }
func (t *Slice) MethodSet() *MethodSet  { return &emptyMethodSet }
func (t *Struct) MethodSet() *MethodSet { return t.mset.of(t) }
func (t *Pointer) MethodSet() *MethodSet {
	if named, _ := t.base.(*Named); named != nil {
		// Avoid recomputing mset(*T) for each distinct Pointer
		// instance whose underlying type is a named type.
		return named.pmset.of(t)
	}
	return t.mset.of(t)
}
func (t *Tuple) MethodSet() *MethodSet     { return &emptyMethodSet }
func (t *Signature) MethodSet() *MethodSet { return &emptyMethodSet }
func (t *Builtin) MethodSet() *MethodSet   { return &emptyMethodSet }
func (t *Interface) MethodSet() *MethodSet { return t.mset.of(t) }
func (t *Map) MethodSet() *MethodSet       { return &emptyMethodSet }
func (t *Chan) MethodSet() *MethodSet      { return &emptyMethodSet }
func (t *Named) MethodSet() *MethodSet     { return t.mset.of(t) }

func (t *Basic) String() string     { return typeString(t) }
func (t *Array) String() string     { return typeString(t) }
func (t *Slice) String() string     { return typeString(t) }
func (t *Struct) String() string    { return typeString(t) }
func (t *Pointer) String() string   { return typeString(t) }
func (t *Tuple) String() string     { return typeString(t) }
func (t *Signature) String() string { return typeString(t) }
func (t *Builtin) String() string   { return typeString(t) }
func (t *Interface) String() string { return typeString(t) }
func (t *Map) String() string       { return typeString(t) }
func (t *Chan) String() string      { return typeString(t) }
func (t *Named) String() string     { return typeString(t) }
<|endoftext|>


<commit_before>package dataProcess

import (
	"../autils"
	"database/sql"
	"github.com/gin-gonic/gin"
	"net/http"
	"time"
)

// 作弊请求数据处理
func BrowswersCount(c *gin.Context, db *sql.DB) {
	position := "left"
	cd := cheatData{}

	date := c.Query("date")
	if date == "" {
		date = autils.GetCurrentData(time.Now().AddDate(0, 0, -1))
	}

	q, _ := c.Get("conditions")
	sDate := autils.AnaSigleDate(q)
	s := date
	if sDate != "" {
		s = sDate
	}
	cd.Columns = []tStruct{{
		"浏览器",
		"type",
		position,
	}, {
		"请求数",
		"num",
		position,
	}}

	infos := getBrowsersInfo(db, s)

	cd.Rows = infos

	c.JSON(http.StatusOK, gin.H{
		"status": 0,
		"msg":    "ok",
		"data":   cd,
	})
}

func getBrowsersInfo(db *sql.DB, date string) []cRowsInfo {
	sqlStr := "select type, num from browsers where date = '" + date + "' order by num desc"
	rows, err := db.Query(sqlStr)
	autils.ErrHadle(err)

	var name string
	var num int
	cri := cRowsInfo{}
	criArr := []cRowsInfo{}
	for rows.Next() {
		err := rows.Scan(&name, &num)
		autils.ErrHadle(err)
		cri.Domain = name
		cri.Num = num
		criArr = append(criArr, cri)
	}
	err = rows.Err()
	autils.ErrHadle(err)

	defer rows.Close()
	return criArr
}
<commit_msg>update browsers struct.<commit_after>package dataProcess

import (
	"../autils"
	"database/sql"
	"github.com/gin-gonic/gin"
	"net/http"
	"time"
)

type bsRowsInfo struct {
	Type string `json:"type"`
	Num  int    `json:"num"`
}

type browsersData struct {
	Columns []tStruct    `json:"columns"`
	Rows    []bsRowsInfo `json:"rows"`
}

// 作弊请求数据处理
func BrowswersCount(c *gin.Context, db *sql.DB) {
	position := "left"
	cd := browsersData{}

	date := c.Query("date")
	if date == "" {
		date = autils.GetCurrentData(time.Now().AddDate(0, 0, -1))
	}

	q, _ := c.Get("conditions")
	sDate := autils.AnaSigleDate(q)
	s := date
	if sDate != "" {
		s = sDate
	}
	cd.Columns = []tStruct{{
		"浏览器",
		"type",
		position,
	}, {
		"请求数",
		"num",
		position,
	}}

	infos := getBrowsersInfo(db, s)

	cd.Rows = infos

	c.JSON(http.StatusOK, gin.H{
		"status": 0,
		"msg":    "ok",
		"data":   cd,
	})
}

func getBrowsersInfo(db *sql.DB, date string) []bsRowsInfo {
	sqlStr := "select type, num from browsers where date = '" + date + "' order by num desc"
	rows, err := db.Query(sqlStr)
	autils.ErrHadle(err)

	var name string
	var num int
	cri := bsRowsInfo{}
	criArr := []bsRowsInfo{}
	for rows.Next() {
		err := rows.Scan(&name, &num)
		autils.ErrHadle(err)
		cri.Type = name
		cri.Num = num
		criArr = append(criArr, cri)
	}
	err = rows.Err()
	autils.ErrHadle(err)

	defer rows.Close()
	return criArr
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"regexp"
	"strings"

	"gopkg.in/h2non/filetype.v1"
	"github.com/nlopes/slack"
)

func GetURLBytes(url string) (result []byte, err error) {
	client := &http.Client{}

	req, err := http.NewRequest("GET", url, nil)
	if err != nil {
		log.Fatalln(err)
	}

	req.Header.Set("User-Agent", "Mozilla/5.0 (https://github.com/tb0hdan/torpedo; tb0hdan@gmail.com) Go-http-client/1.1")

	resp, err := client.Do(req)
	if err != nil {
		log.Fatalln(err)
	}

	defer resp.Body.Close()
	result, err = ioutil.ReadAll(resp.Body)
	if err != nil {
		log.Fatalln(err)
	}
	return
}

func GetMIMEType(fname string) (mimetype, extension string, is_image bool, err error) {
	// Read a file
	buf, err := ioutil.ReadFile(fname)

	if err != nil {
		fmt.Printf("GetMIMEType could not read file %s", fname)
		return
	}

	// We only have to pass the file header = first 261 bytes
	head := buf[:261]

	kind, err := filetype.Match(head)
	if err != nil {
		fmt.Printf("Mimetype unkwown: %s", err)
		return
	}

	mimetype = kind.MIME.Value
	extension = kind.Extension
	is_image = filetype.IsImage(head)
	return
}

func DownloadToTmp(url string) (fname string, mimetype string, is_image bool, err error) {
	img, _ := GetURLBytes(url)
	tmpfile, err := ioutil.TempFile("/tmp", "torpedo")
	if err != nil {
		log.Fatal(err)
	}

	if _, err := tmpfile.Write(img); err != nil {
		log.Fatal(err)
	}

	if err := tmpfile.Close(); err != nil {
		log.Fatal(err)
	}
	fname = tmpfile.Name()
	mimetype, _, is_image, err = GetMIMEType(fname)
	return
}

func GetRequestedFeature(full_command string, usage...string) (requestedFeature, command, message string) {
	// Support multiple commands within single function
	requestedFeature = strings.Split(full_command, " ")[0]
	command = strings.TrimSpace(strings.TrimLeft(full_command, requestedFeature))
	if usage[0] == "" {
		message = fmt.Sprintf("Usage: %s string\n", requestedFeature)
	} else {
		message = fmt.Sprintf("Usage: %s %s\n", requestedFeature, usage[0])
	}
	return
}

func ChannelsUploadImage(channels []string, fname, fpath, ftype string, api *slack.Client) {
	parameters := slack.FileUploadParameters{File: fpath, Filetype: ftype,
		Filename: fname, Title: fname,
		Channels: channels}
	api.UploadFile(parameters)
}

func UnformatURL(url string) (newurl string) {
	re := regexp.MustCompile("[<>]")
	newurl = strings.TrimSpace(re.ReplaceAllString(url, ""))
	return
}

func FileExists(fpath string) (exists bool) {
	// TODO: Find a way around this, os.IsExist expects an error and we don't have one yet
	exists = true
	if _, err := os.Stat(fpath); os.IsNotExist(err) {
		exists = false
	}
	return
}
<commit_msg>usage oops<commit_after>package main

import (
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"regexp"
	"strings"

	"gopkg.in/h2non/filetype.v1"
	"github.com/nlopes/slack"
)

func GetURLBytes(url string) (result []byte, err error) {
	client := &http.Client{}

	req, err := http.NewRequest("GET", url, nil)
	if err != nil {
		log.Fatalln(err)
	}

	req.Header.Set("User-Agent", "Mozilla/5.0 (https://github.com/tb0hdan/torpedo; tb0hdan@gmail.com) Go-http-client/1.1")

	resp, err := client.Do(req)
	if err != nil {
		log.Fatalln(err)
	}

	defer resp.Body.Close()
	result, err = ioutil.ReadAll(resp.Body)
	if err != nil {
		log.Fatalln(err)
	}
	return
}

func GetMIMEType(fname string) (mimetype, extension string, is_image bool, err error) {
	// Read a file
	buf, err := ioutil.ReadFile(fname)

	if err != nil {
		fmt.Printf("GetMIMEType could not read file %s", fname)
		return
	}

	// We only have to pass the file header = first 261 bytes
	head := buf[:261]

	kind, err := filetype.Match(head)
	if err != nil {
		fmt.Printf("Mimetype unkwown: %s", err)
		return
	}

	mimetype = kind.MIME.Value
	extension = kind.Extension
	is_image = filetype.IsImage(head)
	return
}

func DownloadToTmp(url string) (fname string, mimetype string, is_image bool, err error) {
	img, _ := GetURLBytes(url)
	tmpfile, err := ioutil.TempFile("/tmp", "torpedo")
	if err != nil {
		log.Fatal(err)
	}

	if _, err := tmpfile.Write(img); err != nil {
		log.Fatal(err)
	}

	if err := tmpfile.Close(); err != nil {
		log.Fatal(err)
	}
	fname = tmpfile.Name()
	mimetype, _, is_image, err = GetMIMEType(fname)
	return
}

func GetRequestedFeature(full_command string, usage...string) (requestedFeature, command, message string) {
	// Support multiple commands within single function
	requestedFeature = strings.Split(full_command, " ")[0]
	command = strings.TrimSpace(strings.TrimLeft(full_command, requestedFeature))
	if len(usage) == 0 {
		message = fmt.Sprintf("Usage: %s string\n", requestedFeature)
	} else {
		message = fmt.Sprintf("Usage: %s %s\n", requestedFeature, usage[0])
	}
	return
}

func ChannelsUploadImage(channels []string, fname, fpath, ftype string, api *slack.Client) {
	parameters := slack.FileUploadParameters{File: fpath, Filetype: ftype,
		Filename: fname, Title: fname,
		Channels: channels}
	api.UploadFile(parameters)
}

func UnformatURL(url string) (newurl string) {
	re := regexp.MustCompile("[<>]")
	newurl = strings.TrimSpace(re.ReplaceAllString(url, ""))
	return
}

func FileExists(fpath string) (exists bool) {
	// TODO: Find a way around this, os.IsExist expects an error and we don't have one yet
	exists = true
	if _, err := os.Stat(fpath); os.IsNotExist(err) {
		exists = false
	}
	return
}
<|endoftext|>


<commit_before>package airbreak

import (
  "bytes"
  "runtime"
  "errors"
  "log"
  "os"
  "text/template"
  "net/http"
  "sync"
)

var ApiKey string =  ""
var Endpoint string = "https://airbreak.io/notifier_api/v2/notices.xml"
var tmpl = template.Must(template.New("error").Parse(source))
var Verbose = false

var (
  badResponse = errors.New("Bad response")
  apiKeyMissing = errors.New("Please set the airbreak.ApiKey before doing calls")
  dunno     = []byte("???")
  centerDot = []byte("·")
  dot       = []byte(".")
)

type Line struct {
  Function string
  File string
  Line int
}

// stack implements Stack, skipping N frames
func stacktrace(skip int) (lines []Line) {
  for i := skip; ; i++ {
    pc, file, line, ok := runtime.Caller(i)
    if !ok {
      break
    }

    item := Line{ string(function(pc)), string(file), line}
    lines = append(lines, item )
  }
  return
}

var channel chan map[string]interface{}
var once sync.Once

// function returns, if possible, the name of the function containing the PC.
func function(pc uintptr) []byte {
  fn := runtime.FuncForPC(pc)
  if fn == nil {
    return dunno
  }
  name := []byte(fn.Name())
  // The name includes the path name to the package, which is unnecessary
  // since the file name is already included.  Plus, it has center dots.
  // That is, we see
  //  runtime/debug.*T·ptrmethod
  // and want
  //  *T.ptrmethod
  if period := bytes.Index(name, dot); period >= 0 {
    name = name[period+1:]
  }
  name = bytes.Replace(name, centerDot, dot, -1)
  return name
}

func initChannel() {
  channel = make(chan map[string]interface{}, 100)
  go worker()
}

func worker() {
  for params := range channel {
    buffer := bytes.NewBufferString("")

    if err := tmpl.Execute(buffer, params); err != nil {
      log.Printf("Airbreak error: %s", err)
      continue
    }

    response, err := http.Post(Endpoint, "text/xml", buffer)
    response.Body.Close()

    if err != nil {
      log.Printf("Airbreak error: %s", err)
      continue
    }

    if Verbose {
      log.Printf("Airbreak post: %s", params["Error"])
    }

  }

  return
}

func ErrorRequest(e error, request *http.Request) error {
  once.Do(initChannel)

  if ApiKey == "" {
    return apiKeyMissing
  }

  params := map[string]interface{} {
    "Error": e,
    "ApiKey": ApiKey,
    "ErrorName": e.Error(),
    "Request": request,
  }

  pwd, err := os.Getwd()
  if err == nil {
    params["Pwd"] = pwd
  }

  params["Backtrace"] = stacktrace(3)

  channel <- params
  return nil
}

func Error(e error) error {
  return ErrorRequest(e, nil)
}

const source = `
<?xml version="1.0" encoding="UTF-8"?>
<notice version="2.0">
  <api-key>{{ .ApiKey }}</api-key>
  <notifier>
    <name>Airbrake Golang</name>
    <version>0.0.1</version>
    <url>http://airbrake.io</url>
  </notifier>
  <error>
    <class>{{ html .ErrorName }}</class>
    <message>test{{ with .ErrorMessage }}{{html .}}{{ end }}</message>
    <backtrace>
      {{ range .Backtrace }}
      <line method="{{.Function}}" file="{{.File}}" number="{{.Line}}"/>
      {{ end }}
    </backtrace>
  </error>
  {{ with .Request }}
  <request>
    <url>{{ .URL }}</url>
    <component/>
    <action/>
    <cgi-data>
    </cgi-data>
  </request>
  {{ end }}
  <server-environment>
    <environment-name>production</environment-name>
    <project-root>{{ .Pwd }}</project-root>
  </server-environment>
</notice>`
<commit_msg>stylistic update<commit_after>package airbreak

import (
  "bytes"
  "runtime"
  "errors"
  "log"
  "os"
  "text/template"
  "net/http"
  "sync"
)

var (
  ApiKey    =  ""
  Endpoint  = "https://airbreak.io/notifier_api/v2/notices.xml"
  Verbose   = false

  badResponse   = errors.New("Bad response")
  apiKeyMissing = errors.New("Please set the airbreak.ApiKey before doing calls")
  dunno         = []byte("???")
  centerDot     = []byte("·")
  dot           = []byte(".")
  tmpl          = template.Must(template.New("error").Parse(source))
)

type Line struct {
  Function string
  File string
  Line int
}

// stack implements Stack, skipping N frames
func stacktrace(skip int) (lines []Line) {
  for i := skip; ; i++ {
    pc, file, line, ok := runtime.Caller(i)
    if !ok {
      break
    }

    item := Line{ string(function(pc)), string(file), line}
    lines = append(lines, item )
  }
  return
}

var channel chan map[string]interface{}
var once sync.Once

// function returns, if possible, the name of the function containing the PC.
func function(pc uintptr) []byte {
  fn := runtime.FuncForPC(pc)
  if fn == nil {
    return dunno
  }
  name := []byte(fn.Name())
  // The name includes the path name to the package, which is unnecessary
  // since the file name is already included.  Plus, it has center dots.
  // That is, we see
  //  runtime/debug.*T·ptrmethod
  // and want
  //  *T.ptrmethod
  if period := bytes.Index(name, dot); period >= 0 {
    name = name[period+1:]
  }
  name = bytes.Replace(name, centerDot, dot, -1)
  return name
}

func initChannel() {
  channel = make(chan map[string]interface{}, 100)
  go worker()
}

func worker() {
  for params := range channel {
    buffer := bytes.NewBufferString("")

    if err := tmpl.Execute(buffer, params); err != nil {
      log.Printf("Airbreak error: %s", err)
      continue
    }

    response, err := http.Post(Endpoint, "text/xml", buffer)
    response.Body.Close()

    if err != nil {
      log.Printf("Airbreak error: %s", err)
      continue
    }

    if Verbose {
      log.Printf("Airbreak post: %s", params["Error"])
    }

  }

  return
}

func ErrorRequest(e error, request *http.Request) error {
  once.Do(initChannel)

  if ApiKey == "" {
    return apiKeyMissing
  }

  params := map[string]interface{} {
    "Error": e,
    "ApiKey": ApiKey,
    "ErrorName": e.Error(),
    "Request": request,
  }

  pwd, err := os.Getwd()
  if err == nil {
    params["Pwd"] = pwd
  }

  params["Backtrace"] = stacktrace(3)

  channel <- params
  return nil
}

func Error(e error) error {
  return ErrorRequest(e, nil)
}

const source = `
<?xml version="1.0" encoding="UTF-8"?>
<notice version="2.0">
  <api-key>{{ .ApiKey }}</api-key>
  <notifier>
    <name>Airbrake Golang</name>
    <version>0.0.1</version>
    <url>http://airbrake.io</url>
  </notifier>
  <error>
    <class>{{ html .ErrorName }}</class>
    <message>test{{ with .ErrorMessage }}{{html .}}{{ end }}</message>
    <backtrace>
      {{ range .Backtrace }}
      <line method="{{.Function}}" file="{{.File}}" number="{{.Line}}"/>
      {{ end }}
    </backtrace>
  </error>
  {{ with .Request }}
  <request>
    <url>{{ .URL }}</url>
    <component/>
    <action/>
    <cgi-data>
    </cgi-data>
  </request>
  {{ end }}
  <server-environment>
    <environment-name>production</environment-name>
    <project-root>{{ .Pwd }}</project-root>
  </server-environment>
</notice>`
<|endoftext|>


<commit_before>package app

import (
	"fmt"
	"github.com/timeredbull/tsuru/log"
	"os/exec"
	"strconv"
	"strings"
)

type Unit struct {
	Type              string
	Name              string
	Machine           int
	Ip                string
	AgentState        string `yaml:"agent-state"`
	MachineAgentState string
	InstanceState     string
	InstanceId        string
	app               *App
}

func (u *Unit) Destroy() ([]byte, error) {
	cmd := exec.Command("juju", "destroy-service", "-e", u.app.JujuEnv, u.Name)
	log.Printf("destroying %s with name %s", u.Type, u.Name)
	out, err := cmd.CombinedOutput()
	if err != nil {
		return out, err
	}
	cmd = exec.Command("juju", "terminate-machine", "-e", u.app.JujuEnv, strconv.Itoa(u.Machine))
	return cmd.CombinedOutput()
}

func (u *Unit) Command(cmds ...string) ([]byte, error) {
	c := exec.Command("juju", "ssh", "-o", "StrictHostKeyChecking no", "-e", u.app.JujuEnv, strconv.Itoa(u.Machine))
	c.Args = append(c.Args, cmds...)
	log.Printf("executing %s on %s", strings.Join(cmds, " "), u.Name)
	return c.CombinedOutput()
}

func (u *Unit) GetName() string {
	return u.Name
}

func (u *Unit) GetIp() string {
	return u.Ip
}

func (u *Unit) ExecuteHook(hook string) ([]byte, error) {
	cmd := fmt.Sprintf("/var/lib/tsuru/hooks/%s", hook)
	output, err := u.Command(cmd)
	log.Print(string(output))
	return output, err
}
<commit_msg>api/app: added log to Unit.Destroy<commit_after>package app

import (
	"fmt"
	"github.com/timeredbull/tsuru/log"
	"os/exec"
	"strconv"
	"strings"
)

type Unit struct {
	Type              string
	Name              string
	Machine           int
	Ip                string
	AgentState        string `yaml:"agent-state"`
	MachineAgentState string
	InstanceState     string
	InstanceId        string
	app               *App
}

func (u *Unit) Destroy() ([]byte, error) {
	cmd := exec.Command("juju", "destroy-service", "-e", u.app.JujuEnv, u.Name)
	log.Printf("destroying %s with name %s", u.Type, u.Name)
	out, err := cmd.CombinedOutput()
	log.Printf(string(out))
	if err != nil {
		return out, err
	}
	cmd = exec.Command("juju", "terminate-machine", "-e", u.app.JujuEnv, strconv.Itoa(u.Machine))
	return cmd.CombinedOutput()
}

func (u *Unit) Command(cmds ...string) ([]byte, error) {
	c := exec.Command("juju", "ssh", "-o", "StrictHostKeyChecking no", "-e", u.app.JujuEnv, strconv.Itoa(u.Machine))
	c.Args = append(c.Args, cmds...)
	log.Printf("executing %s on %s", strings.Join(cmds, " "), u.Name)
	return c.CombinedOutput()
}

func (u *Unit) GetName() string {
	return u.Name
}

func (u *Unit) GetIp() string {
	return u.Ip
}

func (u *Unit) ExecuteHook(hook string) ([]byte, error) {
	cmd := fmt.Sprintf("/var/lib/tsuru/hooks/%s", hook)
	output, err := u.Command(cmd)
	log.Print(string(output))
	return output, err
}
<|endoftext|>


<commit_before>// Copyright 2015 Robert S. Gerus. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package bot

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

	"github.com/cloudflare/gokabinet/kt"

	cfg "github.com/arachnist/gorepost/config"
	"github.com/arachnist/gorepost/irc"
)

var k *kt.Conn

type seenRecord struct {
	Network string
	Target  string
	Action  string
	Time    time.Time
	Text    string
}

func seenrecord(output chan irc.Message, msg irc.Message) {
	if msg.Params == nil {
		return
	}

	v := seenRecord{
		Network: msg.Context["Network"],
		Target:  msg.Params[0],
		Action:  msg.Command,
		Time:    time.Now(),
		Text:    msg.Trailing,
	}

	b, err := json.Marshal(v)
	if err != nil {
		log.Println("Context:", msg.Context, "json marshal of seen record failed:", err)
		return
	}

	err = k.Set("seen/"+msg.Prefix.Name, b)
	if err != nil {
		log.Println("Context:", msg.Context, "error recording seen record:", err)
	}
}

func seen(output chan irc.Message, msg irc.Message) {
	var v seenRecord
	var r string

	args := strings.Split(msg.Trailing, " ")

	if args[0] != ":seen" {
		return
	}
	if len(args) < 2 {
		return
	}

	b, err := k.GetBytes("seen/" + args[1])
	if err == kt.ErrNotFound {
		output <- reply(msg, cfg.LookupString(msg.Context, "NotSeenMessage"))
		return
	} else if err != nil {
		output <- reply(msg, fmt.Sprint("error getting record for", args[1], err))
		return
	}

	err = json.Unmarshal(b, &v)
	if err != nil {
		output <- reply(msg, fmt.Sprint("error unmarshaling record for", args[1], err))
		return
	}

	r = fmt.Sprintf("Last seen %s on %s/%s at %v ", args[1], v.Network, v.Target, v.Time.Round(time.Minute))

	switch v.Action {
	case "JOIN":
		r += "joining"
	case "PART":
		r += fmt.Sprint("leaving: ", v.Text)
	case "QUIT":
		r += fmt.Sprint("quitting with reasson: ", v.Text)
	case "PRIVMSG":
		r += fmt.Sprint("saying: ", v.Text)
	}

	output <- reply(msg, r)
}

func init() {
	var err error
	var ktHost = "127.0.0.1"
	var ktPort = 1337

	log.Println("SEEN: connecting to KT")
	k, err = kt.NewConn(ktHost, ktPort, 4, 2*time.Second)
	if err != nil {
		log.Println("error connecting to kyoto tycoon", err)
		return
	}

	log.Println("Registering callbacks")
	addCallback("PRIVMSG", "seen", seen)
	addCallback("PRIVMSG", "seenrecord", seenrecord)
	addCallback("JOIN", "seenrecord", seenrecord)
	addCallback("PART", "seenrecord", seenrecord)
	addCallback("QUIT", "seenrecord", seenrecord)
	addCallback("NOTICE", "seenrecord", seenrecord)
}
<commit_msg>Rounding to seconds makes more sense.<commit_after>// Copyright 2015 Robert S. Gerus. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package bot

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

	"github.com/cloudflare/gokabinet/kt"

	cfg "github.com/arachnist/gorepost/config"
	"github.com/arachnist/gorepost/irc"
)

var k *kt.Conn

type seenRecord struct {
	Network string
	Target  string
	Action  string
	Time    time.Time
	Text    string
}

func seenrecord(output chan irc.Message, msg irc.Message) {
	if msg.Params == nil {
		return
	}

	v := seenRecord{
		Network: msg.Context["Network"],
		Target:  msg.Params[0],
		Action:  msg.Command,
		Time:    time.Now(),
		Text:    msg.Trailing,
	}

	b, err := json.Marshal(v)
	if err != nil {
		log.Println("Context:", msg.Context, "json marshal of seen record failed:", err)
		return
	}

	err = k.Set("seen/"+msg.Prefix.Name, b)
	if err != nil {
		log.Println("Context:", msg.Context, "error recording seen record:", err)
	}
}

func seen(output chan irc.Message, msg irc.Message) {
	var v seenRecord
	var r string

	args := strings.Split(msg.Trailing, " ")

	if args[0] != ":seen" {
		return
	}
	if len(args) < 2 {
		return
	}

	b, err := k.GetBytes("seen/" + args[1])
	if err == kt.ErrNotFound {
		output <- reply(msg, cfg.LookupString(msg.Context, "NotSeenMessage"))
		return
	} else if err != nil {
		output <- reply(msg, fmt.Sprint("error getting record for", args[1], err))
		return
	}

	err = json.Unmarshal(b, &v)
	if err != nil {
		output <- reply(msg, fmt.Sprint("error unmarshaling record for", args[1], err))
		return
	}

	r = fmt.Sprintf("Last seen %s on %s/%s at %v ", args[1], v.Network, v.Target, v.Time.Round(time.Second))

	switch v.Action {
	case "JOIN":
		r += "joining"
	case "PART":
		r += fmt.Sprint("leaving: ", v.Text)
	case "QUIT":
		r += fmt.Sprint("quitting with reasson: ", v.Text)
	case "PRIVMSG":
		r += fmt.Sprint("saying: ", v.Text)
	}

	output <- reply(msg, r)
}

func init() {
	var err error
	var ktHost = "127.0.0.1"
	var ktPort = 1337

	log.Println("SEEN: connecting to KT")
	k, err = kt.NewConn(ktHost, ktPort, 4, 2*time.Second)
	if err != nil {
		log.Println("error connecting to kyoto tycoon", err)
		return
	}

	log.Println("Registering callbacks")
	addCallback("PRIVMSG", "seen", seen)
	addCallback("PRIVMSG", "seenrecord", seenrecord)
	addCallback("JOIN", "seenrecord", seenrecord)
	addCallback("PART", "seenrecord", seenrecord)
	addCallback("QUIT", "seenrecord", seenrecord)
	addCallback("NOTICE", "seenrecord", seenrecord)
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"html/template"
	"image/jpeg"
	"io"
	"log"
	"net/http"
	"os"
	"path/filepath"
	"strconv"
)

var uploadTemplate = template.Must(template.ParseFiles("upload.html"))
var thumbnailTemplate = template.Must(template.ParseFiles("thumbnails.html"))

var staticURL = "/static/"
var staticDir = "static/"
var mediaURL = "/media/"
var mediaDir = "media/"

// TODO errors are currently ignored
var curDir, _ = os.Getwd()

// Common attrs
var attrs = map[string]interface{}{
	"static_url": staticURL,
}

func uploadHandler(w http.ResponseWriter, req *http.Request) {
	if req.Method == "POST" {
		displayThumbnails(w, req)
		return
	}
	uploadTemplate.Execute(w, attrs)
}

func faviconHandler(w http.ResponseWriter, req *http.Request) {
	w.Write([]byte(""))
}

type Thumbnail struct {
	Quality int
	Size    string
	URL     string
}

func displayThumbnails(w http.ResponseWriter, req *http.Request) {
	// contentType := req.Header.Get("Content-Type")
	// log.Println("Content type:", contentType)

	// TODO If image is in the request body, use:
	// img, imgErr := jpeg.Decode(req.Body)
	rawFile, header, fileErr := req.FormFile("image")
	if fileErr != nil {
		io.WriteString(w, fmt.Sprintf("Error while parsing: %s", fileErr))
		return
	}

	// TODO Handle arbitrary image types
	img, imgErr := jpeg.Decode(rawFile)
	if imgErr != nil {
		io.WriteString(w, fmt.Sprintf("Error while decoding: %s", imgErr))
		return
	}

	// TODO Shrink the original image down to thumbnail size (at most 200px)

	// Create thumbnails for a range of qualities
	// TODO Use option
	qualities := []int{100, 90, 75, 65, 50, 35, 25, 10}
	files := make([]*Thumbnail, len(qualities))

	// TODO Create the image directory if it does not exist
	for index, quality := range qualities {
		// TODO Errors are ignored
		filename := fmt.Sprintf("_%d.jpg", quality)
		fullPath := filepath.Join(curDir, mediaDir, filename)
		url := filepath.Join(mediaURL, filename)

		// TODO Never write the file to disk - simply base64 encode
		output, _ := os.Create(fullPath)
		defer output.Close()

		jpeg.Encode(output, img, &jpeg.Options{quality})
		files[index] = &Thumbnail{Quality: quality, URL: url}

		info, infoErr := output.Stat()
		if infoErr == nil {
			files[index].Size = strconv.FormatFloat(float64(info.Size())/1000.0, 'f', 1, 64) + " kb"
			log.Println("File size:", files[index].Size)
		}
	}

	// TODO Easiest way to extend another map
	templateAttrs := make(map[string]interface{})
	for key, value := range attrs {
		templateAttrs[key] = value
	}
	templateAttrs["Filename"] = header.Filename
	templateAttrs["Files"] = files

	thumbnailTemplate.Execute(w, templateAttrs)
}

func main() {
	// Static files: images, css, javascript
	http.Handle(staticURL, http.StripPrefix(staticURL, http.FileServer(http.Dir(filepath.Join(curDir, staticDir)))))

	// Uploaded files
	http.Handle(mediaURL, http.StripPrefix(mediaURL, http.FileServer(http.Dir(filepath.Join(curDir, mediaDir)))))

	// TODO determine address from a flag
	address := ":8080"

	http.HandleFunc("/", uploadHandler)
	http.HandleFunc("/favicon.ico", faviconHandler)
	log.Printf("Server starting on address: %s\n", address)

	serveErr := http.ListenAndServe(address, nil)
	if serveErr != nil {
		log.Println(serveErr)
	}
}
<commit_msg>Server address can be specified with the flag '-address'<commit_after>package main

import (
	"flag"
	"fmt"
	"html/template"
	"image/jpeg"
	"io"
	"log"
	"net/http"
	"os"
	"path/filepath"
	"strconv"
)

// Templates
var uploadTemplate = template.Must(template.ParseFiles("upload.html"))
var thumbnailTemplate = template.Must(template.ParseFiles("thumbnails.html"))

// Directories
var staticURL = "/static/"
var staticDir = "static/"
var mediaURL = "/media/"
var mediaDir = "media/"

// TODO errors are currently ignored
var curDir, _ = os.Getwd()

// Server Address
var address string

// Common attrs
var attrs = map[string]interface{}{
	"static_url": staticURL,
}

func uploadHandler(w http.ResponseWriter, req *http.Request) {
	if req.Method == "POST" {
		displayThumbnails(w, req)
		return
	}
	uploadTemplate.Execute(w, attrs)
}

func faviconHandler(w http.ResponseWriter, req *http.Request) {
	w.Write([]byte(""))
}

type Thumbnail struct {
	Quality int
	Size    string
	URL     string
}

func displayThumbnails(w http.ResponseWriter, req *http.Request) {
	// contentType := req.Header.Get("Content-Type")
	// log.Println("Content type:", contentType)

	// TODO If image is in the request body, use:
	// img, imgErr := jpeg.Decode(req.Body)
	rawFile, header, fileErr := req.FormFile("image")
	if fileErr != nil {
		io.WriteString(w, fmt.Sprintf("Error while parsing: %s", fileErr))
		return
	}

	// TODO Handle arbitrary image types
	img, imgErr := jpeg.Decode(rawFile)
	if imgErr != nil {
		io.WriteString(w, fmt.Sprintf("Error while decoding: %s", imgErr))
		return
	}

	// TODO Shrink the original image down to thumbnail size (at most 200px)

	// Create thumbnails for a range of qualities
	// TODO Use option
	qualities := []int{100, 90, 75, 65, 50, 35, 25, 10}
	files := make([]*Thumbnail, len(qualities))

	// TODO Create the image directory if it does not exist
	for index, quality := range qualities {
		// TODO Errors are ignored
		filename := fmt.Sprintf("_%d.jpg", quality)
		fullPath := filepath.Join(curDir, mediaDir, filename)
		url := filepath.Join(mediaURL, filename)

		// TODO Never write the file to disk - simply base64 encode
		output, _ := os.Create(fullPath)
		defer output.Close()

		jpeg.Encode(output, img, &jpeg.Options{quality})
		files[index] = &Thumbnail{Quality: quality, URL: url}

		info, infoErr := output.Stat()
		if infoErr == nil {
			files[index].Size = strconv.FormatFloat(float64(info.Size())/1000.0, 'f', 1, 64) + " kb"
			log.Println("File size:", files[index].Size)
		}
	}

	// TODO Easiest way to extend another map
	templateAttrs := make(map[string]interface{})
	for key, value := range attrs {
		templateAttrs[key] = value
	}
	templateAttrs["Filename"] = header.Filename
	templateAttrs["Files"] = files

	thumbnailTemplate.Execute(w, templateAttrs)
}

func main() {
	// Parse the given server address
	flag.StringVar(&address, "address", ":8080", "address for the server")
	flag.Parse()

	// Static files: images, css, javascript
	http.Handle(staticURL, http.StripPrefix(staticURL, http.FileServer(http.Dir(filepath.Join(curDir, staticDir)))))

	// Uploaded files
	http.Handle(mediaURL, http.StripPrefix(mediaURL, http.FileServer(http.Dir(filepath.Join(curDir, mediaDir)))))

	http.HandleFunc("/", uploadHandler)
	http.HandleFunc("/favicon.ico", faviconHandler)
	log.Printf("Server starting on address: %s\n", address)

	serveErr := http.ListenAndServe(address, nil)
	if serveErr != nil {
		log.Println(serveErr)
	}
}
<|endoftext|>


<commit_before>package provider

import (
	"reflect"
	"testing"

	"github.com/keel-hq/keel/types"
	"github.com/keel-hq/keel/util/image"
	testingUtils "github.com/keel-hq/keel/util/testing"
)

func mustParse(i string) *image.Reference {
	ref, err := image.Parse(i)
	if err != nil {
		panic(err)
	}
	return ref
}

func Test_appendImage(t *testing.T) {
	type args struct {
		images []*types.TrackedImage
		new    *types.TrackedImage
	}
	tests := []struct {
		name string
		args args
		want []*types.TrackedImage
	}{
		{
			name: "new image",
			args: args{
				images: []*types.TrackedImage{},
				new:    testingUtils.GetTrackedImage("karolisr/webhook-demo:latest"),
			},
			want: []*types.TrackedImage{testingUtils.GetTrackedImage("karolisr/webhook-demo:latest")},
		},
		{
			name: "new semver",
			args: args{
				images: []*types.TrackedImage{},
				new:    testingUtils.GetTrackedImage("karolisr/webhook-demo:1.2.3"),
			},
			want: []*types.TrackedImage{
				testingUtils.GetTrackedImage("karolisr/webhook-demo:1.2.3"),
			},
		},
		{
			name: "new semver with prerelease",
			args: args{
				images: []*types.TrackedImage{
					testingUtils.GetTrackedImage("karolisr/webhook-demo:1.2.3"),
				},
				new: testingUtils.GetTrackedImage("karolisr/webhook-demo:1.5.0-dev"),
			},
			want: []*types.TrackedImage{
				&types.TrackedImage{
					Image: mustParse("karolisr/webhook-demo:1.5.0-dev"),
					SemverPreReleaseTags: map[string]string{
						"dev": "1.5.0-dev",
					},
					Meta: make(map[string]string),
				},
			},
		},
		{
			name: "new semver with both prereleases",
			args: args{
				images: []*types.TrackedImage{
					&types.TrackedImage{
						Image: mustParse("karolisr/webhook-demo:1.2.3-prod"),
						SemverPreReleaseTags: map[string]string{
							"prod": "1.2.3-prod",
						},
						Meta: make(map[string]string),
					},
				},
				new: testingUtils.GetTrackedImage("karolisr/webhook-demo:1.5.0-dev"),
			},
			want: []*types.TrackedImage{
				&types.TrackedImage{
					Image: mustParse("karolisr/webhook-demo:1.5.0-dev"),
					SemverPreReleaseTags: map[string]string{
						"dev":  "1.5.0-dev",
						"prod": "1.2.3-prod",
					},
					Meta: make(map[string]string),
				},
			},
		},
		{
			name: "new semver with previous non-semver tag",
			args: args{
				images: []*types.TrackedImage{
					&types.TrackedImage{
						Image:                mustParse("karolisr/webhook-demo:build-xx"),
						SemverPreReleaseTags: make(map[string]string),
						Meta:                 make(map[string]string),
					},
				},
				new: testingUtils.GetTrackedImage("karolisr/webhook-demo:1.5.0-dev"),
			},
			want: []*types.TrackedImage{
				&types.TrackedImage{
					Image:                mustParse("karolisr/webhook-demo:build-xx"),
					SemverPreReleaseTags: make(map[string]string),
					Meta:                 make(map[string]string),
				},
				&types.TrackedImage{
					Image: mustParse("karolisr/webhook-demo:1.5.0-dev"),
					SemverPreReleaseTags: map[string]string{
						"dev": "1.5.0-dev",
					},
					Meta: make(map[string]string),
				},
			},
		},
		{
			name: "mixed versions",
			args: args{
				images: []*types.TrackedImage{
					&types.TrackedImage{
						Image:                mustParse("karolisr/webhook-demo:latest"),
						SemverPreReleaseTags: make(map[string]string),
						Meta:                 make(map[string]string),
					},
					&types.TrackedImage{
						Image:                mustParse("karolisr/webhook-demo:build-foo"),
						SemverPreReleaseTags: make(map[string]string),
						Meta:                 make(map[string]string),
					},
					&types.TrackedImage{
						Image: mustParse("karolisr/webhook-demo:1.5.0-prod"),
						SemverPreReleaseTags: map[string]string{
							"prod": "1.5.0-prod",
						},
						Meta: make(map[string]string),
					},
				},
				new: testingUtils.GetTrackedImage("karolisr/webhook-demo:1.7.0-dev"),
			},
			want: []*types.TrackedImage{
				&types.TrackedImage{
					Image:                mustParse("karolisr/webhook-demo:latest"),
					SemverPreReleaseTags: make(map[string]string),
					Meta:                 make(map[string]string),
				},
				&types.TrackedImage{
					Image:                mustParse("karolisr/webhook-demo:build-foo"),
					SemverPreReleaseTags: make(map[string]string),
					Meta:                 make(map[string]string),
				},
				&types.TrackedImage{
					Image: mustParse("karolisr/webhook-demo:1.7.0-dev"),
					SemverPreReleaseTags: map[string]string{
						"prod": "1.5.0-prod",
						"dev":  "1.7.0-dev",
					},
					Meta: make(map[string]string),
				},
			},
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			if got := appendImage(tt.args.images, tt.args.new); !reflect.DeepEqual(got, tt.want) {
				t.Errorf("appendImage() = %v, want %v", got, tt.want)
			}
		})
	}
}

func Test_lookupSemverImageIdx(t *testing.T) {
	type args struct {
		images []*types.TrackedImage
		new    *types.TrackedImage
	}
	tests := []struct {
		name  string
		args  args
		want  int
		want1 bool
	}{
		{
			name: "different image",
			args: args{
				images: []*types.TrackedImage{
					testingUtils.GetTrackedImage("karolisr/webhook-demo:1.7.0-dev"),
				},
				new: testingUtils.GetTrackedImage("karolisr/foo:latest"),
			},
			want:  0,
			want1: false,
		},
		{
			name: "empty",
			args: args{
				images: []*types.TrackedImage{},
				new:    testingUtils.GetTrackedImage("karolisr/foo:latest"),
			},
			want:  0,
			want1: false,
		},
		{
			name: "semver second",
			args: args{
				images: []*types.TrackedImage{
					testingUtils.GetTrackedImage("karolisr/webhook-demo:dev"),
					testingUtils.GetTrackedImage("karolisr/webhook-demo:1.7.0-dev"),
					testingUtils.GetTrackedImage("karolisr/webhook-demo:test"),
				},
				new: testingUtils.GetTrackedImage("karolisr/webhook-demo:1.5.0"),
			},
			want:  1,
			want1: true,
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			got, got1 := lookupSemverImageIdx(tt.args.images, tt.args.new)
			if got != tt.want {
				t.Errorf("lookupSemverImageIdx() got = %v, want %v", got, tt.want)
			}
			if got1 != tt.want1 {
				t.Errorf("lookupSemverImageIdx() got1 = %v, want %v", got1, tt.want1)
			}
		})
	}
}
<commit_msg>ammend test<commit_after>package provider

import (
	"reflect"
	"testing"

	"github.com/keel-hq/keel/types"
	"github.com/keel-hq/keel/util/image"
	testingUtils "github.com/keel-hq/keel/util/testing"
)

func mustParse(i string) *image.Reference {
	ref, err := image.Parse(i)
	if err != nil {
		panic(err)
	}
	return ref
}

func Test_appendImage(t *testing.T) {
	type args struct {
		images []*types.TrackedImage
		new    *types.TrackedImage
	}
	tests := []struct {
		name string
		args args
		want []*types.TrackedImage
	}{
		{
			name: "new image",
			args: args{
				images: []*types.TrackedImage{},
				new:    testingUtils.GetTrackedImage("karolisr/webhook-demo:latest"),
			},
			want: []*types.TrackedImage{testingUtils.GetTrackedImage("karolisr/webhook-demo:latest")},
		},
		{
			name: "new semver",
			args: args{
				images: []*types.TrackedImage{},
				new:    testingUtils.GetTrackedImage("karolisr/webhook-demo:1.2.3"),
			},
			want: []*types.TrackedImage{
				testingUtils.GetTrackedImage("karolisr/webhook-demo:1.2.3"),
			},
		},
		{
			name: "new semver with prerelease",
			args: args{
				images: []*types.TrackedImage{
					testingUtils.GetTrackedImage("karolisr/webhook-demo:1.2.3"),
				},
				new: testingUtils.GetTrackedImage("karolisr/webhook-demo:1.5.0-dev"),
			},
			want: []*types.TrackedImage{
				&types.TrackedImage{
					Image: mustParse("karolisr/webhook-demo:1.5.0-dev"),
					SemverPreReleaseTags: map[string]string{
						"dev": "1.5.0-dev",
					},
					Meta: make(map[string]string),
				},
			},
		},
		{
			name: "new semver with both prereleases",
			args: args{
				images: []*types.TrackedImage{
					&types.TrackedImage{
						Image: mustParse("karolisr/webhook-demo:1.2.3-prod"),
						SemverPreReleaseTags: map[string]string{
							"prod": "1.2.3-prod",
						},
						Meta: make(map[string]string),
					},
				},
				new: testingUtils.GetTrackedImage("karolisr/webhook-demo:1.5.0-dev"),
			},
			want: []*types.TrackedImage{
				&types.TrackedImage{
					Image: mustParse("karolisr/webhook-demo:1.5.0-dev"),
					SemverPreReleaseTags: map[string]string{
						"dev":  "1.5.0-dev",
						"prod": "1.2.3-prod",
					},
					Meta: make(map[string]string),
				},
			},
		},
		{
			name: "semver prerelease",
			args: args{
				images: []*types.TrackedImage{},
				new:    testingUtils.GetTrackedImage("karolisr/webhook-demo:1.5.0-dev"),
			},
			want: []*types.TrackedImage{
				&types.TrackedImage{
					Image: mustParse("karolisr/webhook-demo:1.5.0-dev"),
					SemverPreReleaseTags: map[string]string{
						"dev": "1.5.0-dev",
					},
					Meta: make(map[string]string),
				},
			},
		},
		{
			name: "new semver with previous non-semver tag",
			args: args{
				images: []*types.TrackedImage{
					&types.TrackedImage{
						Image:                mustParse("karolisr/webhook-demo:build-xx"),
						SemverPreReleaseTags: make(map[string]string),
						Meta:                 make(map[string]string),
					},
				},
				new: testingUtils.GetTrackedImage("karolisr/webhook-demo:1.5.0-dev"),
			},
			want: []*types.TrackedImage{
				&types.TrackedImage{
					Image:                mustParse("karolisr/webhook-demo:build-xx"),
					SemverPreReleaseTags: make(map[string]string),
					Meta:                 make(map[string]string),
				},
				&types.TrackedImage{
					Image: mustParse("karolisr/webhook-demo:1.5.0-dev"),
					SemverPreReleaseTags: map[string]string{
						"dev": "1.5.0-dev",
					},
					Meta: make(map[string]string),
				},
			},
		},
		{
			name: "mixed versions",
			args: args{
				images: []*types.TrackedImage{
					&types.TrackedImage{
						Image:                mustParse("karolisr/webhook-demo:latest"),
						SemverPreReleaseTags: make(map[string]string),
						Meta:                 make(map[string]string),
					},
					&types.TrackedImage{
						Image:                mustParse("karolisr/webhook-demo:build-foo"),
						SemverPreReleaseTags: make(map[string]string),
						Meta:                 make(map[string]string),
					},
					&types.TrackedImage{
						Image: mustParse("karolisr/webhook-demo:1.5.0-prod"),
						SemverPreReleaseTags: map[string]string{
							"prod": "1.5.0-prod",
						},
						Meta: make(map[string]string),
					},
				},
				new: testingUtils.GetTrackedImage("karolisr/webhook-demo:1.7.0-dev"),
			},
			want: []*types.TrackedImage{
				&types.TrackedImage{
					Image:                mustParse("karolisr/webhook-demo:latest"),
					SemverPreReleaseTags: make(map[string]string),
					Meta:                 make(map[string]string),
				},
				&types.TrackedImage{
					Image:                mustParse("karolisr/webhook-demo:build-foo"),
					SemverPreReleaseTags: make(map[string]string),
					Meta:                 make(map[string]string),
				},
				&types.TrackedImage{
					Image: mustParse("karolisr/webhook-demo:1.7.0-dev"),
					SemverPreReleaseTags: map[string]string{
						"prod": "1.5.0-prod",
						"dev":  "1.7.0-dev",
					},
					Meta: make(map[string]string),
				},
			},
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			if got := appendImage(tt.args.images, tt.args.new); !reflect.DeepEqual(got, tt.want) {
				t.Errorf("appendImage() = %v, want %v", got, tt.want)
			}
		})
	}
}

func Test_lookupSemverImageIdx(t *testing.T) {
	type args struct {
		images []*types.TrackedImage
		new    *types.TrackedImage
	}
	tests := []struct {
		name  string
		args  args
		want  int
		want1 bool
	}{
		{
			name: "different image",
			args: args{
				images: []*types.TrackedImage{
					testingUtils.GetTrackedImage("karolisr/webhook-demo:1.7.0-dev"),
				},
				new: testingUtils.GetTrackedImage("karolisr/foo:latest"),
			},
			want:  0,
			want1: false,
		},
		{
			name: "empty",
			args: args{
				images: []*types.TrackedImage{},
				new:    testingUtils.GetTrackedImage("karolisr/foo:latest"),
			},
			want:  0,
			want1: false,
		},
		{
			name: "semver second",
			args: args{
				images: []*types.TrackedImage{
					testingUtils.GetTrackedImage("karolisr/webhook-demo:dev"),
					testingUtils.GetTrackedImage("karolisr/webhook-demo:1.7.0-dev"),
					testingUtils.GetTrackedImage("karolisr/webhook-demo:test"),
				},
				new: testingUtils.GetTrackedImage("karolisr/webhook-demo:1.5.0"),
			},
			want:  1,
			want1: true,
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			got, got1 := lookupSemverImageIdx(tt.args.images, tt.args.new)
			if got != tt.want {
				t.Errorf("lookupSemverImageIdx() got = %v, want %v", got, tt.want)
			}
			if got1 != tt.want1 {
				t.Errorf("lookupSemverImageIdx() got1 = %v, want %v", got1, tt.want1)
			}
		})
	}
}
<|endoftext|>


<commit_before>package debugstream

import (
	"bufio"
	"fmt"
	"io"
	"strconv"
	"strings"
	"sync"

	"github.com/oakmound/oak/v3/oakerr"
)

var (
	// DefaultCommands to attach to. TODO: init should be lazy.
	DefaultCommands = NewScopedCommands()
)

// ScopedCommands for the debug stream commands.
// Contains a set of scopes that align with oak.Controller.
// Currently can only be attached to a single stream
type ScopedCommands struct {
	sync.Mutex
	attachOnce   sync.Once
	assumedScope int32
	scopes       []int32
	commands     map[int32]map[string]func([]string)
}

// NewScopedCommands creates set of standard help functions.
func NewScopedCommands() *ScopedCommands {
	sc := &ScopedCommands{commands: map[int32]map[string]func([]string){}}
	sc.AddCommand("help", sc.printHelp)
	sc.AddCommand("scope", sc.assumeScope)
	sc.AddCommand("fade", fadeCommands)
	return sc
}

// AttachToStream and start executing the registered commands on input to said stream.
// Currently a given set of scoped commands may be attached once and only once.
func (c *ScopedCommands) AttachToStream(input io.Reader) {
	if c == nil {
		return
	}
	c.attachOnce.Do(
		func() {
			scanner := bufio.NewScanner(input)
			go func() {
				for {
					for scanner.Scan() {

						// TODO: accept interrupts

						tokenString := strings.Fields(scanner.Text())
						if len(tokenString) == 0 {
							continue
						}
						// Attempt to parse the first arg as a scope
						scopeID, err := strToInt32(tokenString[0])

						tokenIDX := 0
						// if there was a scope specified then increment what we care about
						if err == nil {
							_, ok := c.commands[scopeID]
							if !ok {
								fmt.Printf("unknown scopeID %d see correct usage via help\n", scopeID)
								continue
							}
							if len(tokenString) == 1 {
								fmt.Printf("Only provided scopeID %d without see usage via help\n", scopeID)
								continue
							}

							tokenIDX++
							// see if specified
							if fn, ok := c.commands[scopeID][tokenString[tokenIDX]]; ok {
								fn(tokenString[tokenIDX+1:])
								continue
							}
						}

						// assumedscope
						if fn, ok := c.commands[c.assumedScope][tokenString[0]]; ok {
							fn(tokenString[1:])
							continue
						}

						fmt.Println("fall ", tokenString)
						// fallback to scope 0
						if fn, ok := c.commands[0][tokenString[0]]; ok {
							fn(tokenString[1:])
							continue
						}

						fmt.Printf("Unknown command '%s' for scopeID %d see correct usage via help or help %d\n", tokenString[tokenIDX], scopeID, scopeID)

					}
				}
			}()
		})
}

// AddCommand adds a console command to call fn when
// '<s> <args>' is input to the console. fn will be called
// with args split on whitespace.
func (c *ScopedCommands) AddCommand(s string, fn func([]string)) error {
	// We tightly link to controllerIDs here for better or for worse and controllerIDs shall always be > 0
	// This means our unscoped commands are safe when set as 0.
	return c.AddScopedCommand(0, s, fn)
}

// AddCommand adds a console command to call fn when
// '<s> <args>' is input to the console. fn will be called
// with args split on whitespace.
func (c *ScopedCommands) AddScopedCommand(scopeID int32, s string, fn func([]string)) error {
	return c.addCommand(scopeID, s, fn, false)
}

// addCommand for future executions.
func (c *ScopedCommands) addCommand(scopeID int32, s string, fn func([]string), force bool) error {

	c.Lock()
	defer c.Unlock()

	if _, ok := c.commands[scopeID]; !ok {

		c.commands[scopeID] = map[string]func([]string){}
		c.scopes = append(c.scopes, scopeID)
	}

	if _, ok := c.commands[scopeID][s]; ok {
		if !force {
			return oakerr.ExistingElement{
				InputName:   s,
				InputType:   "string",
				Overwritten: false,
			}
		}
	}
	c.commands[scopeID][s] = fn

	return nil
}

// ClearCommand clears an existing debug command for scope with key: <s>
func (c *ScopedCommands) ClearCommand(scopeID int32, s string) {
	_, ok := c.commands[scopeID]
	if !ok {
		return
	}
	delete(c.commands[scopeID], s)
}

// ResetCommands will throw out all existing debug commands from the
// debug console.
func (c *ScopedCommands) ResetCommands() {
	c.commands = map[int32]map[string]func([]string){}
}

// ResetCommandsForScope will throw out all existing debug commands from the
// debug console for hte given scope.
func (c *ScopedCommands) ResetCommandsForScope(scope int32) {
	c.commands[scope] = map[string]func([]string){}
}

// RemoveScope from the command set.
// Usually done on the close of a scope.
func (c *ScopedCommands) RemoveScope(scope int32) {
	delete(c.commands, scope)
	for i := 0; i < len(c.scopes); i++ {
		if c.scopes[i] == scope {
			c.scopes = append(c.scopes[:i], c.scopes[i+1:]...)
			return
		}
	}
}

// GetDebugKeys returns the current debug console commands as a string array
func (c *ScopedCommands) CommandsInScope(scope int32) []string {

	cmds, ok := c.commands[scope]
	if !ok {
		return []string{}
	}

	dkeys := make([]string, len(cmds))
	i := 0
	for k := range cmds {
		dkeys[i] = k
		i++
	}
	return dkeys
}

func (c *ScopedCommands) printHelp(tokenString []string) {
	if len(tokenString) == 0 {
		fmt.Println("help <scopeID> to see commands linked to a window or help 0 to see general commands")
		fmt.Printf("Active Scopes: %v\n", c.scopes)
		return
	}

	scopeID, err := strToInt32(tokenString[0])
	if err != nil {
		fmt.Println("help <scopeID> expects a valid int scope")
		fmt.Printf("you provided %s which errored with %v \n", tokenString[0], err)
		return
	}
	if _, ok := c.commands[scopeID]; !ok {
		fmt.Printf("inactive scope %d see correct usage via help\n", scopeID)
	}
	fmt.Println("Current Assumed Scope:", c.assumedScope)
	fmt.Printf("Commands: %s\n", strings.Join(c.CommandsInScope(scopeID), ","))
}

// assumeScope of the given windowID if possible
// This allows for easier usage of windows when multiple windows exist.
func (c *ScopedCommands) assumeScope(tokenString []string) {
	if len(tokenString) == 0 {
		fmt.Println("assume scope requires a scopeID or -")
		fmt.Printf("Active Scopes: %v\n", c.scopes)
		return
	}

	scopeID, err := strToInt32(tokenString[0])
	if err != nil {
		fmt.Println("assume scope <scopeID> expects a valid int32 scope")
		fmt.Printf("you provided %s which errored with %v \n", tokenString[0], err)
		return
	}
	if _, ok := c.commands[scopeID]; !ok {
		fmt.Printf("inactive scope %d see correct usage via help\n", scopeID)
	}
	c.assumedScope = scopeID
	fmt.Println("assumed scope ", scopeID)
}

// strToInt32 helps align to the window scope handles
func strToInt32(potentialInt string) (int32, error) {
	i64, err := strconv.ParseInt(potentialInt, 10, 32)
	return int32(i64), err
}

// parseTokenAsInt is a convience function for parsing from our string slice of strings
func parseTokenAsInt(tokenString []string, arrIndex int, defaultVal int) int {
	if len(tokenString) > arrIndex {
		tmp, err := strconv.Atoi(tokenString[arrIndex])
		if err == nil {
			return tmp
		}
	}
	return defaultVal
}
<commit_msg>debugstream: expose AddCommand as a package function<commit_after>package debugstream

import (
	"bufio"
	"fmt"
	"io"
	"strconv"
	"strings"
	"sync"

	"github.com/oakmound/oak/v3/oakerr"
)

var (
	// DefaultCommands to attach to. TODO: init should be lazy.
	DefaultCommands = NewScopedCommands()
)

// ScopedCommands for the debug stream commands.
// Contains a set of scopes that align with oak.Controller.
// Currently can only be attached to a single stream
type ScopedCommands struct {
	sync.Mutex
	attachOnce   sync.Once
	assumedScope int32
	scopes       []int32
	commands     map[int32]map[string]func([]string)
}

// NewScopedCommands creates set of standard help functions.
func NewScopedCommands() *ScopedCommands {
	sc := &ScopedCommands{commands: map[int32]map[string]func([]string){}}
	sc.AddCommand("help", sc.printHelp)
	sc.AddCommand("scope", sc.assumeScope)
	sc.AddCommand("fade", fadeCommands)
	return sc
}

// AttachToStream and start executing the registered commands on input to said stream.
// Currently a given set of scoped commands may be attached once and only once.
func (c *ScopedCommands) AttachToStream(input io.Reader) {
	if c == nil {
		return
	}
	c.attachOnce.Do(
		func() {
			scanner := bufio.NewScanner(input)
			go func() {
				for {
					for scanner.Scan() {

						// TODO: accept interrupts

						tokenString := strings.Fields(scanner.Text())
						if len(tokenString) == 0 {
							continue
						}
						// Attempt to parse the first arg as a scope
						scopeID, err := strToInt32(tokenString[0])

						tokenIDX := 0
						// if there was a scope specified then increment what we care about
						if err == nil {
							_, ok := c.commands[scopeID]
							if !ok {
								fmt.Printf("unknown scopeID %d see correct usage via help\n", scopeID)
								continue
							}
							if len(tokenString) == 1 {
								fmt.Printf("Only provided scopeID %d without see usage via help\n", scopeID)
								continue
							}

							tokenIDX++
							// see if specified
							if fn, ok := c.commands[scopeID][tokenString[tokenIDX]]; ok {
								fn(tokenString[tokenIDX+1:])
								continue
							}
						}

						// assumedscope
						if fn, ok := c.commands[c.assumedScope][tokenString[0]]; ok {
							fn(tokenString[1:])
							continue
						}

						fmt.Println("fall ", tokenString)
						// fallback to scope 0
						if fn, ok := c.commands[0][tokenString[0]]; ok {
							fn(tokenString[1:])
							continue
						}

						fmt.Printf("Unknown command '%s' for scopeID %d see correct usage via help or help %d\n", tokenString[tokenIDX], scopeID, scopeID)

					}
				}
			}()
		})
}

// AddCommand adds a console command to call fn when
// '<s> <args>' is input to the console. fn will be called
// with args split on whitespace.
func (c *ScopedCommands) AddCommand(s string, fn func([]string)) error {
	// We tightly link to controllerIDs here for better or for worse and controllerIDs shall always be > 0
	// This means our unscoped commands are safe when set as 0.
	return c.AddScopedCommand(0, s, fn)
}

func AddCommand(s string, fn func([]string)) error {
	return DefaultCommands.AddCommand(s, fn)
}

// AddCommand adds a console command to call fn when
// '<s> <args>' is input to the console. fn will be called
// with args split on whitespace.
func (c *ScopedCommands) AddScopedCommand(scopeID int32, s string, fn func([]string)) error {
	return c.addCommand(scopeID, s, fn, false)
}

func AddScopedCommand(scopeID int32, s string, fn func([]string)) error {
	return DefaultCommands.AddScopedCommand(scopeID, s, fn)
}

// addCommand for future executions.
func (c *ScopedCommands) addCommand(scopeID int32, s string, fn func([]string), force bool) error {

	c.Lock()
	defer c.Unlock()

	if _, ok := c.commands[scopeID]; !ok {

		c.commands[scopeID] = map[string]func([]string){}
		c.scopes = append(c.scopes, scopeID)
	}

	if _, ok := c.commands[scopeID][s]; ok {
		if !force {
			return oakerr.ExistingElement{
				InputName:   s,
				InputType:   "string",
				Overwritten: false,
			}
		}
	}
	c.commands[scopeID][s] = fn

	return nil
}

// ClearCommand clears an existing debug command for scope with key: <s>
func (c *ScopedCommands) ClearCommand(scopeID int32, s string) {
	_, ok := c.commands[scopeID]
	if !ok {
		return
	}
	delete(c.commands[scopeID], s)
}

// ResetCommands will throw out all existing debug commands from the
// debug console.
func (c *ScopedCommands) ResetCommands() {
	c.commands = map[int32]map[string]func([]string){}
}

// ResetCommandsForScope will throw out all existing debug commands from the
// debug console for hte given scope.
func (c *ScopedCommands) ResetCommandsForScope(scope int32) {
	c.commands[scope] = map[string]func([]string){}
}

// RemoveScope from the command set.
// Usually done on the close of a scope.
func (c *ScopedCommands) RemoveScope(scope int32) {
	delete(c.commands, scope)
	for i := 0; i < len(c.scopes); i++ {
		if c.scopes[i] == scope {
			c.scopes = append(c.scopes[:i], c.scopes[i+1:]...)
			return
		}
	}
}

// GetDebugKeys returns the current debug console commands as a string array
func (c *ScopedCommands) CommandsInScope(scope int32) []string {

	cmds, ok := c.commands[scope]
	if !ok {
		return []string{}
	}

	dkeys := make([]string, len(cmds))
	i := 0
	for k := range cmds {
		dkeys[i] = k
		i++
	}
	return dkeys
}

func (c *ScopedCommands) printHelp(tokenString []string) {
	if len(tokenString) == 0 {
		fmt.Println("help <scopeID> to see commands linked to a window or help 0 to see general commands")
		fmt.Printf("Active Scopes: %v\n", c.scopes)
		return
	}

	scopeID, err := strToInt32(tokenString[0])
	if err != nil {
		fmt.Println("help <scopeID> expects a valid int scope")
		fmt.Printf("you provided %s which errored with %v \n", tokenString[0], err)
		return
	}
	if _, ok := c.commands[scopeID]; !ok {
		fmt.Printf("inactive scope %d see correct usage via help\n", scopeID)
	}
	fmt.Println("Current Assumed Scope:", c.assumedScope)
	fmt.Printf("Commands: %s\n", strings.Join(c.CommandsInScope(scopeID), ","))
}

// assumeScope of the given windowID if possible
// This allows for easier usage of windows when multiple windows exist.
func (c *ScopedCommands) assumeScope(tokenString []string) {
	if len(tokenString) == 0 {
		fmt.Println("assume scope requires a scopeID or -")
		fmt.Printf("Active Scopes: %v\n", c.scopes)
		return
	}

	scopeID, err := strToInt32(tokenString[0])
	if err != nil {
		fmt.Println("assume scope <scopeID> expects a valid int32 scope")
		fmt.Printf("you provided %s which errored with %v \n", tokenString[0], err)
		return
	}
	if _, ok := c.commands[scopeID]; !ok {
		fmt.Printf("inactive scope %d see correct usage via help\n", scopeID)
	}
	c.assumedScope = scopeID
	fmt.Println("assumed scope ", scopeID)
}

// strToInt32 helps align to the window scope handles
func strToInt32(potentialInt string) (int32, error) {
	i64, err := strconv.ParseInt(potentialInt, 10, 32)
	return int32(i64), err
}

// parseTokenAsInt is a convience function for parsing from our string slice of strings
func parseTokenAsInt(tokenString []string, arrIndex int, defaultVal int) int {
	if len(tokenString) > arrIndex {
		tmp, err := strconv.Atoi(tokenString[arrIndex])
		if err == nil {
			return tmp
		}
	}
	return defaultVal
}
<|endoftext|>


<commit_before>package api

import (
	"bufio"
	"bytes"
	"encoding/json"
	"image"
	"image/draw"
	"image/png" // This needs to be imported because otherwhise image.Decode won't work with png images
	"io/ioutil"
	"os"
	"strings"
	"sync"

	"github.com/mjarkk/wotnlclans/other"

	"github.com/disintegration/imaging"
	"github.com/mjarkk/wotnlclans/db"
)

type imageAndIDType struct {
	ID    string
	Image image.Image
}

// GetIcons fetches all clan icons and creates a grid
func GetIcons() error {
	other.DevPrint("Getting clan icons...")
	clans, err := db.GetCurrentClansData()
	if err != nil {
		return err
	}
	toSavePath := "./icons/clanIcons"
	os.RemoveAll(toSavePath)
	os.Mkdir(toSavePath, os.ModePerm)
	imgAndID := []imageAndIDType{}

	var waitForImgs sync.WaitGroup
	waitForImgs.Add(len(clans))

	for _, clan := range clans {
		go func(clan db.ClanStats) {
			iconToGet, ok := clan.Emblems["X195.Portal"]
			if !ok {
				iconToGet, ok = clan.Emblems["X256.Wowp"]
				if !ok {
					return
				}
			}
			if !strings.Contains(iconToGet, "http://") && !strings.Contains(iconToGet, "https://") {
				return
			}
			out, err := RawGet(iconToGet)
			if err != nil {
				return
			}
			uriDots := strings.Split(iconToGet, ".")
			fileExt := uriDots[len(uriDots)-1]
			imgPath := toSavePath + "/" + clan.ID + "." + fileExt
			err = ioutil.WriteFile(imgPath, out, 0644)
			if err != nil {
				return
			}

			img, _, err := image.Decode(bytes.NewReader(out))
			if err != nil {
				return
			}

			imgAndID = append(imgAndID, imageAndIDType{
				ID:    clan.ID,
				Image: img,
			})
			waitForImgs.Done()
		}(clan)
	}

	waitForImgs.Wait()

	if len(imgAndID) > 0 {
		imgSize := 60
		imgsInARow := 30

		ids := [][]string{[]string{}}
		outputImg := image.NewRGBA(image.Rectangle{image.Point{0, 0}, image.Point{0, 0}})

		for _, imgObj := range imgAndID {

			id := imgObj.ID
			if len(ids[len(ids)-1]) == imgsInARow {
				ids = append(ids, []string{})
			}
			from := struct {
				top  int
				side int
			}{
				top:  len(ids),
				side: len(ids[len(ids)-1]),
			}

			insertImg := imaging.Resize(imgObj.Image, imgSize, imgSize, imaging.Lanczos)
			offset := image.Point{imgSize * from.side, imgSize * (from.top - 1)}
			whereToInsert := image.Rectangle{offset, offset.Add(insertImg.Bounds().Size())}
			maxSize := image.Point{(len(ids[0]) + 1) * imgSize, len(ids) * imgSize}

			canvas := image.NewRGBA(image.Rectangle{image.Point{0, 0}, maxSize})
			draw.Draw(canvas, outputImg.Bounds(), outputImg, image.Point{0, 0}, draw.Src)
			draw.Draw(canvas, whereToInsert, insertImg, image.Point{0, 0}, draw.Src)
			outputImg = canvas

			ids[len(ids)-1] = append(ids[len(ids)-1], id)
		}

		file, err := os.Create("./icons/allIcons.png")
		if err != nil {
			return err
		}
		png.Encode(file, outputImg)
		file.Close()

		file, err = os.Create("./icons/allIcons.json")
		if err != nil {
			return err
		}
		writer := bufio.NewWriter(file)

		defer func() {
			writer.Flush()
			file.Close()
		}()

		jsonEncoder := json.NewEncoder(writer)
		err = jsonEncoder.Encode(ids)
		if err != nil {
			return err
		}
		return nil
	}

	return nil
}
<commit_msg>Removed the creation of images<commit_after>package api

import (
	"bufio"
	"bytes"
	"encoding/json"
	"image"
	"image/draw"
	"image/png" // This needs to be imported because otherwhise image.Decode won't work with png images
	"os"
	"strings"
	"sync"

	"github.com/mjarkk/wotnlclans/other"

	"github.com/disintegration/imaging"
	"github.com/mjarkk/wotnlclans/db"
)

type imageAndIDType struct {
	ID    string
	Image image.Image
}

// GetIcons fetches all clan icons and creates a grid
func GetIcons() error {
	other.DevPrint("Getting clan icons...")
	clans, err := db.GetCurrentClansData()
	if err != nil {
		return err
	}
	// toSavePath := "./icons/clanIcons"
	// os.RemoveAll(toSavePath)
	// os.Mkdir(toSavePath, os.ModePerm)
	imgAndID := []imageAndIDType{}

	var waitForImgs sync.WaitGroup
	waitForImgs.Add(len(clans))

	for _, clan := range clans {
		go func(clan db.ClanStats) {
			iconToGet, ok := clan.Emblems["X195.Portal"]
			if !ok {
				iconToGet, ok = clan.Emblems["X256.Wowp"]
				if !ok {
					return
				}
			}
			if !strings.Contains(iconToGet, "http://") && !strings.Contains(iconToGet, "https://") {
				return
			}
			out, err := RawGet(iconToGet)
			if err != nil {
				return
			}
			// uriDots := strings.Split(iconToGet, ".")
			// fileExt := uriDots[len(uriDots)-1]
			// imgPath := toSavePath + "/" + clan.ID + "." + fileExt
			// err = ioutil.WriteFile(imgPath, out, 0644)
			// if err != nil {
			// 	return
			// }

			img, _, err := image.Decode(bytes.NewReader(out))
			if err != nil {
				return
			}

			imgAndID = append(imgAndID, imageAndIDType{
				ID:    clan.ID,
				Image: img,
			})
			waitForImgs.Done()
		}(clan)
	}

	waitForImgs.Wait()

	if len(imgAndID) > 0 {
		imgSize := 60
		imgsInARow := 30

		ids := [][]string{[]string{}}
		outputImg := image.NewRGBA(image.Rectangle{image.Point{0, 0}, image.Point{0, 0}})

		for _, imgObj := range imgAndID {

			id := imgObj.ID
			if len(ids[len(ids)-1]) == imgsInARow {
				ids = append(ids, []string{})
			}
			from := struct {
				top  int
				side int
			}{
				top:  len(ids),
				side: len(ids[len(ids)-1]),
			}

			insertImg := imaging.Resize(imgObj.Image, imgSize, imgSize, imaging.Lanczos)
			offset := image.Point{imgSize * from.side, imgSize * (from.top - 1)}
			whereToInsert := image.Rectangle{offset, offset.Add(insertImg.Bounds().Size())}
			maxSize := image.Point{(len(ids[0]) + 1) * imgSize, len(ids) * imgSize}

			canvas := image.NewRGBA(image.Rectangle{image.Point{0, 0}, maxSize})
			draw.Draw(canvas, outputImg.Bounds(), outputImg, image.Point{0, 0}, draw.Src)
			draw.Draw(canvas, whereToInsert, insertImg, image.Point{0, 0}, draw.Src)
			outputImg = canvas

			ids[len(ids)-1] = append(ids[len(ids)-1], id)
		}

		file, err := os.Create("./icons/allIcons.png")
		if err != nil {
			return err
		}
		png.Encode(file, outputImg)
		file.Close()

		file, err = os.Create("./icons/allIcons.json")
		if err != nil {
			return err
		}
		writer := bufio.NewWriter(file)

		defer func() {
			writer.Flush()
			file.Close()
		}()

		jsonEncoder := json.NewEncoder(writer)
		err = jsonEncoder.Encode(ids)
		if err != nil {
			return err
		}
		return nil
	}

	return nil
}
<|endoftext|>


<commit_before>// Copyright 2019 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Package runner provides utilities to execute commands.
package runner

import (
	"bytes"
	"errors"
	"fmt"
	"log"
	"os"
	"os/exec"
	"strings"
)

// Runner is the interface to execute commands.
type Runner interface {
	CmdRun(cmd *exec.Cmd) error
	CmdOutput(cmd *exec.Cmd) ([]byte, error)
	CmdCombinedOutput(cmd *exec.Cmd) ([]byte, error)
}

// Default is the Runner that executes the command by default.
type Default struct{}

// CmdRun executes the command.
func (*Default) CmdRun(cmd *exec.Cmd) error {
	log.Printf("Running: %v", cmd.Args)
	cmd.Stdin = os.Stdin
	cmd.Stdout = os.Stdout
	var stderr bytes.Buffer
	cmd.Stderr = &stderr
	if err := cmd.Run(); err != nil {
		return fmt.Errorf("%v: %s", err, stderr.String())
	}
	return nil
}

// CmdOutput executes the command and returns the command stdout.
func (*Default) CmdOutput(cmd *exec.Cmd) ([]byte, error) {
	log.Printf("Running: %v", cmd.Args)
	var stderr bytes.Buffer
	cmd.Stderr = &stderr
	b, err := cmd.Output()
	if err != nil {
		return b, fmt.Errorf("%v: %s", err, stderr.String())
	}
	return b, nil
}

// CmdCombinedOutput executes the command and returns the command stdout and stderr.
func (*Default) CmdCombinedOutput(cmd *exec.Cmd) ([]byte, error) {
	log.Printf("Running: %v", cmd.Args)
	return cmd.CombinedOutput()
}

func contains(s string, subs ...string) bool {
	for _, sub := range subs {
		if !strings.Contains(s, sub) {
			return false
		}
	}
	return true
}

// Fake is the Runner that only prints command information and does not run it.
type Fake struct{}

// CmdRun prints the command information.
func (*Fake) CmdRun(cmd *exec.Cmd) error {
	cmdStr := strings.Join(cmd.Args, " ")
	switch {
	case contains(cmdStr, "cp"):
		// In dry_run mode, stil execute commands that copy Terraform modules and configs
		// to the Terraform working directory so that users can find them.
		return (&Default{}).CmdRun(cmd)
	default:
		log.Printf("Dry run call: %s", strings.Join(cmd.Args, " "))
		return nil
	}
}

// CmdOutput prints the command information.
func (*Fake) CmdOutput(cmd *exec.Cmd) ([]byte, error) {
	log.Printf("Dry run call: %s", strings.Join(cmd.Args, " "))
	cmdStr := strings.Join(cmd.Args, " ")
	switch {
	case contains(cmdStr, "projects describe"):
		return nil, errors.New("")
	case contains(cmdStr, "logging sinks describe audit-logs-to-bigquery", "--format json"):
		return []byte("{}"), nil
	case contains(cmdStr, "config get-value account", "--format json"):
		return []byte(`"dryrun@dryrun.com"`), nil
	case contains(cmdStr, "projects get-iam-policy"):
		return []byte("{}"), nil
	case contains(cmdStr, "service-accounts list", "--filter email:forseti-server-gcp-*", "--format json"):
		return []byte(`[{"email": "forseti-server-gcp-dryrun@dryrun.iam.gserviceaccount.com"}]`), nil
	case contains(cmdStr, "gsutil ls"):
		return []byte("gs://forseti-server-dryrun"), nil
	case contains(cmdStr, "iam service-accounts list --format json --filter email:forseti-server-gcp-*"):
		return []byte(`[{"email": forseti-sa@@forseti-project.iam.gserviceaccount.com"}]`), nil
	case contains(cmdStr, "monitoring channels list"):
		return []byte("[]"), nil
	case contains(cmdStr, "monitoring channels create"):
		return []byte(`{"name": "projects/dryrun/notificationChannels/dryrun"}`), nil
	case contains(cmdStr, "monitoring policies list"):
		return []byte("[]"), nil
	case contains(cmdStr, "compute instances list"):
		return []byte("[]"), nil
	case contains(cmdStr, "terraform output -json project_number"):
		return []byte("\"11111\""), nil
	default:
		return nil, nil
	}
}

// CmdCombinedOutput prints the command information.
func (*Fake) CmdCombinedOutput(cmd *exec.Cmd) ([]byte, error) {
	log.Printf("Dry run call: %s", strings.Join(cmd.Args, " "))
	cmdStr := strings.Join(cmd.Args, " ")
	switch {
	case contains(cmdStr, "deployment-manager deployments list", "--format json"):
		return []byte("[]"), nil
	case contains(cmdStr, "monitoring policies list"):
		return []byte(""), nil
	default:
		return nil, nil
	}
}
<commit_msg>add resource-manager liens list in fake runner<commit_after>// Copyright 2019 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Package runner provides utilities to execute commands.
package runner

import (
	"bytes"
	"errors"
	"fmt"
	"log"
	"os"
	"os/exec"
	"strings"
)

// Runner is the interface to execute commands.
type Runner interface {
	CmdRun(cmd *exec.Cmd) error
	CmdOutput(cmd *exec.Cmd) ([]byte, error)
	CmdCombinedOutput(cmd *exec.Cmd) ([]byte, error)
}

// Default is the Runner that executes the command by default.
type Default struct{}

// CmdRun executes the command.
func (*Default) CmdRun(cmd *exec.Cmd) error {
	log.Printf("Running: %v", cmd.Args)
	cmd.Stdin = os.Stdin
	cmd.Stdout = os.Stdout
	var stderr bytes.Buffer
	cmd.Stderr = &stderr
	if err := cmd.Run(); err != nil {
		return fmt.Errorf("%v: %s", err, stderr.String())
	}
	return nil
}

// CmdOutput executes the command and returns the command stdout.
func (*Default) CmdOutput(cmd *exec.Cmd) ([]byte, error) {
	log.Printf("Running: %v", cmd.Args)
	var stderr bytes.Buffer
	cmd.Stderr = &stderr
	b, err := cmd.Output()
	if err != nil {
		return b, fmt.Errorf("%v: %s", err, stderr.String())
	}
	return b, nil
}

// CmdCombinedOutput executes the command and returns the command stdout and stderr.
func (*Default) CmdCombinedOutput(cmd *exec.Cmd) ([]byte, error) {
	log.Printf("Running: %v", cmd.Args)
	return cmd.CombinedOutput()
}

func contains(s string, subs ...string) bool {
	for _, sub := range subs {
		if !strings.Contains(s, sub) {
			return false
		}
	}
	return true
}

// Fake is the Runner that only prints command information and does not run it.
type Fake struct{}

// CmdRun prints the command information.
func (*Fake) CmdRun(cmd *exec.Cmd) error {
	cmdStr := strings.Join(cmd.Args, " ")
	switch {
	case contains(cmdStr, "cp"):
		// In dry_run mode, stil execute commands that copy Terraform modules and configs
		// to the Terraform working directory so that users can find them.
		return (&Default{}).CmdRun(cmd)
	default:
		log.Printf("Dry run call: %s", strings.Join(cmd.Args, " "))
		return nil
	}
}

// CmdOutput prints the command information.
func (*Fake) CmdOutput(cmd *exec.Cmd) ([]byte, error) {
	log.Printf("Dry run call: %s", strings.Join(cmd.Args, " "))
	cmdStr := strings.Join(cmd.Args, " ")
	switch {
	case contains(cmdStr, "projects describe"):
		return nil, errors.New("")
	case contains(cmdStr, "logging sinks describe audit-logs-to-bigquery", "--format json"):
		return []byte("{}"), nil
	case contains(cmdStr, "config get-value account", "--format json"):
		return []byte(`"dryrun@dryrun.com"`), nil
	case contains(cmdStr, "projects get-iam-policy"):
		return []byte("{}"), nil
	case contains(cmdStr, "service-accounts list", "--filter email:forseti-server-gcp-*", "--format json"):
		return []byte(`[{"email": "forseti-server-gcp-dryrun@dryrun.iam.gserviceaccount.com"}]`), nil
	case contains(cmdStr, "gsutil ls"):
		return []byte("gs://forseti-server-dryrun"), nil
	case contains(cmdStr, "iam service-accounts list --format json --filter email:forseti-server-gcp-*"):
		return []byte(`[{"email": forseti-sa@@forseti-project.iam.gserviceaccount.com"}]`), nil
	case contains(cmdStr, "monitoring channels list"):
		return []byte("[]"), nil
	case contains(cmdStr, "monitoring channels create"):
		return []byte(`{"name": "projects/dryrun/notificationChannels/dryrun"}`), nil
	case contains(cmdStr, "monitoring policies list"):
		return []byte("[]"), nil
	case contains(cmdStr, "compute instances list"):
		return []byte("[]"), nil
	case contains(cmdStr, "resource-manager liens list"):
		return []byte("[]"), nil
	case contains(cmdStr, "terraform output -json project_number"):
		return []byte("\"11111\""), nil
	default:
		return nil, nil
	}
}

// CmdCombinedOutput prints the command information.
func (*Fake) CmdCombinedOutput(cmd *exec.Cmd) ([]byte, error) {
	log.Printf("Dry run call: %s", strings.Join(cmd.Args, " "))
	cmdStr := strings.Join(cmd.Args, " ")
	switch {
	case contains(cmdStr, "deployment-manager deployments list", "--format json"):
		return []byte("[]"), nil
	case contains(cmdStr, "monitoring policies list"):
		return []byte(""), nil
	default:
		return nil, nil
	}
}
<|endoftext|>


<commit_before>package api

import (
	"context"

	"github.com/TheThingsNetwork/ttn/utils/errors"
	"google.golang.org/grpc/metadata"
)

var ErrContext = errors.NewErrInternal("Could not get metadata from context")

var ErrNoToken = errors.NewErrInvalidArgument("Metadata", "token missing")
var ErrNoID = errors.NewErrInvalidArgument("Metadata", "id missing")

func MetadataFromContext(ctx context.Context) (md metadata.MD, err error) {
	var ok bool
	if md, ok = metadata.FromContext(ctx); !ok {
		return md, ErrContext
	}
	return md, nil
}

func IDFromMetadata(md metadata.MD) (string, error) {
	id, ok := md["id"]
	if !ok || len(id) == 0 {
		return "", ErrNoID
	}
	return id[0], nil
}

func TokenFromMetadata(md metadata.MD) (string, error) {
	token, ok := md["token"]
	if !ok || len(token) == 0 {
		return "", ErrNoToken
	}
	return token[0], nil
}
<commit_msg>api/metadata.go: consistent style<commit_after>package api

import (
	"context"

	"github.com/TheThingsNetwork/ttn/utils/errors"
	"google.golang.org/grpc/metadata"
)

var ErrContext = errors.NewErrInternal("Could not get metadata from context")

var ErrNoToken = errors.NewErrInvalidArgument("Metadata", "token missing")
var ErrNoID = errors.NewErrInvalidArgument("Metadata", "id missing")

func MetadataFromContext(ctx context.Context) (metadata.MD, error) {
	md, ok := metadata.FromContext(ctx)
	if !ok {
		return md, ErrContext
	}
	return md, nil
}

func IDFromMetadata(md metadata.MD) (string, error) {
	id, ok := md["id"]
	if !ok || len(id) == 0 {
		return "", ErrNoID
	}
	return id[0], nil
}

func TokenFromMetadata(md metadata.MD) (string, error) {
	token, ok := md["token"]
	if !ok || len(token) == 0 {
		return "", ErrNoToken
	}
	return token[0], nil
}
<|endoftext|>