<commit_before>package tarantool

import (
	"context"
)

type ExecOption interface {
	apply(*request)
}

type opaqueOption struct {
	opaque interface{}
}

func (o *opaqueOption) apply(r *request) {
	r.opaque = o.opaque
}

func OpaqueExecOption(opaque interface{}) ExecOption {
	return &opaqueOption{opaque: opaque}
}

// the Result type is used to return write errors here
func (conn *Connection) writeRequest(ctx context.Context, request *request, q Query) (*request, *Result) {
	var err error

	requestID := conn.nextID()

	pp := packetPool.GetWithID(requestID)

	if err = pp.packMsg(q, conn.packData); err != nil {
		return nil, &Result{
			Error:     NewQueryError(ErrInvalidMsgpack, err.Error()),
			ErrorCode: ErrInvalidMsgpack,
		}
	}

	request.packet = pp

	if oldRequest := conn.requests.Put(requestID, request); oldRequest != nil {
		select {
		case oldRequest.replyChan <- &AsyncResult{
			Error:     ConnectionClosedError(conn),
			ErrorCode: ErrNoConnection,
			Opaque:    oldRequest.opaque,
		}:
		default:
		}
	}

	writeChan := conn.writeChan
	if writeChan == nil {
		return nil, &Result{
			Error:     ConnectionClosedError(conn),
			ErrorCode: ErrNoConnection,
		}
	}

	select {
	case writeChan <- request:
	case <-ctx.Done():
		if conn.perf.QueryTimeouts != nil && ctx.Err() == context.DeadlineExceeded {
			conn.perf.QueryTimeouts.Add(1)
		}
		r := conn.requests.Pop(requestID)
		requestPool.Put(r)
		return nil, &Result{
			Error:     NewContextError(ctx, conn, "Send error"),
			ErrorCode: ErrTimeout,
		}
	case <-conn.exit:
		return nil, &Result{
			Error:     ConnectionClosedError(conn),
			ErrorCode: ErrNoConnection,
		}
	}

	return request, nil
}

func (conn *Connection) readResult(ctx context.Context, arc chan *AsyncResult) *AsyncResult {
	select {
	case ar := <-arc:
		if ar == nil {
			return &AsyncResult{
				Error:     ConnectionClosedError(conn),
				ErrorCode: ErrNoConnection,
			}
		}
		return ar
	case <-ctx.Done():
		if conn.perf.QueryTimeouts != nil && ctx.Err() == context.DeadlineExceeded {
			conn.perf.QueryTimeouts.Add(1)
		}
		return &AsyncResult{
			Error:     NewContextError(ctx, conn, "Recv error"),
			ErrorCode: ErrTimeout,
		}
	case <-conn.exit:
		return &AsyncResult{
			Error:     ConnectionClosedError(conn),
			ErrorCode: ErrNoConnection,
		}
	}
}

func (conn *Connection) Exec(ctx context.Context, q Query, options ...ExecOption) (result *Result) {
	var cancel context.CancelFunc = func() {}

	if _, ok := ctx.Deadline(); !ok && conn.queryTimeout != 0 {
		ctx, cancel = context.WithTimeout(ctx, conn.queryTimeout)
	}

	replyChan := make(chan *AsyncResult, 1)

	request := requestPool.Get()
	request.replyChan = replyChan
	for i := 0; i < len(options); i++ {
		options[i].apply(request)
	}

	if _, rerr := conn.writeRequest(ctx, request, q); rerr != nil {
		cancel()
		return rerr
	}

	ar := conn.readResult(ctx, replyChan)
	cancel()

	if rerr := ar.Error; rerr != nil {
		return &Result{
			Error:     rerr,
			ErrorCode: ar.ErrorCode,
		}
	}

	pp := ar.BinaryPacket
	if pp == nil {
		return &Result{
			Error:     ConnectionClosedError(conn),
			ErrorCode: ErrNoConnection,
		}
	}

	if err := pp.Unmarshal(); err != nil {
		result = &Result{
			Error:     err,
			ErrorCode: ErrInvalidMsgpack,
		}
	} else {
		result = pp.Result()
		if result == nil {
			result = &Result{}
		}
	}
	pp.Release()

	return result
}

func (conn *Connection) ExecAsync(ctx context.Context, q Query, opaque interface{}, replyChan chan *AsyncResult) error {
	request := requestPool.Get()
	request.opaque = opaque
	request.replyChan = replyChan

	if _, rerr := conn.writeRequest(ctx, request, q); rerr != nil {
		return rerr.Error
	}
	return nil
}

func (conn *Connection) Execute(q Query) ([][]interface{}, error) {
	res := conn.Exec(context.Background(), q)
	return res.Data, res.Error
}
<commit_msg>Strong timeout deadline<commit_after>package tarantool

import (
	"context"
)

type ExecOption interface {
	apply(*request)
}

type opaqueOption struct {
	opaque interface{}
}

func (o *opaqueOption) apply(r *request) {
	r.opaque = o.opaque
}

func OpaqueExecOption(opaque interface{}) ExecOption {
	return &opaqueOption{opaque: opaque}
}

// the Result type is used to return write errors here
func (conn *Connection) writeRequest(ctx context.Context, request *request, q Query) (*request, *Result) {
	var err error

	requestID := conn.nextID()

	pp := packetPool.GetWithID(requestID)

	if err = pp.packMsg(q, conn.packData); err != nil {
		return nil, &Result{
			Error:     NewQueryError(ErrInvalidMsgpack, err.Error()),
			ErrorCode: ErrInvalidMsgpack,
		}
	}

	request.packet = pp

	if oldRequest := conn.requests.Put(requestID, request); oldRequest != nil {
		select {
		case oldRequest.replyChan <- &AsyncResult{
			Error:     ConnectionClosedError(conn),
			ErrorCode: ErrNoConnection,
			Opaque:    oldRequest.opaque,
		}:
		default:
		}
	}

	writeChan := conn.writeChan
	if writeChan == nil {
		return nil, &Result{
			Error:     ConnectionClosedError(conn),
			ErrorCode: ErrNoConnection,
		}
	}

	select {
	case writeChan <- request:
	case <-ctx.Done():
		if conn.perf.QueryTimeouts != nil && ctx.Err() == context.DeadlineExceeded {
			conn.perf.QueryTimeouts.Add(1)
		}
		r := conn.requests.Pop(requestID)
		requestPool.Put(r)
		return nil, &Result{
			Error:     NewContextError(ctx, conn, "Send error"),
			ErrorCode: ErrTimeout,
		}
	case <-conn.exit:
		return nil, &Result{
			Error:     ConnectionClosedError(conn),
			ErrorCode: ErrNoConnection,
		}
	}

	return request, nil
}

func (conn *Connection) readResult(ctx context.Context, arc chan *AsyncResult) *AsyncResult {
	select {
	case ar := <-arc:
		if ar == nil {
			return &AsyncResult{
				Error:     ConnectionClosedError(conn),
				ErrorCode: ErrNoConnection,
			}
		}
		return ar
	case <-ctx.Done():
		if conn.perf.QueryTimeouts != nil && ctx.Err() == context.DeadlineExceeded {
			conn.perf.QueryTimeouts.Add(1)
		}
		return &AsyncResult{
			Error:     NewContextError(ctx, conn, "Recv error"),
			ErrorCode: ErrTimeout,
		}
	case <-conn.exit:
		return &AsyncResult{
			Error:     ConnectionClosedError(conn),
			ErrorCode: ErrNoConnection,
		}
	}
}

func (conn *Connection) Exec(ctx context.Context, q Query, options ...ExecOption) (result *Result) {
	var cancel context.CancelFunc = func() {}

	if conn.queryTimeout != 0 {
		ctx, cancel = context.WithTimeout(ctx, conn.queryTimeout)
	}

	replyChan := make(chan *AsyncResult, 1)

	request := requestPool.Get()
	request.replyChan = replyChan
	for i := 0; i < len(options); i++ {
		options[i].apply(request)
	}

	if _, rerr := conn.writeRequest(ctx, request, q); rerr != nil {
		cancel()
		return rerr
	}

	ar := conn.readResult(ctx, replyChan)
	cancel()

	if rerr := ar.Error; rerr != nil {
		return &Result{
			Error:     rerr,
			ErrorCode: ar.ErrorCode,
		}
	}

	pp := ar.BinaryPacket
	if pp == nil {
		return &Result{
			Error:     ConnectionClosedError(conn),
			ErrorCode: ErrNoConnection,
		}
	}

	if err := pp.Unmarshal(); err != nil {
		result = &Result{
			Error:     err,
			ErrorCode: ErrInvalidMsgpack,
		}
	} else {
		result = pp.Result()
		if result == nil {
			result = &Result{}
		}
	}
	pp.Release()

	return result
}

func (conn *Connection) ExecAsync(ctx context.Context, q Query, opaque interface{}, replyChan chan *AsyncResult) error {
	request := requestPool.Get()
	request.opaque = opaque
	request.replyChan = replyChan

	if _, rerr := conn.writeRequest(ctx, request, q); rerr != nil {
		return rerr.Error
	}
	return nil
}

func (conn *Connection) Execute(q Query) ([][]interface{}, error) {
	res := conn.Exec(context.Background(), q)
	return res.Data, res.Error
}
<|endoftext|>


<commit_before>package gobcodec

import (
	"encoding/gob"
	"sync"
)

type buffer struct {
	buf []byte
	n   int
}

func (b *buffer) Read(p []byte) (int, error) {
	n := copy(p, b.buf)
	b.buf = b.buf[n:]
	return n, nil
}

func (b *buffer) Write(p []byte) (int, error) {
	b.buf = append(b.buf[:b.n], p...)
	n := len(p)
	b.n += n
	return n, nil
}

type Codec struct {
	l sync.Mutex
	b *buffer
	e *gob.Encoder
	d *gob.Decoder
}

func NewCodec() *Codec {
	b := &buffer{}
	return &Codec{
		b: b,
		e: gob.NewEncoder(b),
		d: gob.NewDecoder(b),
	}
}

func (c *Codec) Register(v interface{}) error {
	c.l.Lock()
	c.b.n = 0
	if err := c.e.Encode(v); err != nil {
		return returnErr(c, err)

	}
	var z interface{}
	if err := c.d.Decode(z); err != nil {
		return returnErr(c, err)
	}
	c.l.Unlock()
	return nil
}

func (c *Codec) Encode(v interface{}, dst []byte) ([]byte, error) {
	c.l.Lock()
	c.b.buf = dst
	c.b.n = 0
	if err := c.e.Encode(v); err != nil {
		return dst, returnErr(c, err)
	}
	dst = c.b.buf
	c.l.Unlock()
	return dst, nil
}

func (c *Codec) Decode(v interface{}, src []byte) ([]byte, error) {
	c.l.Lock()
	c.b.buf = src
	if err := c.d.Decode(v); err != nil {
		return src, returnErr(c, err)
	}
	src = c.b.buf
	c.l.Unlock()
	return src, nil
}

func returnErr(c *Codec, err error) error {
	c.l.Unlock()
	return err
}
<commit_msg>GC help - nullify used buffer after each encoding/decoding<commit_after>package gobcodec

import (
	"encoding/gob"
	"sync"
)

type buffer struct {
	buf []byte
	n   int
}

func (b *buffer) Read(p []byte) (int, error) {
	n := copy(p, b.buf)
	b.buf = b.buf[n:]
	return n, nil
}

func (b *buffer) Write(p []byte) (int, error) {
	b.buf = append(b.buf[:b.n], p...)
	n := len(p)
	b.n += n
	return n, nil
}

type Codec struct {
	l sync.Mutex
	b *buffer
	e *gob.Encoder
	d *gob.Decoder
}

func NewCodec() *Codec {
	b := &buffer{}
	return &Codec{
		b: b,
		e: gob.NewEncoder(b),
		d: gob.NewDecoder(b),
	}
}

func (c *Codec) Register(v interface{}) error {
	c.l.Lock()
	c.b.n = 0
	if err := c.e.Encode(v); err != nil {
		return returnErr(c, err)

	}
	var z interface{}
	if err := c.d.Decode(z); err != nil {
		return returnErr(c, err)
	}
	c.b.buf = nil
	c.l.Unlock()
	return nil
}

func (c *Codec) Encode(v interface{}, dst []byte) ([]byte, error) {
	c.l.Lock()
	c.b.buf = dst
	c.b.n = 0
	if err := c.e.Encode(v); err != nil {
		return dst, returnErr(c, err)
	}
	dst = c.b.buf
	c.b.buf = nil
	c.l.Unlock()
	return dst, nil
}

func (c *Codec) Decode(v interface{}, src []byte) ([]byte, error) {
	c.l.Lock()
	c.b.buf = src
	if err := c.d.Decode(v); err != nil {
		return src, returnErr(c, err)
	}
	src = c.b.buf
	c.b.buf = nil
	c.l.Unlock()
	return src, nil
}

func returnErr(c *Codec, err error) error {
	c.l.Unlock()
	return err
}
<|endoftext|>


<commit_before>// This executable provides an HTTP server that watches for file system changes
// to .go files within the working directory (and all nested go packages).
// Navigating to the configured host and port will show a web UI showing the
// results of running `go test` in each go package.

package main

import (
	"flag"
	"fmt"
	"log"
	"net/http"
	"os"
	"path/filepath"
	"runtime"
	"strings"
	"time"

	"github.com/smartystreets/goconvey/web/server/api"
	"github.com/smartystreets/goconvey/web/server/contract"
	exec "github.com/smartystreets/goconvey/web/server/executor"
	parse "github.com/smartystreets/goconvey/web/server/parser"
	"github.com/smartystreets/goconvey/web/server/system"
	watch "github.com/smartystreets/goconvey/web/server/watcher"
)

func init() {
	flags()
	folders()
}
func flags() {
	flag.IntVar(&port, "port", 8080, "The port at which to serve http.")
	flag.StringVar(&host, "host", "127.0.0.1", "The host at which to serve http.")
	flag.DurationVar(&nap, "poll", quarterSecond, "The interval to wait between polling the file system for changes (default: 250ms).")
	flag.IntVar(&packages, "packages", 10, "The number of packages to test in parallel. Higher == faster but more costly in terms of computing. (default: 10)")
	flag.StringVar(&gobin, "gobin", "go", "The path to the 'go' binary (default: search on the PATH).")
	flag.BoolVar(&cover, "cover", true, "Enable package-level coverage statistics. Warning: this will obfuscate line number reporting on panics and build failures! Requires Go 1.2+ and the go cover tool. (default: true)")
	flag.IntVar(&depth, "depth", -1, "The directory scanning depth. If -1, scan infinitely deep directory structures. 0: scan working directory. 1+: Scan into nested directories, limited to value. (default: -1)")
	flag.StringVar(&testflags, "testflags", "", "Any extra flags to be passed to go test tool (default: '')`")

	log.SetOutput(os.Stdout)
	log.SetFlags(log.LstdFlags | log.Lshortfile)
}
func folders() {
	_, file, _, _ := runtime.Caller(0)
	here := filepath.Dir(file)
	static = filepath.Join(here, "/web/client")
	reports = filepath.Join(static, "reports")
}

func main() {
	flag.Parse()
	log.Printf("Initial configuration: [host: %s] [port: %d] [poll: %v] [cover: %v] [testflags: %v]\n", host, port, nap, cover, testflags)

	monitor, server := wireup()

	go monitor.ScanForever()

	serveHTTP(server)
}

func serveHTTP(server contract.Server) {
	serveStaticResources()
	serveAjaxMethods(server)
	activateServer()
}

func serveStaticResources() {
	http.Handle("/", http.FileServer(http.Dir(static)))
}

func serveAjaxMethods(server contract.Server) {
	http.HandleFunc("/watch", server.Watch)
	http.HandleFunc("/ignore", server.Ignore)
	http.HandleFunc("/reinstate", server.Reinstate)
	http.HandleFunc("/latest", server.Results)
	http.HandleFunc("/execute", server.Execute)
	http.HandleFunc("/status", server.Status)
	http.HandleFunc("/status/poll", server.LongPollStatus)
}

func activateServer() {
	log.Printf("Serving HTTP at: http://%s:%d\n", host, port)
	err := http.ListenAndServe(fmt.Sprintf(":%d", port), nil)
	if err != nil {
		fmt.Println(err)
	}
}

func wireup() (*contract.Monitor, contract.Server) {
	log.Println("Constructing components...")
	working, err := os.Getwd()
	if err != nil {
		panic(err)
	}

	// Ensure testflags does not contain any disallowed flags
	for _, a := range strings.Fields(testflags) {
		if a == "-test.parallel" || a == "-parallel" {
			log.Fatal("GoConvey does not support the parallel test flag")
		}
	}

	depthLimit := system.NewDepthLimit(system.NewFileSystem(), depth)
	shell := system.NewShell(gobin, testflags, cover, reports)

	watcher := watch.NewWatcher(depthLimit, shell)
	watcher.Adjust(working)

	parser := parse.NewParser(parse.ParsePackageResults)
	tester := exec.NewConcurrentTester(shell)
	tester.SetBatchSize(packages)

	statusNotif := make(chan bool, 1)
	executor := exec.NewExecutor(tester, parser, statusNotif)
	server := api.NewHTTPServer(watcher, executor, statusNotif)
	scanner := watch.NewScanner(depthLimit, watcher)
	monitor := contract.NewMonitor(scanner, watcher, executor, server, sleeper)

	return monitor, server
}

func sleeper() {
	time.Sleep(nap)
}

var (
	port      int
	host      string
	gobin     string
	nap       time.Duration
	packages  int
	cover     bool
	depth     int
	testflags string

	static  string
	reports string

	quarterSecond = time.Millisecond * 250
)
<commit_msg>Included example of the testflags usage.<commit_after>// This executable provides an HTTP server that watches for file system changes
// to .go files within the working directory (and all nested go packages).
// Navigating to the configured host and port will show a web UI showing the
// results of running `go test` in each go package.

package main

import (
	"flag"
	"fmt"
	"log"
	"net/http"
	"os"
	"path/filepath"
	"runtime"
	"strings"
	"time"

	"github.com/smartystreets/goconvey/web/server/api"
	"github.com/smartystreets/goconvey/web/server/contract"
	exec "github.com/smartystreets/goconvey/web/server/executor"
	parse "github.com/smartystreets/goconvey/web/server/parser"
	"github.com/smartystreets/goconvey/web/server/system"
	watch "github.com/smartystreets/goconvey/web/server/watcher"
)

func init() {
	flags()
	folders()
}
func flags() {
	flag.IntVar(&port, "port", 8080, "The port at which to serve http.")
	flag.StringVar(&host, "host", "127.0.0.1", "The host at which to serve http.")
	flag.DurationVar(&nap, "poll", quarterSecond, "The interval to wait between polling the file system for changes (default: 250ms).")
	flag.IntVar(&packages, "packages", 10, "The number of packages to test in parallel. Higher == faster but more costly in terms of computing. (default: 10)")
	flag.StringVar(&gobin, "gobin", "go", "The path to the 'go' binary (default: search on the PATH).")
	flag.BoolVar(&cover, "cover", true, "Enable package-level coverage statistics. Warning: this will obfuscate line number reporting on panics and build failures! Requires Go 1.2+ and the go cover tool. (default: true)")
	flag.IntVar(&depth, "depth", -1, "The directory scanning depth. If -1, scan infinitely deep directory structures. 0: scan working directory. 1+: Scan into nested directories, limited to value. (default: -1)")
	flag.StringVar(&testflags, "testflags", "", "Any extra flags to be passed to go test tool (default: '') (example: '-testflags="-test.short=true")`")

	log.SetOutput(os.Stdout)
	log.SetFlags(log.LstdFlags | log.Lshortfile)
}
func folders() {
	_, file, _, _ := runtime.Caller(0)
	here := filepath.Dir(file)
	static = filepath.Join(here, "/web/client")
	reports = filepath.Join(static, "reports")
}

func main() {
	flag.Parse()
	log.Printf("Initial configuration: [host: %s] [port: %d] [poll: %v] [cover: %v] [testflags: %v]\n", host, port, nap, cover, testflags)

	monitor, server := wireup()

	go monitor.ScanForever()

	serveHTTP(server)
}

func serveHTTP(server contract.Server) {
	serveStaticResources()
	serveAjaxMethods(server)
	activateServer()
}

func serveStaticResources() {
	http.Handle("/", http.FileServer(http.Dir(static)))
}

func serveAjaxMethods(server contract.Server) {
	http.HandleFunc("/watch", server.Watch)
	http.HandleFunc("/ignore", server.Ignore)
	http.HandleFunc("/reinstate", server.Reinstate)
	http.HandleFunc("/latest", server.Results)
	http.HandleFunc("/execute", server.Execute)
	http.HandleFunc("/status", server.Status)
	http.HandleFunc("/status/poll", server.LongPollStatus)
}

func activateServer() {
	log.Printf("Serving HTTP at: http://%s:%d\n", host, port)
	err := http.ListenAndServe(fmt.Sprintf(":%d", port), nil)
	if err != nil {
		fmt.Println(err)
	}
}

func wireup() (*contract.Monitor, contract.Server) {
	log.Println("Constructing components...")
	working, err := os.Getwd()
	if err != nil {
		panic(err)
	}

	// Ensure testflags does not contain any disallowed flags
	for _, a := range strings.Fields(testflags) {
		if a == "-test.parallel" || a == "-parallel" {
			log.Fatal("GoConvey does not support the parallel test flag")
		}
	}

	depthLimit := system.NewDepthLimit(system.NewFileSystem(), depth)
	shell := system.NewShell(gobin, testflags, cover, reports)

	watcher := watch.NewWatcher(depthLimit, shell)
	watcher.Adjust(working)

	parser := parse.NewParser(parse.ParsePackageResults)
	tester := exec.NewConcurrentTester(shell)
	tester.SetBatchSize(packages)

	statusNotif := make(chan bool, 1)
	executor := exec.NewExecutor(tester, parser, statusNotif)
	server := api.NewHTTPServer(watcher, executor, statusNotif)
	scanner := watch.NewScanner(depthLimit, watcher)
	monitor := contract.NewMonitor(scanner, watcher, executor, server, sleeper)

	return monitor, server
}

func sleeper() {
	time.Sleep(nap)
}

var (
	port      int
	host      string
	gobin     string
	nap       time.Duration
	packages  int
	cover     bool
	depth     int
	testflags string

	static  string
	reports string

	quarterSecond = time.Millisecond * 250
)
<|endoftext|>


<commit_before>// TODO: Handle user auth.
// TODO: Verify service account auth actually works.
// TODO: Cache discovery/directory documents for faster requests.
// TODO: Handle media upload/download.
// TODO: Handle repeated parameters.

package main

import (
	"encoding/json"
	"encoding/pem"
	"errors"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"strings"

	"code.google.com/p/goauth2/oauth/jwt"
)

var (
	// Flags that get parsed before the command, necessary for loading Cloud Endpoints APIs
	// e.g., "googlecl --endpoint=foo help myapi" parses the endpoint flag before loading the API
	endpointFs   = flag.NewFlagSet("endpoint", flag.ExitOnError)
	flagEndpoint = endpointFs.String("endpoint", "https://www.googleapis.com/", "Cloud Endpoints URL, e.g., https://my-app-id.appspot.com/_ah/api/")

	// Flags that get parsed after the command, common to all APIs
	fs          = flag.NewFlagSet("googlecl", flag.ExitOnError)
	flagPem     = fs.String("meta.pem", "", "Location of .pem file")
	flagSecrets = fs.String("meta.secrets", "", "Location of client_secrets.json")
	flagStdin   = fs.Bool("meta.in", false, "Accept request body from stdin")
	flagInFile  = fs.String("meta.inFile", "", "File to pass as request body")
)

func simpleHelp() {
	fmt.Println("Makes requests to Google APIs")
	fmt.Println("Usage:")
	fmt.Println("  googlecl <api> <method> --param=foo")
}

func help() {
	args := endpointFs.Args()
	nargs := len(args)
	if nargs == 0 || (nargs == 1 && args[0] == "help") {
		simpleHelp()
		return
	}
	apiName := args[1]
	api, err := loadAPI(apiName)
	if err != nil {
		log.Fatal(err)
	}
	if nargs == 2 {
		// googlecl help <api>
		fmt.Println(api.Title, api.Description)
		fmt.Println("More information:", api.DocumentationLink)
		fmt.Println("Methods:")
		for _, m := range api.Methods {
			fmt.Println(m.ID, m.Description)
		}
		type pair struct {
			k string
			r Resource
		}
		l := []pair{}
		for k, r := range api.Resources {
			l = append(l, pair{k, r})
		}
		for i := 0; i < len(l); i++ {
			r := l[i].r
			for _, m := range r.Methods {
				fmt.Printf("%s - %s\n", m.ID[len(api.Name)+1:], m.Description)
			}
			for k, r := range r.Resources {
				l = append(l, pair{k, r})
			}
		}
	} else {
		// googlecl help <api> <method>
		method := args[2]
		m := findMethod(method, *api)
		fmt.Println(method, m.Description)
		fmt.Println("Parameters:")
		for k, p := range m.Parameters {
			fmt.Printf("  --%s (%s) - %s\n", k, p.Type, p.Description)
		}
		for k, p := range api.Parameters {
			fmt.Printf("  --%s (%s) - %s\n", k, p.Type, p.Description)
		}
	}
}

func list() {
	var directory struct {
		Items []struct {
			Name, Version, Description string
		}
	}
	getAndParse("discovery/v1/apis", &directory)
	fmt.Println("Available methods:")
	for _, i := range directory.Items {
		fmt.Printf("%s %s - %s\n", i.Name, i.Version, i.Description)
	}
}

func main() {
	endpointFs.Parse(os.Args[1:])
	if len(endpointFs.Args()) == 0 {
		simpleHelp()
		return
	}

	cmd := endpointFs.Args()[0]
	if cmd == "help" {
		help()
		return
	} else if cmd == "list" {
		list()
		return
	}

	method := endpointFs.Args()[1]
	if method == "" {
		log.Fatal("Must specify API method to call")
	}

	api, err := loadAPI(cmd)
	if err != nil {
		log.Fatal(err)
	}
	if api == nil || (len(api.Resources) == 0 && len(api.Methods) == 0) {
		log.Fatal("Couldn't load API ", cmd)
	}

	m := findMethod(method, *api)
	for k, p := range api.Parameters {
		fs.String(k, p.Default, p.Description)
	}
	for k, p := range m.Parameters {
		fs.String(k, p.Default, p.Description)
	}
	fs.Parse(endpointFs.Args()[2:])
	m.call(api)
}

func findMethod(method string, api API) *Method {
	parts := strings.Split(method, ".")
	var ms map[string]Method
	rs := api.Resources
	for i := 0; i < len(parts)-1; i++ {
		r := rs[parts[i]]
		if &r == nil {
			log.Fatal("Could not find requested method ", method)
		}
		rs = r.Resources
		ms = r.Methods
	}
	lp := parts[len(parts)-1]
	m := ms[lp]
	if &m == nil {
		log.Fatal("Could not find requested method ", method)
	}
	return &m
}

func getPreferredVersion(apiName string) (string, error) {
	var d struct {
		Items []struct {
			Version string
		}
	}
	err := getAndParse(fmt.Sprintf("discovery/v1/apis?preferred=true&name=%s&fields=items/version", apiName), &d)
	if err != nil {
		return "", err
	}
	if d.Items == nil {
		log.Fatal("Could not load API ", apiName)
	}
	return d.Items[0].Version, nil
}

// loadAPI takes a string like "apiname" or "apiname:v4" and loads the API from Discovery
func loadAPI(s string) (*API, error) {
	parts := strings.SplitN(s, ":", 2)
	apiName := parts[0]
	var v string
	if len(parts) == 2 {
		v = parts[1]
	} else {
		// Look up preferred version in Directory
		var err error
		v, err = getPreferredVersion(apiName)
		if err != nil {
			log.Fatal(err)
		}
	}

	var a API
	err := getAndParse(fmt.Sprintf("discovery/v1/apis/%s/%s/rest", apiName, v), &a)
	if err != nil {
		return nil, err
	}
	return &a, nil
}

func getAndParse(path string, v interface{}) error {
	url := *flagEndpoint + path

	r, err := http.Get(url)
	if err != nil {
		return err
	}
	defer r.Body.Close()
	err = json.NewDecoder(r.Body).Decode(v)
	if err != nil {
		return err
	}
	return nil
}

type API struct {
	BaseURL, Name, Title, Description, DocumentationLink string
	Resources                                            map[string]Resource
	Methods                                              map[string]Method
	Parameters                                           map[string]Parameter
}

type Resource struct {
	Resources map[string]Resource
	Methods   map[string]Method
}

type Method struct {
	ID, Path, HttpMethod, Description string
	Parameters                        map[string]Parameter
	Scopes                            []string
}

func (m Method) call(api *API) {
	if m.Scopes != nil {
		scope := strings.Join(m.Scopes, " ")
		if *flagPem != "" && *flagSecrets != "" {
			tok, err := accessTokenFromPemFile(scope, *flagPem, *flagSecrets)
			if err != nil {
				log.Fatal(err)
			}
			log.Print(tok)
		} else {
			log.Fatal("This method requires access to API scopes: ", scope)
		}
	}

	url := api.BaseURL + m.Path
	for k, p := range m.Parameters {
		url = p.process(k, url)
	}
	for k, p := range api.Parameters {
		url = p.process(k, url)
	}

	var body io.Reader
	if *flagStdin {
		// If user passes the --in flag, use stdin as the request body
		body = os.Stdin
	} else if *flagInFile != "" {
		// If user passes --inFile flag, open that file and use its content as request body
		var err error
		body, err = os.Open(*flagInFile)
		if err != nil {
			log.Fatal(err)
		}
	}

	r, err := http.NewRequest(m.HttpMethod, url, body)
	if err != nil {
		log.Fatal(err)
	}

	client := &http.Client{}
	resp, err := client.Do(r)
	if err != nil {
		log.Fatal(err)
	}
	defer resp.Body.Close()

	io.Copy(os.Stderr, resp.Body)
	if resp.StatusCode < 200 || resp.StatusCode > 299 {
		os.Exit(1)
	}
}

func accessTokenFromPemFile(scope, pemPath, secretsPath string) (string, error) {
	pemFile, err := os.Open(pemPath)
	if err != nil {
		return "", err
	}
	defer pemFile.Close()
	keyBytes, err := ioutil.ReadAll(pemFile)
	if err != nil {
		return "", err
	}
	pb, _ := pem.Decode(keyBytes)
	if len(pb.Bytes) == 0 {
		return "", errors.New("No PEM data found")
	}

	secretsFile, err := os.Open(secretsPath)
	if err != nil {
		return "", err
	}
	defer secretsFile.Close()
	secretsBytes, err := ioutil.ReadAll(secretsFile)
	if err != nil {
		return "", err
	}
	var config struct {
		Web struct {
			ClientEmail string `json:"client_email"`
			TokenURI    string `json:"token_uri"`
		}
	}
	err = json.Unmarshal(secretsBytes, &config)
	if err != nil {
		return "", err
	}

	t := jwt.NewToken(config.Web.ClientEmail, scope, pb.Bytes)
	t.ClaimSet.Aud = config.Web.TokenURI
	tok, err := t.Assert(&http.Client{})
	if err != nil {
		return "", err
	}
	return tok.AccessToken, nil
}

type Parameter struct {
	Type, Description, Location, Default string
	Required                             bool
}

func (p Parameter) process(k string, url string) string {
	f := fs.Lookup(k)
	if f == nil {
		return url
	}
	v := f.Value.String()
	if v == "" {
		return url
	}
	if p.Location == "path" {
		if p.Required && v == "" {
			log.Print("Missing required parameter ", k)
		}
		t := fmt.Sprintf("{%s}", k)
		return strings.Replace(url, t, v, -1)
	} else if p.Location == "query" {
		delim := "&"
		if !strings.Contains(url, "?") {
			delim = "?"
		}
		return url + fmt.Sprintf("%s%s=%s", delim, k, v)
	}
	return url
}
<commit_msg>Fixes service account auth, request bodies now broken...<commit_after>// TODO: Handle user auth.
// TODO: Cache discovery/directory documents for faster requests.
// TODO: Handle media upload/download.
// TODO: Handle repeated parameters.
// TODO: Request bodies seem not to be getting set...

package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"strings"

	"code.google.com/p/goauth2/oauth/jwt"
)

var (
	// Flags that get parsed before the command, necessary for loading Cloud Endpoints APIs
	// e.g., "googlecl --endpoint=foo help myapi" parses the endpoint flag before loading the API
	endpointFs   = flag.NewFlagSet("endpoint", flag.ExitOnError)
	flagEndpoint = endpointFs.String("endpoint", "https://www.googleapis.com/", "Cloud Endpoints URL, e.g., https://my-app-id.appspot.com/_ah/api/")

	// Flags that get parsed after the command, common to all APIs
	fs          = flag.NewFlagSet("googlecl", flag.ExitOnError)
	flagPem     = fs.String("meta.pem", "", "Location of .pem file")
	flagSecrets = fs.String("meta.secrets", "", "Location of client_secrets.json")
	flagStdin   = fs.Bool("meta.in", false, "Accept request body from stdin")
	flagInFile  = fs.String("meta.inFile", "", "File to pass as request body")
)

func simpleHelp() {
	fmt.Println("Makes requests to Google APIs")
	fmt.Println("Usage:")
	fmt.Println("  googlecl <api> <method> --param=foo")
}

func help() {
	args := endpointFs.Args()
	nargs := len(args)
	if nargs == 0 || (nargs == 1 && args[0] == "help") {
		simpleHelp()
		return
	}
	apiName := args[1]
	api, err := loadAPI(apiName)
	if err != nil {
		log.Fatal(err)
	}
	if nargs == 2 {
		// googlecl help <api>
		fmt.Println(api.Title, api.Description)
		fmt.Println("More information:", api.DocumentationLink)
		fmt.Println("Methods:")
		for _, m := range api.Methods {
			fmt.Println(m.ID, m.Description)
		}
		type pair struct {
			k string
			r Resource
		}
		l := []pair{}
		for k, r := range api.Resources {
			l = append(l, pair{k, r})
		}
		for i := 0; i < len(l); i++ {
			r := l[i].r
			for _, m := range r.Methods {
				fmt.Printf("%s - %s\n", m.ID[len(api.Name)+1:], m.Description)
			}
			for k, r := range r.Resources {
				l = append(l, pair{k, r})
			}
		}
	} else {
		// googlecl help <api> <method>
		method := args[2]
		m := findMethod(method, *api)
		fmt.Println(method, m.Description)
		fmt.Println("Parameters:")
		for k, p := range m.Parameters {
			fmt.Printf("  --%s (%s) - %s\n", k, p.Type, p.Description)
		}
		for k, p := range api.Parameters {
			fmt.Printf("  --%s (%s) - %s\n", k, p.Type, p.Description)
		}
	}
}

func list() {
	var directory struct {
		Items []struct {
			Name, Version, Description string
		}
	}
	getAndParse("discovery/v1/apis", &directory)
	fmt.Println("Available methods:")
	for _, i := range directory.Items {
		fmt.Printf("%s %s - %s\n", i.Name, i.Version, i.Description)
	}
}

func main() {
	endpointFs.Parse(os.Args[1:])
	if len(endpointFs.Args()) == 0 {
		simpleHelp()
		return
	}

	cmd := endpointFs.Args()[0]
	if cmd == "help" {
		help()
		return
	} else if cmd == "list" {
		list()
		return
	}

	method := endpointFs.Args()[1]
	if method == "" {
		log.Fatal("Must specify API method to call")
	}

	api, err := loadAPI(cmd)
	if err != nil {
		log.Fatal(err)
	}
	if api == nil || (len(api.Resources) == 0 && len(api.Methods) == 0) {
		log.Fatal("Couldn't load API ", cmd)
	}

	m := findMethod(method, *api)
	for k, p := range api.Parameters {
		fs.String(k, p.Default, p.Description)
	}
	for k, p := range m.Parameters {
		fs.String(k, p.Default, p.Description)
	}
	fs.Parse(endpointFs.Args()[2:])
	m.call(api)
}

func findMethod(method string, api API) *Method {
	parts := strings.Split(method, ".")
	var ms map[string]Method
	rs := api.Resources
	for i := 0; i < len(parts)-1; i++ {
		r := rs[parts[i]]
		if &r == nil {
			log.Fatal("Could not find requested method ", method)
		}
		rs = r.Resources
		ms = r.Methods
	}
	lp := parts[len(parts)-1]
	m := ms[lp]
	if &m == nil {
		log.Fatal("Could not find requested method ", method)
	}
	return &m
}

func getPreferredVersion(apiName string) (string, error) {
	var d struct {
		Items []struct {
			Version string
		}
	}
	err := getAndParse(fmt.Sprintf("discovery/v1/apis?preferred=true&name=%s&fields=items/version", apiName), &d)
	if err != nil {
		return "", err
	}
	if d.Items == nil {
		log.Fatal("Could not load API ", apiName)
	}
	return d.Items[0].Version, nil
}

// loadAPI takes a string like "apiname" or "apiname:v4" and loads the API from Discovery
func loadAPI(s string) (*API, error) {
	parts := strings.SplitN(s, ":", 2)
	apiName := parts[0]
	var v string
	if len(parts) == 2 {
		v = parts[1]
	} else {
		// Look up preferred version in Directory
		var err error
		v, err = getPreferredVersion(apiName)
		if err != nil {
			log.Fatal(err)
		}
	}

	var a API
	err := getAndParse(fmt.Sprintf("discovery/v1/apis/%s/%s/rest", apiName, v), &a)
	if err != nil {
		return nil, err
	}
	return &a, nil
}

func getAndParse(path string, v interface{}) error {
	url := *flagEndpoint + path

	r, err := http.Get(url)
	if err != nil {
		return err
	}
	defer r.Body.Close()
	err = json.NewDecoder(r.Body).Decode(v)
	if err != nil {
		return err
	}
	return nil
}

type API struct {
	BaseURL, Name, Title, Description, DocumentationLink string
	Resources                                            map[string]Resource
	Methods                                              map[string]Method
	Parameters                                           map[string]Parameter
}

type Resource struct {
	Resources map[string]Resource
	Methods   map[string]Method
}

type Method struct {
	ID, Path, HttpMethod, Description string
	Parameters                        map[string]Parameter
	Scopes                            []string
}

func (m Method) call(api *API) {
	url := api.BaseURL + m.Path
	for k, p := range m.Parameters {
		url = p.process(k, url)
	}
	// API-level common parameters
	for k, p := range api.Parameters {
		url = p.process(k, url)
	}

	r, err := http.NewRequest(m.HttpMethod, url, nil)
	if err != nil {
		log.Fatal("error creating request:", err)
	}

	if *flagStdin {
		// If user passes the --in flag, use stdin as the request body
		r.Body = os.Stdin
	} else if *flagInFile != "" {
		// If user passes --inFile flag, open that file and use its content as request body
		body, err := os.Open(*flagInFile)
		if err != nil {
			log.Fatal(err)
		}
		r.Body = body
	}

	// Add auth header
	if m.Scopes != nil {
		if *flagPem != "" && *flagSecrets != "" {
			scope := strings.Join(m.Scopes, " ")
			tok := accessTokenFromPemFile(scope, *flagPem, *flagSecrets)
			r.Header.Set("Authorization", "Bearer "+tok)
		} else {
			log.Fatal("This method requires access to API scopes: ", m.Scopes)
		}
	}

	client := &http.Client{}
	resp, err := client.Do(r)
	if err != nil {
		log.Fatal(err)
	}
	defer resp.Body.Close()

	io.Copy(os.Stderr, resp.Body)
	if resp.StatusCode < 200 || resp.StatusCode > 299 {
		os.Exit(1)
	}
}

func accessTokenFromPemFile(scope, pemPath, secretsPath string) string {
	secretBytes, err := ioutil.ReadFile(secretsPath)
	if err != nil {
		log.Fatal("error reading secrets file:", err)
	}
	var config struct {
		Web struct {
			ClientEmail string `json:"client_email"`
			TokenURI    string `json:"token_uri"`
		}
	}
	err = json.Unmarshal(secretBytes, &config)
	if err != nil {
		log.Fatal("error unmarshalling secrets:", err)
	}

	keyBytes, err := ioutil.ReadFile(pemPath)
	if err != nil {
		log.Fatal("error reading private key file:", err)
	}

	// Craft the ClaimSet and JWT token.
	t := jwt.NewToken(config.Web.ClientEmail, scope, keyBytes)
	t.ClaimSet.Aud = config.Web.TokenURI

	// We need to provide a client.
	c := &http.Client{}

	// Get the access token.
	o, err := t.Assert(c)
	if err != nil {
		log.Fatal("assertion error:", err)
	}

	return o.AccessToken
}

type Parameter struct {
	Type, Description, Location, Default string
	Required                             bool
}

func (p Parameter) process(k string, url string) string {
	f := fs.Lookup(k)
	if f == nil {
		return url
	}
	v := f.Value.String()
	if v == "" {
		return url
	}
	if p.Location == "path" {
		if p.Required && v == "" {
			log.Print("Missing required parameter ", k)
		}
		t := fmt.Sprintf("{%s}", k)
		return strings.Replace(url, t, v, -1)
	} else if p.Location == "query" {
		delim := "&"
		if !strings.Contains(url, "?") {
			delim = "?"
		}
		return url + fmt.Sprintf("%s%s=%s", delim, k, v)
	}
	return url
}
<|endoftext|>


<commit_before>// Copyright 2013-2014 Unknown
//
// 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.

// Go Walker Server generates Go projects API documentation and Hacker View on the fly.
package main

import (
	"fmt"
	"os"
	"os/signal"
	"strings"
	"syscall"

	"github.com/Unknwon/com"
	"github.com/astaxie/beego"
	"github.com/beego/i18n"

	"github.com/Unknwon/gowalker/doc"
	"github.com/Unknwon/gowalker/hv"
	"github.com/Unknwon/gowalker/models"
	"github.com/Unknwon/gowalker/routers"
	"github.com/Unknwon/gowalker/utils"
)

const (
	APP_VER = "1.0.11.0525"
)

// We have to call a initialize function manully
// because we use `bee bale` to pack static resources
// and we cannot make sure that which init() execute first.
func initialize() {
	// Load configuration, set app version and log level.
	utils.LoadConfig("conf/app.ini")

	// Load locale files.
	langs := strings.Split(utils.Cfg.MustValue("lang", "types"), "|")
	// Skip en-US.
	for i := 1; i < len(langs); i++ {
		err := i18n.SetMessage(langs[i], "conf/locale_"+langs[i]+".ini")
		if err != nil {
			panic("Fail to set message file: " + err.Error())
		}
	}

	// Trim 4th part.
	routers.AppVer = strings.Join(strings.Split(APP_VER, ".")[:3], ".")

	beego.AppName = utils.Cfg.MustValue("beego", "app_name")
	beego.RunMode = utils.Cfg.MustValue("beego", "run_mode")
	beego.HttpPort = utils.Cfg.MustInt("beego", "http_port_"+beego.RunMode)

	routers.IsBeta = utils.Cfg.MustBool("server", "beta")
	routers.IsProMode = beego.RunMode == "prod"
	if routers.IsProMode {
		beego.SetLevel(beego.LevelInfo)
		beego.Info("Product mode enabled")

		os.Mkdir("./log", os.ModePerm)
		beego.BeeLogger.SetLogger("file", `{"filename": "log/log"}`)
	}

	// Initialize data.
	models.InitDb()
	routers.InitRouter()

	doc.SetGithubCredentials(utils.Cfg.MustValue("github", "client_id"),
		utils.Cfg.MustValue("github", "client_secret"))
}

func catchExit() {
	sigTerm := syscall.Signal(15)
	sig := make(chan os.Signal)
	signal.Notify(sig, os.Interrupt, sigTerm)

	for {
		switch <-sig {
		case os.Interrupt, sigTerm:
			fmt.Println()
			com.ColorLog("[WARN] INTERRUPT SIGNAL DETECTED!!!\n")
			routers.FlushCache()
			com.ColorLog("[WARN] READY TO EXIT\n")
			os.Exit(0)
		}
	}
}

func main() {
	initialize()
	go catchExit()

	beego.Info(beego.AppName, APP_VER)

	// Register routers.
	beego.Router("/", &routers.HomeRouter{})
	beego.Router("/refresh", &routers.RefreshRouter{})
	beego.Router("/search", &routers.SearchRouter{})
	beego.Router("/index", &routers.IndexRouter{})
	// beego.Router("/label", &routers.LabelsRouter{})
	beego.Router("/function", &routers.FuncsRouter{})
	beego.Router("/example", &routers.ExamplesRouter{})
	beego.Router("/about", &routers.AboutRouter{})

	beego.Router("/api/docs", &routers.ApiRouter{}, "get:Docs")
	beego.Router("/api/v1/badge", &routers.ApiRouter{}, "get:Badge")
	beego.Router("/api/v1/search", &routers.ApiRouter{}, "get:Search")
	beego.Router("/api/v1/refresh", &routers.ApiRouter{}, "get:Refresh")
	beego.Router("/api/v1/pkginfo", &routers.ApiRouter{}, "get:PkgInfo")

	// Register template functions.
	beego.AddFuncMap("i18n", i18n.Tr)
	beego.AddFuncMap("isHasEleS", isHasEleS)
	beego.AddFuncMap("isHasEleE", isHasEleE)
	beego.AddFuncMap("isNotEmptyS", isNotEmptyS)

	// "robot.txt"
	beego.Router("/robots.txt", &routers.RobotRouter{})

	// For all unknown pages.
	beego.Router("/:all", &routers.HomeRouter{})

	// Static path.
	beego.SetStaticPath("/public", "public")
	beego.Run()
}

func isHasEleS(s []string) bool {
	if len(s) == 1 && len(s[0]) == 0 {
		return false
	}
	return len(s) > 0
}

func isHasEleE(s []*hv.Example) bool {
	return len(s) > 0
}

func isNotEmptyS(s string) bool {
	return len(s) > 0
}
<commit_msg>Fix license<commit_after>// Copyright 2013 Unknown
//
// 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.

// Go Walker Server generates Go projects API documentation and Hacker View on the fly.
package main

import (
	"fmt"
	"os"
	"os/signal"
	"strings"
	"syscall"

	"github.com/Unknwon/com"
	"github.com/astaxie/beego"
	"github.com/beego/i18n"

	"github.com/Unknwon/gowalker/doc"
	"github.com/Unknwon/gowalker/hv"
	"github.com/Unknwon/gowalker/models"
	"github.com/Unknwon/gowalker/routers"
	"github.com/Unknwon/gowalker/utils"
)

const (
	APP_VER = "1.0.11.0525"
)

// We have to call a initialize function manully
// because we use `bee bale` to pack static resources
// and we cannot make sure that which init() execute first.
func initialize() {
	// Load configuration, set app version and log level.
	utils.LoadConfig("conf/app.ini")

	// Load locale files.
	langs := strings.Split(utils.Cfg.MustValue("lang", "types"), "|")
	// Skip en-US.
	for i := 1; i < len(langs); i++ {
		err := i18n.SetMessage(langs[i], "conf/locale_"+langs[i]+".ini")
		if err != nil {
			panic("Fail to set message file: " + err.Error())
		}
	}

	// Trim 4th part.
	routers.AppVer = strings.Join(strings.Split(APP_VER, ".")[:3], ".")

	beego.AppName = utils.Cfg.MustValue("beego", "app_name")
	beego.RunMode = utils.Cfg.MustValue("beego", "run_mode")
	beego.HttpPort = utils.Cfg.MustInt("beego", "http_port_"+beego.RunMode)

	routers.IsBeta = utils.Cfg.MustBool("server", "beta")
	routers.IsProMode = beego.RunMode == "prod"
	if routers.IsProMode {
		beego.SetLevel(beego.LevelInfo)
		beego.Info("Product mode enabled")

		os.Mkdir("./log", os.ModePerm)
		beego.BeeLogger.SetLogger("file", `{"filename": "log/log"}`)
	}

	// Initialize data.
	models.InitDb()
	routers.InitRouter()

	doc.SetGithubCredentials(utils.Cfg.MustValue("github", "client_id"),
		utils.Cfg.MustValue("github", "client_secret"))
}

func catchExit() {
	sigTerm := syscall.Signal(15)
	sig := make(chan os.Signal)
	signal.Notify(sig, os.Interrupt, sigTerm)

	for {
		switch <-sig {
		case os.Interrupt, sigTerm:
			fmt.Println()
			com.ColorLog("[WARN] INTERRUPT SIGNAL DETECTED!!!\n")
			routers.FlushCache()
			com.ColorLog("[WARN] READY TO EXIT\n")
			os.Exit(0)
		}
	}
}

func main() {
	initialize()
	go catchExit()

	beego.Info(beego.AppName, APP_VER)

	// Register routers.
	beego.Router("/", &routers.HomeRouter{})
	beego.Router("/refresh", &routers.RefreshRouter{})
	beego.Router("/search", &routers.SearchRouter{})
	beego.Router("/index", &routers.IndexRouter{})
	// beego.Router("/label", &routers.LabelsRouter{})
	beego.Router("/function", &routers.FuncsRouter{})
	beego.Router("/example", &routers.ExamplesRouter{})
	beego.Router("/about", &routers.AboutRouter{})

	beego.Router("/api/docs", &routers.ApiRouter{}, "get:Docs")
	beego.Router("/api/v1/badge", &routers.ApiRouter{}, "get:Badge")
	beego.Router("/api/v1/search", &routers.ApiRouter{}, "get:Search")
	beego.Router("/api/v1/refresh", &routers.ApiRouter{}, "get:Refresh")
	beego.Router("/api/v1/pkginfo", &routers.ApiRouter{}, "get:PkgInfo")

	// Register template functions.
	beego.AddFuncMap("i18n", i18n.Tr)
	beego.AddFuncMap("isHasEleS", isHasEleS)
	beego.AddFuncMap("isHasEleE", isHasEleE)
	beego.AddFuncMap("isNotEmptyS", isNotEmptyS)

	// "robot.txt"
	beego.Router("/robots.txt", &routers.RobotRouter{})

	// For all unknown pages.
	beego.Router("/:all", &routers.HomeRouter{})

	// Static path.
	beego.SetStaticPath("/public", "public")
	beego.Run()
}

func isHasEleS(s []string) bool {
	if len(s) == 1 && len(s[0]) == 0 {
		return false
	}
	return len(s) > 0
}

func isHasEleE(s []*hv.Example) bool {
	return len(s) > 0
}

func isNotEmptyS(s string) bool {
	return len(s) > 0
}
<|endoftext|>


<commit_before>package api

import (
	"net/http"

	wkhtmltopdf "github.com/SebastiaanKlippert/go-wkhtmltopdf"

	"errors"

	"strings"

	"encoding/json"
	"os"

	"io/ioutil"

	"bitbucket.org/mundipagg/boletoapi/bank"
	"bitbucket.org/mundipagg/boletoapi/boleto"
	"bitbucket.org/mundipagg/boletoapi/db"
	"bitbucket.org/mundipagg/boletoapi/log"
	"bitbucket.org/mundipagg/boletoapi/models"
	"bitbucket.org/mundipagg/boletoapi/util"
	gin "gopkg.in/gin-gonic/gin.v1"
)

//Regista um boleto em um determinado banco
func registerBoleto(c *gin.Context) {
	_boleto, _ := c.Get("boleto")
	boleto := _boleto.(models.BoletoRequest)
	bank, err := bank.Get(boleto.BankNumber)
	if checkError(c, err, log.CreateLog()) {
		return
	}
	lg := bank.Log()
	lg.Operation = "RegisterBoleto"
	lg.NossoNumero = boleto.Title.OurNumber
	lg.Recipient = bank.GetBankNumber().BankName()
	c.Set("log", lg)
	lg.Request(boleto, c.Request.URL.RequestURI(), c.Request.Header)
	repo, err := db.GetDB()
	if checkError(c, err, lg) {
		return
	}
	resp, errR := bank.ProcessBoleto(boleto)
	if checkError(c, errR, lg) {
		return
	}
	lg.Response(resp, c.Request.URL.RequestURI())
	st := http.StatusOK
	if len(resp.Errors) > 0 {
		st = http.StatusBadRequest
	} else {
		boView := models.NewBoletoView(boleto, resp.BarCodeNumber, resp.DigitableLine)
		resp.URL = boView.EncodeURL()
		errMongo := repo.SaveBoleto(boView)
		if errMongo != nil {
			lg.Warn(errMongo.Error(), "I could not save your boleto at Database")
			fd, errOpen := os.Create("/home/upMongo/boleto_" + boView.UID + ".json")
			if errOpen != nil {
				lg.Fatal(boView, "[BOLETO_ONLINE_CONTINGENCIA]"+errOpen.Error())
			}
			data, _ := json.Marshal(boView)
			_, errW := fd.Write(data)
			if errW != nil {
				lg.Fatal(boView, "[BOLETO_ONLINE_CONTINGENCIA]"+errW.Error())
			}
			fd.Close()
		}
	}
	c.JSON(st, resp)
}

func getBoleto(c *gin.Context) {
	c.Status(200)

	id := c.Query("id")
	fmt := c.Query("fmt")
	repo, errCon := db.GetDB()
	if checkError(c, errCon, log.CreateLog()) {
		return
	}
	bleto, err := repo.GetBoletoByID(id)
	if err != nil {
		uid := util.Decrypt(id)
		fd, err := os.Open("/home/upMongo/boleto_" + uid + ".json")
		if err != nil {
			checkError(c, errors.New("Boleto não encontrado na base de dados"), log.CreateLog())
			return
		}
		data, errR := ioutil.ReadAll(fd)
		if errR != nil {
			checkError(c, errors.New("Boleto não encontrado na base de dados"), log.CreateLog())
			return
		}
		json.Unmarshal(data, &bleto)
		fd.Close()
	}

	s := boleto.HTML(bleto, fmt)
	if fmt == "html" {
		c.Header("Content-Type", "text/html; charset=utf-8")
		c.Writer.WriteString(s)
	} else {
		c.Header("Content-Type", "application/pdf")
		buf, _ := toPdf(s)
		c.Writer.Write(buf)
	}

}

func toPdf(page string) ([]byte, error) {
	pdfg, err := wkhtmltopdf.NewPDFGenerator()
	if err != nil {
		return nil, err
	}
	pdfg.Dpi.Set(600)
	pdfg.NoCollate.Set(false)
	pdfg.PageSize.Set(wkhtmltopdf.PageSizeA4)
	pdfg.AddPage(wkhtmltopdf.NewPageReader(strings.NewReader(page)))
	err = pdfg.Create()
	if err != nil {
		return nil, err
	}
	return pdfg.Bytes(), nil
}
<commit_msg>:art: refatora o codigo<commit_after>package api

import (
	"net/http"

	wkhtmltopdf "github.com/SebastiaanKlippert/go-wkhtmltopdf"

	"errors"

	"strings"

	"encoding/json"
	"os"

	"io/ioutil"

	"bitbucket.org/mundipagg/boletoapi/bank"
	"bitbucket.org/mundipagg/boletoapi/boleto"
	"bitbucket.org/mundipagg/boletoapi/config"
	"bitbucket.org/mundipagg/boletoapi/db"
	"bitbucket.org/mundipagg/boletoapi/log"
	"bitbucket.org/mundipagg/boletoapi/models"
	"bitbucket.org/mundipagg/boletoapi/util"
	gin "gopkg.in/gin-gonic/gin.v1"
)

//Regista um boleto em um determinado banco
func registerBoleto(c *gin.Context) {
	_boleto, _ := c.Get("boleto")
	boleto := _boleto.(models.BoletoRequest)
	bank, err := bank.Get(boleto.BankNumber)
	if checkError(c, err, log.CreateLog()) {
		return
	}
	lg := bank.Log()
	lg.Operation = "RegisterBoleto"
	lg.NossoNumero = boleto.Title.OurNumber
	lg.Recipient = bank.GetBankNumber().BankName()
	lg.Request(boleto, c.Request.URL.RequestURI(), util.HeaderToMap(c.Request.Header))
	repo, err := db.GetDB()
	if checkError(c, err, lg) {
		return
	}
	resp, errR := bank.ProcessBoleto(boleto)
	if checkError(c, errR, lg) {
		return
	}
	lg.Response(resp, c.Request.URL.RequestURI())
	st := http.StatusOK
	if len(resp.Errors) > 0 {
		st = http.StatusBadRequest
	} else {
		boView := models.NewBoletoView(boleto, resp.BarCodeNumber, resp.DigitableLine)
		resp.URL = boView.EncodeURL()
		errMongo := repo.SaveBoleto(boView)
		if errMongo != nil {
			saveBoletoJSONFile(boView, lg, errMongo)
		}
	}
	c.JSON(st, resp)
}

func saveBoletoJSONFile(boView models.BoletoView, lg *log.Log, err error) {
	lg.Warn(err.Error(), "I could not save your boleto at Database")
	fd, errOpen := os.Create(config.Get().BoletoJSONFileStore + "/boleto_" + boView.UID + ".json")
	if errOpen != nil {
		lg.Fatal(boView, "[BOLETO_ONLINE_CONTINGENCIA]"+errOpen.Error())
	}
	data, _ := json.Marshal(boView)
	_, errW := fd.Write(data)
	if errW != nil {
		lg.Fatal(boView, "[BOLETO_ONLINE_CONTINGENCIA]"+errW.Error())
	}
	fd.Close()
}

func getBoleto(c *gin.Context) {
	c.Status(200)

	id := c.Query("id")
	format := c.Query("fmt")
	repo, errCon := db.GetDB()
	if checkError(c, errCon, log.CreateLog()) {
		return
	}
	bleto, err := repo.GetBoletoByID(id)
	if err != nil {
		uid := util.Decrypt(id)
		fd, err := os.Open("/boleto_" + uid + ".json")
		if err != nil {
			checkError(c, errors.New("Boleto não encontrado na base de dados"), log.CreateLog())
			return
		}
		data, errR := ioutil.ReadAll(fd)
		if errR != nil {
			checkError(c, errors.New("Boleto não encontrado na base de dados"), log.CreateLog())
			return
		}
		json.Unmarshal(data, &bleto)
		fd.Close()
	}

	s := boleto.HTML(bleto, format)
	if format == "html" {
		c.Header("Content-Type", "text/html; charset=utf-8")
		c.Writer.WriteString(s)
	} else {
		c.Header("Content-Type", "application/pdf")
		buf, _ := toPdf(s)
		c.Writer.Write(buf)
	}

}

func toPdf(page string) ([]byte, error) {
	pdfg, err := wkhtmltopdf.NewPDFGenerator()
	if err != nil {
		return nil, err
	}
	pdfg.Dpi.Set(600)
	pdfg.NoCollate.Set(false)
	pdfg.PageSize.Set(wkhtmltopdf.PageSizeA4)
	pdfg.AddPage(wkhtmltopdf.NewPageReader(strings.NewReader(page)))
	err = pdfg.Create()
	if err != nil {
		return nil, err
	}
	return pdfg.Bytes(), nil
}
<|endoftext|>


<commit_before>// Package compfile returns ReadClosers for files that are possible
// compressed, guessing the compression type based on the file
// extension.
package compfile

import (
	"bufio"
	"compress/bzip2"
	"compress/gzip"
	"io"
	"os"
	"path/filepath"
)

type IoWrapper func(io.ReadCloser) (io.ReadCloser, error)

type readWrapper struct {
	orig io.ReadCloser
	io.Reader
}

func (b *readWrapper) Close() error {
	return b.orig.Close()
}

func bzipWrapper(r io.ReadCloser) (io.ReadCloser, error) {
	return &readWrapper{orig: r, Reader: bzip2.NewReader(r)}, nil
}

type readCloseWrapper struct {
	orig io.ReadCloser
	io.ReadCloser
}

func (g *readCloseWrapper) Close() error {
	g.ReadCloser.Close()
	return g.orig.Close()
}

func gzipWrapper(r io.ReadCloser) (io.ReadCloser, error) {
	gz, err := gzip.NewReader(r)
	if err != nil {
		r.Close()
		return nil, err
	}
	return &readCloseWrapper{orig: r, ReadCloser: gz}, nil
}

var CompressionType = map[string]IoWrapper{
	".bz2":   bzipWrapper,
	".bzip2": bzipWrapper,
	".gz":    gzipWrapper,
}

const DefaultBufferSize = 65536

// Open opens a file (possibly compressed) and returns a suitable
// buffered ReadCloser.
func Open(file string) (io.ReadCloser, error) {
	br, err := OpenBufferedSize(file, DefaultBufferSize)
	if err != nil {
		return nil, err
	}

	if compressor, ok := CompressionType[filepath.Ext(file)]; ok {
		return compressor(br)
	}
	return br, nil
}

// OpenBufferedSize opens a file for buffered I/O with the given
// buffer size.
func OpenBufferedSize(file string, size int) (io.ReadCloser, error) {
	inf, err := os.Open(file)
	if err != nil {
		return nil, err
	}
	return &readWrapper{orig: inf, Reader: bufio.NewReaderSize(inf, size)}, nil
}
<commit_msg>Typo fixes.<commit_after>// Package compfile returns ReadClosers for files that are possibly
// compressed, guessing the compression type based on the file
// extension.
package compfile

import (
	"bufio"
	"compress/bzip2"
	"compress/gzip"
	"io"
	"os"
	"path/filepath"
)

type IoWrapper func(io.ReadCloser) (io.ReadCloser, error)

type readWrapper struct {
	orig io.ReadCloser
	io.Reader
}

func (b *readWrapper) Close() error {
	return b.orig.Close()
}

func bzipWrapper(r io.ReadCloser) (io.ReadCloser, error) {
	return &readWrapper{orig: r, Reader: bzip2.NewReader(r)}, nil
}

type readCloseWrapper struct {
	orig io.ReadCloser
	io.ReadCloser
}

func (g *readCloseWrapper) Close() error {
	g.ReadCloser.Close()
	return g.orig.Close()
}

func gzipWrapper(r io.ReadCloser) (io.ReadCloser, error) {
	gz, err := gzip.NewReader(r)
	if err != nil {
		r.Close()
		return nil, err
	}
	return &readCloseWrapper{orig: r, ReadCloser: gz}, nil
}

var CompressionType = map[string]IoWrapper{
	".bz2":   bzipWrapper,
	".bzip2": bzipWrapper,
	".gz":    gzipWrapper,
}

const DefaultBufferSize = 65536

// Open opens a file (possibly compressed) and returns a suitable
// buffered ReadCloser.
func Open(file string) (io.ReadCloser, error) {
	br, err := OpenBufferedSize(file, DefaultBufferSize)
	if err != nil {
		return nil, err
	}

	if decompressor, ok := CompressionType[filepath.Ext(file)]; ok {
		return decompressor(br)
	}
	return br, nil
}

// OpenBufferedSize opens a file for buffered I/O with the given
// buffer size.
func OpenBufferedSize(file string, size int) (io.ReadCloser, error) {
	inf, err := os.Open(file)
	if err != nil {
		return nil, err
	}
	return &readWrapper{orig: inf, Reader: bufio.NewReaderSize(inf, size)}, nil
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"log"
	"math/rand"
	"os"
	"sync"
	"time"

	"github.com/AdRoll/goamz/aws"
	"github.com/AdRoll/goamz/kinesis"
)

func main() {
	rand.Seed(time.Now().UnixNano()) // takes the current time in nanoseconds as the seed

	var pub = os.Getenv("AWSPUB")
	var secret = os.Getenv("AWSSecret")
	auth := aws.Auth{AccessKey: pub, SecretKey: secret}
	K := kinesis.New(auth, aws.USEast)
	var wg sync.WaitGroup
	for i := 0; i < 100; i++ {
		problemMap := make(map[string]int)
		problemMap["Num1"] = rand.Intn(100)
		problemMap["Num2"] = rand.Intn(100)
		jsonData, jsonErr := json.Marshal(problemMap)
		if jsonErr != nil {
			log.Println("Error:", jsonErr)
			continue
		}
		wg.Add(1)
		go func() {
			defer wg.Done()
			_, err2 := K.PutRecord("math-problems", "math-p", jsonData, "", "")
			log.Println(problemMap["Num1"], "+", problemMap["Num2"], "...sent!")
			if err2 != nil {
				log.Println("Error:", err2)
			}
		}()
		wg.Wait()
	}
}
<commit_msg>update log output<commit_after>package main

import (
	"encoding/json"
	"log"
	"math/rand"
	"os"
	"sync"
	"time"

	"github.com/AdRoll/goamz/aws"
	"github.com/AdRoll/goamz/kinesis"
)

func main() {
	rand.Seed(time.Now().UnixNano()) // takes the current time in nanoseconds as the seed

	var pub = os.Getenv("AWSPUB")
	var secret = os.Getenv("AWSSecret")
	auth := aws.Auth{AccessKey: pub, SecretKey: secret}
	K := kinesis.New(auth, aws.USEast)
	var wg sync.WaitGroup
	for i := 0; i < 100; i++ {
		problemMap := make(map[string]int)
		problemMap["Num1"] = rand.Intn(100)
		problemMap["Num2"] = rand.Intn(100)
		jsonData, jsonErr := json.Marshal(problemMap)
		if jsonErr != nil {
			log.Println("Error:", jsonErr)
			continue
		}
		wg.Add(1)
		go func() {
			defer wg.Done()
			_, err2 := K.PutRecord("math-problems", "math-p", jsonData, "", "")
			log.Println("[", problemMap["Num1"], ",", problemMap["Num2"], "] ...sent!")
			if err2 != nil {
				log.Println("Error:", err2)
			}
		}()
		wg.Wait()
	}
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"fmt"
	_ "github.com/PuerkitoBio/goquery"
	"github.com/headzoo/surf"
)

func main() {
	//initiate browser
	bow := surf.NewBrowser()
	bow.Open("https://www.instagram.com/shubhothegreat")

	scr := bow.Find("script").Eq(6)

	extracted_react_data := []byte(scr.Text()[21 : len(scr.Text())-1])

	var parsed interface{}
	json.Unmarshal(extracted_react_data, &parsed)
	parse, _ := parsed.(map[string]interface{})["entry_data"].(map[string]interface{})["ProfilePage"].([]interface{})[0].(map[string]interface{})["user"].(map[string]interface{})["media"].(map[string]interface{})

	//posts
	posts, _ := parse["nodes"].([]interface{})

	for i := range posts {
		post_uri, _ := posts[i].(map[string]interface{})["display_src"].(string)
		fmt.Println(post_uri)
	}
}
<commit_msg>Fetching all the photos<commit_after>package main

import (
	"encoding/json"
	"fmt"
	_ "github.com/PuerkitoBio/goquery"
	"github.com/headzoo/surf"
)

var ct int = 0

func page_iterator(uri string) {
	//initiate browser
	bow := surf.NewBrowser()
	bow.Open(uri)

	scr := bow.Find("script").Eq(6)

	extracted_react_data := []byte(scr.Text()[21 : len(scr.Text())-1])

	var parsed interface{}
	json.Unmarshal(extracted_react_data, &parsed)
	parse, _ := parsed.(map[string]interface{})["entry_data"].(map[string]interface{})["ProfilePage"].([]interface{})[0].(map[string]interface{})["user"].(map[string]interface{})["media"].(map[string]interface{})

	//posts
	posts, _ := parse["nodes"].([]interface{})

	// for i := range posts {
	// 	post_uri, _ := posts[i].(map[string]interface{})["display_src"].(string)
	// 	fmt.Println(post_uri)
	// }

	ct = ct + len(posts)
	//next_page
	page_info, _ := parse["page_info"].(map[string]interface{})
	hasnextpage, _ := page_info["has_next_page"].(bool)

	fmt.Println(hasnextpage)

	if hasnextpage {
		end_cursor := page_info["end_cursor"].(string)
		fmt.Println(page_info)
		page_iterator(uri + "/?max_id=" + end_cursor)
	}

}

func main() {
	page_iterator("https://www.instagram.com/rishi_raj95")
}
<|endoftext|>


<commit_before>// khan
// https://github.com/topfreegames/khan
//
// Licensed under the MIT license:
// http://www.opensource.org/licenses/mit-license
// Copyright © 2016 Top Free Games <backend@tfgco.com>

package api

import (
	"fmt"
	"net/http"
	"time"

	"github.com/labstack/echo"
	"github.com/topfreegames/khan/log"
	"github.com/topfreegames/khan/models"
	"github.com/uber-go/zap"
)

// CreatePlayerHandler is the handler responsible for creating new players
func CreatePlayerHandler(app *App) func(c echo.Context) error {
	return func(c echo.Context) error {
		c.Set("route", "CreatePlayer")
		start := time.Now()
		gameID := c.Param("gameID")

		db := app.Db(c.StdContext())

		logger := app.Logger.With(
			zap.String("source", "playerHandler"),
			zap.String("operation", "createPlayer"),
			zap.String("gameID", gameID),
		)

		var payload CreatePlayerPayload
		err := WithSegment("payload", c, func() error {
			if err := LoadJSONPayload(&payload, c, logger); err != nil {
				return err
			}
			return nil
		})
		if err != nil {
			return FailWith(http.StatusBadRequest, err.Error(), c)
		}

		var player *models.Player
		err = WithSegment("player-create", c, func() error {
			log.D(logger, "Creating player...")
			player, err = models.CreatePlayer(
				db,
				logger,
				app.EncryptionKey,
				gameID,
				payload.PublicID,
				payload.Name,
				payload.Metadata,
			)

			if err != nil {
				log.E(logger, "Player creation failed.", func(cm log.CM) {
					cm.Write(zap.Error(err))
				})
				return err
			}
			return nil
		})
		if err != nil {
			return FailWith(http.StatusInternalServerError, err.Error(), c)
		}

		result := map[string]interface{}{
			"success":  true,
			"gameID":   gameID,
			"publicID": player.PublicID,
			"name":     player.Name,
			"metadata": player.Metadata,
		}

		err = WithSegment("hook-dispatch", c, func() error {
			err = app.DispatchHooks(
				gameID,
				models.PlayerCreatedHook,
				player.Serialize(app.EncryptionKey),
			)
			if err != nil {
				log.E(logger, "Player creation hook dispatch failed.", func(cm log.CM) {
					cm.Write(zap.Error(err))
				})
				return err
			}
			return nil
		})
		if err != nil {
			return FailWith(http.StatusInternalServerError, err.Error(), c)
		}

		log.D(logger, "Player created successfully.", func(cm log.CM) {
			cm.Write(zap.Duration("duration", time.Now().Sub(start)))
		})

		return SucceedWith(result, c)
	}
}

// UpdatePlayerHandler is the handler responsible for updating existing
func UpdatePlayerHandler(app *App) func(c echo.Context) error {
	return func(c echo.Context) error {
		c.Set("route", "UpdatePlayer")
		start := time.Now()
		gameID := c.Param("gameID")
		playerPublicID := c.Param("playerPublicID")

		db := app.Db(c.StdContext())

		logger := app.Logger.With(
			zap.String("source", "playerHandler"),
			zap.String("operation", "updatePlayer"),
			zap.String("gameID", gameID),
			zap.String("playerPublicID", playerPublicID),
		)

		var payload UpdatePlayerPayload
		err := WithSegment("payload", c, func() error {
			return LoadJSONPayload(&payload, c, logger)
		})
		if err != nil {
			return FailWith(http.StatusBadRequest, err.Error(), c)
		}

		var player, beforeUpdatePlayer *models.Player
		var game *models.Game

		err = WithSegment("game-retrieve", c, func() error {
			log.D(logger, "Retrieving game...")
			game, err = models.GetGameByPublicID(db, gameID)

			if err != nil {
				return err
			}
			log.D(logger, "Game retrieved successfully")
			return nil
		})
		if err != nil {
			return FailWith(http.StatusBadRequest, err.Error(), c)
		}

		err = WithSegment("player-retrieve", c, func() error {
			log.D(logger, "Retrieving player...")
			beforeUpdatePlayer, err = models.GetPlayerByPublicID(db, app.EncryptionKey, gameID, playerPublicID)
			if err != nil && err.Error() != (&models.ModelNotFoundError{Type: "Player", ID: playerPublicID}).Error() {
				return err
			}
			log.D(logger, "Player retrieved successfully")
			return nil
		})
		if err != nil {
			return FailWith(http.StatusBadRequest, err.Error(), c)
		}

		err = WithSegment("player-update", c, func() error {
			err = WithSegment("player-update-query", c, func() error {
				log.D(logger, "Updating player...")
				player, err = models.UpdatePlayer(
					db,
					logger,
					app.EncryptionKey,
					gameID,
					playerPublicID,
					payload.Name,
					payload.Metadata,
				)
				return err
			})

			if err != nil {
				log.E(logger, "Updating player failed.", func(cm log.CM) {
					cm.Write(zap.Error(err))
				})
				return err
			}
			return nil
		})
		if err != nil {
			return FailWith(http.StatusInternalServerError, err.Error(), c)
		}

		err = WithSegment("hook-dispatch", c, func() error {
			shouldDispatch := validateUpdatePlayerDispatch(game, beforeUpdatePlayer, player, payload.Metadata, logger)
			if shouldDispatch {
				log.D(logger, "Dispatching player update hooks...")
				err = app.DispatchHooks(
					gameID,
					models.PlayerUpdatedHook,
					player.Serialize(app.EncryptionKey),
				)
				if err != nil {
					log.E(logger, "Update player hook dispatch failed.", func(cm log.CM) {
						cm.Write(zap.Error(err))
					})
					return err
				}
			}
			return nil
		})
		if err != nil {
			return FailWith(http.StatusInternalServerError, err.Error(), c)
		}

		log.D(logger, "Player updated successfully.", func(cm log.CM) {
			cm.Write(zap.Duration("duration", time.Now().Sub(start)))
		})
		return SucceedWith(map[string]interface{}{}, c)
	}
}

// RetrievePlayerHandler is the handler responsible for returning details for a given player
func RetrievePlayerHandler(app *App) func(c echo.Context) error {
	return func(c echo.Context) error {
		c.Set("route", "RetrievePlayer")
		start := time.Now()
		gameID := c.Param("gameID")
		publicID := c.Param("playerPublicID")

		l := app.Logger.With(
			zap.String("source", "playerHandler"),
			zap.String("operation", "retrievePlayer"),
			zap.String("gameID", gameID),
			zap.String("playerPublicID", publicID),
		)

		log.D(l, "Getting DB connection...")
		db, err := app.GetCtxDB(c)
		if err != nil {
			log.E(l, "Failed to connect to DB.", func(cm log.CM) {
				cm.Write(zap.Error(err))
			})
			return FailWith(http.StatusInternalServerError, err.Error(), c)
		}
		log.D(l, "DB Connection successful.")

		var player map[string]interface{}
		err = WithSegment("player-get-details", c, func() error {
			log.D(l, "Retrieving player details...")
			player, err = models.GetPlayerDetails(
				db,
				app.EncryptionKey,
				gameID,
				publicID,
			)
			return err
		})

		if err != nil {
			if err.Error() == fmt.Sprintf("Player was not found with id: %s", publicID) {
				log.D(l, "Player was not found.", func(cm log.CM) {
					cm.Write(zap.Error(err))
				})
				return FailWith(http.StatusNotFound, err.Error(), c)
			}

			log.E(l, "Retrieve player details failed.", func(cm log.CM) {
				cm.Write(zap.Error(err))
			})
			return FailWith(http.StatusInternalServerError, err.Error(), c)
		}

		log.D(l, "Player details retrieved successfully.", func(cm log.CM) {
			cm.Write(zap.Duration("duration", time.Now().Sub(start)))
		})

		return SucceedWith(player, c)
	}
}
<commit_msg>Add transactions to write player (#71)<commit_after>// khan
// https://github.com/topfreegames/khan
//
// Licensed under the MIT license:
// http://www.opensource.org/licenses/mit-license
// Copyright © 2016 Top Free Games <backend@tfgco.com>

package api

import (
	"fmt"
	"net/http"
	"time"

	"github.com/labstack/echo"
	"github.com/topfreegames/extensions/v9/gorp/interfaces"
	"github.com/topfreegames/khan/log"
	"github.com/topfreegames/khan/models"
	"github.com/uber-go/zap"
)

// CreatePlayerHandler is the handler responsible for creating new players
func CreatePlayerHandler(app *App) func(c echo.Context) error {
	return func(c echo.Context) error {
		c.Set("route", "CreatePlayer")
		start := time.Now()
		gameID := c.Param("gameID")

		logger := app.Logger.With(
			zap.String("source", "playerHandler"),
			zap.String("operation", "createPlayer"),
			zap.String("gameID", gameID),
		)

		var payload CreatePlayerPayload
		err := WithSegment("payload", c, func() error {
			if err := LoadJSONPayload(&payload, c, logger); err != nil {
				return err
			}
			return nil
		})
		if err != nil {
			return FailWith(http.StatusBadRequest, err.Error(), c)
		}

		var transaction interfaces.Transaction
		transaction, err = app.BeginTrans(c.StdContext(), logger)
		if err != nil {
			return FailWith(http.StatusInternalServerError, err.Error(), c)
		}

		var player *models.Player
		err = WithSegment("player-create", c, func() error {
			log.D(logger, "Creating player...")
			player, err = models.CreatePlayer(
				transaction,
				logger,
				app.EncryptionKey,
				gameID,
				payload.PublicID,
				payload.Name,
				payload.Metadata,
			)

			if err != nil {
				log.E(logger, "Player creation failed.", func(cm log.CM) {
					cm.Write(zap.Error(err))
				})
				return err
			}
			return nil
		})
		if err != nil {
			errRollback := app.Rollback(transaction, "Player creation failed, rolling back", c, logger, err)
			if errRollback != nil {
				return FailWith(http.StatusInternalServerError, fmt.Sprint(err.Error(), ", rolback error: ", errRollback.Error()), c)
			}
			return FailWith(http.StatusInternalServerError, err.Error(), c)
		}

		err = app.Commit(transaction, "Player created successful", c, logger)
		if err != nil {
			return FailWith(http.StatusInternalServerError, err.Error(), c)
		}

		result := map[string]interface{}{
			"success":  true,
			"gameID":   gameID,
			"publicID": player.PublicID,
			"name":     player.Name,
			"metadata": player.Metadata,
		}

		err = WithSegment("hook-dispatch", c, func() error {
			err = app.DispatchHooks(
				gameID,
				models.PlayerCreatedHook,
				player.Serialize(app.EncryptionKey),
			)
			if err != nil {
				log.E(logger, "Player creation hook dispatch failed.", func(cm log.CM) {
					cm.Write(zap.Error(err))
				})
				return err
			}
			return nil
		})
		if err != nil {
			return FailWith(http.StatusInternalServerError, err.Error(), c)
		}

		log.D(logger, "Player created successfully.", func(cm log.CM) {
			cm.Write(zap.Duration("duration", time.Now().Sub(start)))
		})

		return SucceedWith(result, c)
	}
}

// UpdatePlayerHandler is the handler responsible for updating existing
func UpdatePlayerHandler(app *App) func(c echo.Context) error {
	return func(c echo.Context) error {
		c.Set("route", "UpdatePlayer")
		start := time.Now()
		gameID := c.Param("gameID")
		playerPublicID := c.Param("playerPublicID")

		db := app.Db(c.StdContext())

		logger := app.Logger.With(
			zap.String("source", "playerHandler"),
			zap.String("operation", "updatePlayer"),
			zap.String("gameID", gameID),
			zap.String("playerPublicID", playerPublicID),
		)

		var payload UpdatePlayerPayload
		err := WithSegment("payload", c, func() error {
			return LoadJSONPayload(&payload, c, logger)
		})
		if err != nil {
			return FailWith(http.StatusBadRequest, err.Error(), c)
		}

		var player, beforeUpdatePlayer *models.Player
		var game *models.Game

		err = WithSegment("game-retrieve", c, func() error {
			log.D(logger, "Retrieving game...")
			game, err = models.GetGameByPublicID(db, gameID)

			if err != nil {
				return err
			}
			log.D(logger, "Game retrieved successfully")
			return nil
		})
		if err != nil {
			return FailWith(http.StatusBadRequest, err.Error(), c)
		}

		err = WithSegment("player-retrieve", c, func() error {
			log.D(logger, "Retrieving player...")
			beforeUpdatePlayer, err = models.GetPlayerByPublicID(db, app.EncryptionKey, gameID, playerPublicID)
			if err != nil && err.Error() != (&models.ModelNotFoundError{Type: "Player", ID: playerPublicID}).Error() {
				return err
			}
			log.D(logger, "Player retrieved successfully")
			return nil
		})
		if err != nil {
			return FailWith(http.StatusBadRequest, err.Error(), c)
		}

		var transaction interfaces.Transaction
		transaction, err = app.BeginTrans(c.StdContext(), logger)
		if err != nil {
			return FailWith(http.StatusInternalServerError, err.Error(), c)
		}

		err = WithSegment("player-update", c, func() error {
			err = WithSegment("player-update-query", c, func() error {
				log.D(logger, "Updating player...")
				player, err = models.UpdatePlayer(
					transaction,
					logger,
					app.EncryptionKey,
					gameID,
					playerPublicID,
					payload.Name,
					payload.Metadata,
				)
				return err
			})

			if err != nil {
				log.E(logger, "Updating player failed.", func(cm log.CM) {
					cm.Write(zap.Error(err))
				})
				return err
			}
			return nil
		})
		if err != nil {
			errRollback := app.Rollback(transaction, "Player update failed, rolling back", c, logger, err)
			if errRollback != nil {
				return FailWith(http.StatusInternalServerError, fmt.Sprint(err.Error(), ", rolback error: ", errRollback.Error()), c)
			}
			return FailWith(http.StatusInternalServerError, err.Error(), c)
		}

		err = app.Commit(transaction, "Player created successful", c, logger)
		if err != nil {
			return FailWith(http.StatusInternalServerError, err.Error(), c)
		}

		err = WithSegment("hook-dispatch", c, func() error {
			shouldDispatch := validateUpdatePlayerDispatch(game, beforeUpdatePlayer, player, payload.Metadata, logger)
			if shouldDispatch {
				log.D(logger, "Dispatching player update hooks...")
				err = app.DispatchHooks(
					gameID,
					models.PlayerUpdatedHook,
					player.Serialize(app.EncryptionKey),
				)
				if err != nil {
					log.E(logger, "Update player hook dispatch failed.", func(cm log.CM) {
						cm.Write(zap.Error(err))
					})
					return err
				}
			}
			return nil
		})
		if err != nil {
			return FailWith(http.StatusInternalServerError, err.Error(), c)
		}

		log.D(logger, "Player updated successfully.", func(cm log.CM) {
			cm.Write(zap.Duration("duration", time.Now().Sub(start)))
		})
		return SucceedWith(map[string]interface{}{}, c)
	}
}

// RetrievePlayerHandler is the handler responsible for returning details for a given player
func RetrievePlayerHandler(app *App) func(c echo.Context) error {
	return func(c echo.Context) error {
		c.Set("route", "RetrievePlayer")
		start := time.Now()
		gameID := c.Param("gameID")
		publicID := c.Param("playerPublicID")

		l := app.Logger.With(
			zap.String("source", "playerHandler"),
			zap.String("operation", "retrievePlayer"),
			zap.String("gameID", gameID),
			zap.String("playerPublicID", publicID),
		)

		log.D(l, "Getting DB connection...")
		db, err := app.GetCtxDB(c)
		if err != nil {
			log.E(l, "Failed to connect to DB.", func(cm log.CM) {
				cm.Write(zap.Error(err))
			})
			return FailWith(http.StatusInternalServerError, err.Error(), c)
		}
		log.D(l, "DB Connection successful.")

		var player map[string]interface{}
		err = WithSegment("player-get-details", c, func() error {
			log.D(l, "Retrieving player details...")
			player, err = models.GetPlayerDetails(
				db,
				app.EncryptionKey,
				gameID,
				publicID,
			)
			return err
		})

		if err != nil {
			if err.Error() == fmt.Sprintf("Player was not found with id: %s", publicID) {
				log.D(l, "Player was not found.", func(cm log.CM) {
					cm.Write(zap.Error(err))
				})
				return FailWith(http.StatusNotFound, err.Error(), c)
			}

			log.E(l, "Retrieve player details failed.", func(cm log.CM) {
				cm.Write(zap.Error(err))
			})
			return FailWith(http.StatusInternalServerError, err.Error(), c)
		}

		log.D(l, "Player details retrieved successfully.", func(cm log.CM) {
			cm.Write(zap.Duration("duration", time.Now().Sub(start)))
		})

		return SucceedWith(player, c)
	}
}
<|endoftext|>


<commit_before>package config

import (
	"fmt"
	"github.com/litl/galaxy/utils"
	"strconv"
	"strings"
)

type AppConfig struct {
	// ID is used for ordering and conflict resolution.
	// Usualy set to time.Now().UnixNano()
	Name            string `redis:"name"`
	versionVMap     *utils.VersionedMap
	environmentVMap *utils.VersionedMap
	portsVMap       *utils.VersionedMap
	runtimeVMap     *utils.VersionedMap
}

func NewAppConfig(app, version string) *AppConfig {
	svcCfg := &AppConfig{
		Name:            app,
		versionVMap:     utils.NewVersionedMap(),
		environmentVMap: utils.NewVersionedMap(),
		portsVMap:       utils.NewVersionedMap(),
		runtimeVMap:     utils.NewVersionedMap(),
	}
	svcCfg.SetVersion(version)

	return svcCfg
}

func NewAppConfigWithEnv(app, version string, env map[string]string) *AppConfig {
	svcCfg := NewAppConfig(app, version)

	for k, v := range env {
		svcCfg.environmentVMap.Set(k, v)
	}

	return svcCfg
}

// Env returns a map representing the runtime environment for the container.
// Changes to this map have no effect.
func (s *AppConfig) Env() map[string]string {
	env := map[string]string{}
	for _, k := range s.environmentVMap.Keys() {
		val := s.environmentVMap.Get(k)
		if val != "" {
			env[k] = val
		}
	}
	return env
}

func (s *AppConfig) EnvSet(key, value string) {
	s.environmentVMap.SetVersion(key, value, s.nextID())
}

func (s *AppConfig) EnvGet(key string) string {
	return s.environmentVMap.Get(key)
}

func (s *AppConfig) Version() string {
	return s.versionVMap.Get("version")
}

func (s *AppConfig) SetVersion(version string) {
	s.versionVMap.SetVersion("version", version, s.nextID())
}

func (s *AppConfig) VersionID() string {
	return s.versionVMap.Get("versionID")
}

func (s *AppConfig) SetVersionID(versionID string) {
	s.versionVMap.SetVersion("versionID", versionID, s.nextID())
}

func (s *AppConfig) Ports() map[string]string {
	ports := map[string]string{}
	for _, k := range s.portsVMap.Keys() {
		val := s.portsVMap.Get(k)
		if val != "" {
			ports[k] = val
		}
	}
	return ports
}

func (s *AppConfig) ClearPorts() {
	for _, k := range s.portsVMap.Keys() {
		s.portsVMap.SetVersion(k, "", s.nextID())
	}
}

func (s *AppConfig) AddPort(port, portType string) {
	s.portsVMap.Set(port, portType)
}

func (s *AppConfig) ID() int64 {
	id := int64(0)
	for _, vmap := range []*utils.VersionedMap{
		s.environmentVMap,
		s.versionVMap,
		s.portsVMap,
	} {
		if vmap.LatestVersion() > id {
			id = vmap.LatestVersion()
		}
	}
	return id
}

func (s *AppConfig) ContainerName() string {
	return s.Name + "_" + strconv.FormatInt(s.ID(), 10)
}

func (s *AppConfig) nextID() int64 {
	return s.ID() + 1
}

func (s *AppConfig) SetProcesses(pool string, count int) {
	key := fmt.Sprintf("%s-ps", pool)
	s.runtimeVMap.Set(key, strconv.FormatInt(int64(count), 10))
}

func (s *AppConfig) GetProcesses(pool string) int {
	key := fmt.Sprintf("%s-ps", pool)
	ps := s.runtimeVMap.Get(key)
	if ps == "" {
		return -1
	}
	count, _ := strconv.ParseInt(ps, 10, 16)
	return int(count)
}

func (s *AppConfig) RuntimePools() []string {
	keys := s.runtimeVMap.Keys()
	pools := []string{}
	for _, k := range keys {
		pool := k[:strings.Index(k, "-")]
		if !utils.StringInSlice(pool, pools) {
			pools = append(pools, pool)
		}
	}
	return pools
}

func (s *AppConfig) SetMemory(pool string, mem string) {
	key := fmt.Sprintf("%s-mem", pool)
	s.runtimeVMap.Set(key, mem)
}

func (s *AppConfig) GetMemory(pool string) string {
	key := fmt.Sprintf("%s-mem", pool)
	return s.runtimeVMap.Get(key)
}
<commit_msg>commander: make runtime config changes update the config version<commit_after>package config

import (
	"fmt"
	"github.com/litl/galaxy/utils"
	"strconv"
	"strings"
)

type AppConfig struct {
	// ID is used for ordering and conflict resolution.
	// Usualy set to time.Now().UnixNano()
	Name            string `redis:"name"`
	versionVMap     *utils.VersionedMap
	environmentVMap *utils.VersionedMap
	portsVMap       *utils.VersionedMap
	runtimeVMap     *utils.VersionedMap
}

func NewAppConfig(app, version string) *AppConfig {
	svcCfg := &AppConfig{
		Name:            app,
		versionVMap:     utils.NewVersionedMap(),
		environmentVMap: utils.NewVersionedMap(),
		portsVMap:       utils.NewVersionedMap(),
		runtimeVMap:     utils.NewVersionedMap(),
	}
	svcCfg.SetVersion(version)

	return svcCfg
}

func NewAppConfigWithEnv(app, version string, env map[string]string) *AppConfig {
	svcCfg := NewAppConfig(app, version)

	for k, v := range env {
		svcCfg.environmentVMap.Set(k, v)
	}

	return svcCfg
}

// Env returns a map representing the runtime environment for the container.
// Changes to this map have no effect.
func (s *AppConfig) Env() map[string]string {
	env := map[string]string{}
	for _, k := range s.environmentVMap.Keys() {
		val := s.environmentVMap.Get(k)
		if val != "" {
			env[k] = val
		}
	}
	return env
}

func (s *AppConfig) EnvSet(key, value string) {
	s.environmentVMap.SetVersion(key, value, s.nextID())
}

func (s *AppConfig) EnvGet(key string) string {
	return s.environmentVMap.Get(key)
}

func (s *AppConfig) Version() string {
	return s.versionVMap.Get("version")
}

func (s *AppConfig) SetVersion(version string) {
	s.versionVMap.SetVersion("version", version, s.nextID())
}

func (s *AppConfig) VersionID() string {
	return s.versionVMap.Get("versionID")
}

func (s *AppConfig) SetVersionID(versionID string) {
	s.versionVMap.SetVersion("versionID", versionID, s.nextID())
}

func (s *AppConfig) Ports() map[string]string {
	ports := map[string]string{}
	for _, k := range s.portsVMap.Keys() {
		val := s.portsVMap.Get(k)
		if val != "" {
			ports[k] = val
		}
	}
	return ports
}

func (s *AppConfig) ClearPorts() {
	for _, k := range s.portsVMap.Keys() {
		s.portsVMap.SetVersion(k, "", s.nextID())
	}
}

func (s *AppConfig) AddPort(port, portType string) {
	s.portsVMap.Set(port, portType)
}

func (s *AppConfig) ID() int64 {
	id := int64(0)
	for _, vmap := range []*utils.VersionedMap{
		s.environmentVMap,
		s.versionVMap,
		s.portsVMap,
		s.runtimeVMap,
	} {
		if vmap.LatestVersion() > id {
			id = vmap.LatestVersion()
		}
	}
	return id
}

func (s *AppConfig) ContainerName() string {
	return s.Name + "_" + strconv.FormatInt(s.ID(), 10)
}

func (s *AppConfig) nextID() int64 {
	return s.ID() + 1
}

func (s *AppConfig) SetProcesses(pool string, count int) {
	key := fmt.Sprintf("%s-ps", pool)
	s.runtimeVMap.SetVersion(key, strconv.FormatInt(int64(count), 10), s.nextID())
}

func (s *AppConfig) GetProcesses(pool string) int {
	key := fmt.Sprintf("%s-ps", pool)
	ps := s.runtimeVMap.Get(key)
	if ps == "" {
		return -1
	}
	count, _ := strconv.ParseInt(ps, 10, 16)
	return int(count)
}

func (s *AppConfig) RuntimePools() []string {
	keys := s.runtimeVMap.Keys()
	pools := []string{}
	for _, k := range keys {
		pool := k[:strings.Index(k, "-")]
		if !utils.StringInSlice(pool, pools) {
			pools = append(pools, pool)
		}
	}
	return pools
}

func (s *AppConfig) SetMemory(pool string, mem string) {
	key := fmt.Sprintf("%s-mem", pool)
	s.runtimeVMap.Set(key, mem)
}

func (s *AppConfig) GetMemory(pool string) string {
	key := fmt.Sprintf("%s-mem", pool)
	return s.runtimeVMap.Get(key)
}
<|endoftext|>


<commit_before>package api

import (
	"fmt"
	"net/http"
	"strings"

	"github.com/NebulousLabs/Sia/modules"
	"github.com/NebulousLabs/Sia/types"

	"github.com/julienschmidt/httprouter"
)

// DownloadQueue contains the renter's download queue.
type RenterDownloadQueue struct {
	Downloads []modules.DownloadInfo `json:"downloads"`
}

// RenterFiles lists the files known to the renter.
type RenterFiles struct {
	Files []modules.FileInfo `json:"files"`
}

// RenterLoad lists files that were loaded into the renter.
type RenterLoad struct {
	FilesAdded []string `json:"filesadded"`
}

// RenterShareASCII contains an ASCII-encoded .sia file.
type RenterShareASCII struct {
	ASCIIsia string `json:"asciisia"`
}

// ActiveHosts lists active hosts on the network.
type ActiveHosts struct {
	Hosts []modules.HostDBEntry `json:"hosts"`
}

// renterAllowanceHandlerGET handles the API call to get the allowance.
func (srv *Server) renterAllowanceHandlerGET(w http.ResponseWriter, req *http.Request, _ httprouter.Params) {
	writeJSON(w, srv.renter.Allowance())
}

// renterAllowanceHandlerPOST handles the API call to set the allowance.
func (srv *Server) renterAllowanceHandlerPOST(w http.ResponseWriter, req *http.Request, _ httprouter.Params) {
	// scan values
	funds, ok := scanAmount(req.FormValue("funds"))
	if !ok {
		writeError(w, "Couldn't parse funds", http.StatusBadRequest)
		return
	}
	var hosts uint64
	_, err := fmt.Sscan(req.FormValue("hosts"), &hosts)
	if err != nil {
		writeError(w, "Couldn't parse hosts: "+err.Error(), http.StatusBadRequest)
		return
	}
	var period types.BlockHeight
	_, err = fmt.Sscan(req.FormValue("period"), &period)
	if err != nil {
		writeError(w, "Couldn't parse period: "+err.Error(), http.StatusBadRequest)
		return
	}
	var renewWindow types.BlockHeight
	_, err = fmt.Sscan(req.FormValue("renewwindow"), &renewWindow)
	if err != nil {
		writeError(w, "Couldn't parse renewwindow: "+err.Error(), http.StatusBadRequest)
		return
	}

	err = srv.renter.SetAllowance(modules.Allowance{
		Funds:       funds,
		Hosts:       hosts,
		Period:      period,
		RenewWindow: renewWindow,
	})
	if err != nil {
		writeError(w, err.Error(), http.StatusBadRequest)
		return
	}
	writeSuccess(w)
}

// renterDownloadsHandler handles the API call to request the download queue.
func (srv *Server) renterDownloadsHandler(w http.ResponseWriter, req *http.Request, _ httprouter.Params) {
	writeJSON(w, RenterDownloadQueue{
		Downloads: srv.renter.DownloadQueue(),
	})
}

// renterLoadHandler handles the API call to load a '.sia' file.
func (srv *Server) renterLoadHandler(w http.ResponseWriter, req *http.Request, _ httprouter.Params) {
	files, err := srv.renter.LoadSharedFiles(req.FormValue("source"))
	if err != nil {
		writeError(w, err.Error(), http.StatusBadRequest)
		return
	}

	writeJSON(w, RenterLoad{FilesAdded: files})
}

// renterLoadAsciiHandler handles the API call to load a '.sia' file
// in ASCII form.
func (srv *Server) renterLoadAsciiHandler(w http.ResponseWriter, req *http.Request, _ httprouter.Params) {
	files, err := srv.renter.LoadSharedFilesAscii(req.FormValue("asciisia"))
	if err != nil {
		writeError(w, err.Error(), http.StatusBadRequest)
		return
	}

	writeJSON(w, RenterLoad{FilesAdded: files})
}

// renterRenameHandler handles the API call to rename a file entry in the
// renter.
func (srv *Server) renterRenameHandler(w http.ResponseWriter, req *http.Request, ps httprouter.Params) {
	err := srv.renter.RenameFile(strings.TrimPrefix(ps.ByName("siapath"), "/"), req.FormValue("newsiapath"))
	if err != nil {
		writeError(w, err.Error(), http.StatusBadRequest)
		return
	}

	writeSuccess(w)
}

// renterFilesHandler handles the API call to list all of the files.
func (srv *Server) renterFilesHandler(w http.ResponseWriter, req *http.Request, _ httprouter.Params) {
	writeJSON(w, RenterFiles{
		Files: srv.renter.FileList(),
	})
}

// renterDeleteHander handles the API call to delete a file entry from the
// renter.
func (srv *Server) renterDeleteHandler(w http.ResponseWriter, req *http.Request, ps httprouter.Params) {
	err := srv.renter.DeleteFile(strings.TrimPrefix(ps.ByName("siapath"), "/"))
	if err != nil {
		writeError(w, err.Error(), http.StatusBadRequest)
		return
	}

	writeSuccess(w)
}

// renterDownloadHandler handles the API call to download a file.
func (srv *Server) renterDownloadHandler(w http.ResponseWriter, req *http.Request, ps httprouter.Params) {
	err := srv.renter.Download(strings.TrimPrefix(ps.ByName("siapath"), "/"), req.FormValue("destination"))
	if err != nil {
		writeError(w, "Download failed: "+err.Error(), http.StatusInternalServerError)
		return
	}

	writeSuccess(w)
}

// renterShareHandler handles the API call to create a '.sia' file that
// shares a set of file.
func (srv *Server) renterShareHandler(w http.ResponseWriter, req *http.Request, ps httprouter.Params) {
	err := srv.renter.ShareFiles(strings.Split(req.FormValue("siapaths"), ","), req.FormValue("destination"))
	if err != nil {
		writeError(w, err.Error(), http.StatusBadRequest)
		return
	}

	writeSuccess(w)
}

// renterShareAsciiHandler handles the API call to return a '.sia' file
// in ascii form.
func (srv *Server) renterShareAsciiHandler(w http.ResponseWriter, req *http.Request, ps httprouter.Params) {
	ascii, err := srv.renter.ShareFilesAscii(strings.Split(req.FormValue("siapaths"), ","))
	if err != nil {
		writeError(w, err.Error(), http.StatusBadRequest)
		return
	}
	writeJSON(w, RenterShareASCII{
		ASCIIsia: ascii,
	})
}

// renterUploadHandler handles the API call to upload a file.
func (srv *Server) renterUploadHandler(w http.ResponseWriter, req *http.Request, ps httprouter.Params) {
	var duration types.BlockHeight
	if req.FormValue("duration") != "" {
		_, err := fmt.Sscan(req.FormValue("duration"), &duration)
		if err != nil {
			writeError(w, "Couldn't parse duration: "+err.Error(), http.StatusBadRequest)
			return
		}
	}
	renew := req.FormValue("renew") == "true"
	err := srv.renter.Upload(modules.FileUploadParams{
		Source:   req.FormValue("source"),
		SiaPath:  strings.TrimPrefix(ps.ByName("siapath"), "/"),
		Duration: duration,
		Renew:    renew,
		// let the renter decide these values; eventually they will be configurable
		ErasureCode: nil,
		PieceSize:   0,
	})
	if err != nil {
		writeError(w, "Upload failed: "+err.Error(), http.StatusInternalServerError)
		return
	}

	writeSuccess(w)
}

// renterHostsActiveHandler handes the API call asking for the list of active
// hosts.
func (srv *Server) renterHostsActiveHandler(w http.ResponseWriter, req *http.Request, _ httprouter.Params) {
	writeJSON(w, ActiveHosts{
		Hosts: srv.renter.ActiveHosts(),
	})
}

// renterHostsAllHandler handes the API call asking for the list of all hosts.
func (srv *Server) renterHostsAllHandler(w http.ResponseWriter, req *http.Request, _ httprouter.Params) {
	writeJSON(w, ActiveHosts{
		Hosts: srv.renter.AllHosts(),
	})
}
<commit_msg>hard-code allowance hosts+renewWindow<commit_after>package api

import (
	"fmt"
	"net/http"
	"strings"

	"github.com/NebulousLabs/Sia/modules"
	"github.com/NebulousLabs/Sia/types"

	"github.com/julienschmidt/httprouter"
)

// DownloadQueue contains the renter's download queue.
type RenterDownloadQueue struct {
	Downloads []modules.DownloadInfo `json:"downloads"`
}

// RenterFiles lists the files known to the renter.
type RenterFiles struct {
	Files []modules.FileInfo `json:"files"`
}

// RenterLoad lists files that were loaded into the renter.
type RenterLoad struct {
	FilesAdded []string `json:"filesadded"`
}

// RenterShareASCII contains an ASCII-encoded .sia file.
type RenterShareASCII struct {
	ASCIIsia string `json:"asciisia"`
}

// ActiveHosts lists active hosts on the network.
type ActiveHosts struct {
	Hosts []modules.HostDBEntry `json:"hosts"`
}

// renterAllowanceHandlerGET handles the API call to get the allowance.
func (srv *Server) renterAllowanceHandlerGET(w http.ResponseWriter, req *http.Request, _ httprouter.Params) {
	writeJSON(w, srv.renter.Allowance())
}

// renterAllowanceHandlerPOST handles the API call to set the allowance.
func (srv *Server) renterAllowanceHandlerPOST(w http.ResponseWriter, req *http.Request, _ httprouter.Params) {
	// scan values
	funds, ok := scanAmount(req.FormValue("funds"))
	if !ok {
		writeError(w, "Couldn't parse funds", http.StatusBadRequest)
		return
	}
	// var hosts uint64
	// _, err := fmt.Sscan(req.FormValue("hosts"), &hosts)
	// if err != nil {
	// 	writeError(w, "Couldn't parse hosts: "+err.Error(), http.StatusBadRequest)
	// 	return
	// }
	var period types.BlockHeight
	_, err := fmt.Sscan(req.FormValue("period"), &period)
	if err != nil {
		writeError(w, "Couldn't parse period: "+err.Error(), http.StatusBadRequest)
		return
	}
	// var renewWindow types.BlockHeight
	// _, err = fmt.Sscan(req.FormValue("renewwindow"), &renewWindow)
	// if err != nil {
	// 	writeError(w, "Couldn't parse renewwindow: "+err.Error(), http.StatusBadRequest)
	// 	return
	// }

	err = srv.renter.SetAllowance(modules.Allowance{
		Funds:  funds,
		Period: period,

		// TODO: let user specify these
		Hosts:       6,
		RenewWindow: period / 4,
	})
	if err != nil {
		writeError(w, err.Error(), http.StatusBadRequest)
		return
	}
	writeSuccess(w)
}

// renterDownloadsHandler handles the API call to request the download queue.
func (srv *Server) renterDownloadsHandler(w http.ResponseWriter, req *http.Request, _ httprouter.Params) {
	writeJSON(w, RenterDownloadQueue{
		Downloads: srv.renter.DownloadQueue(),
	})
}

// renterLoadHandler handles the API call to load a '.sia' file.
func (srv *Server) renterLoadHandler(w http.ResponseWriter, req *http.Request, _ httprouter.Params) {
	files, err := srv.renter.LoadSharedFiles(req.FormValue("source"))
	if err != nil {
		writeError(w, err.Error(), http.StatusBadRequest)
		return
	}

	writeJSON(w, RenterLoad{FilesAdded: files})
}

// renterLoadAsciiHandler handles the API call to load a '.sia' file
// in ASCII form.
func (srv *Server) renterLoadAsciiHandler(w http.ResponseWriter, req *http.Request, _ httprouter.Params) {
	files, err := srv.renter.LoadSharedFilesAscii(req.FormValue("asciisia"))
	if err != nil {
		writeError(w, err.Error(), http.StatusBadRequest)
		return
	}

	writeJSON(w, RenterLoad{FilesAdded: files})
}

// renterRenameHandler handles the API call to rename a file entry in the
// renter.
func (srv *Server) renterRenameHandler(w http.ResponseWriter, req *http.Request, ps httprouter.Params) {
	err := srv.renter.RenameFile(strings.TrimPrefix(ps.ByName("siapath"), "/"), req.FormValue("newsiapath"))
	if err != nil {
		writeError(w, err.Error(), http.StatusBadRequest)
		return
	}

	writeSuccess(w)
}

// renterFilesHandler handles the API call to list all of the files.
func (srv *Server) renterFilesHandler(w http.ResponseWriter, req *http.Request, _ httprouter.Params) {
	writeJSON(w, RenterFiles{
		Files: srv.renter.FileList(),
	})
}

// renterDeleteHander handles the API call to delete a file entry from the
// renter.
func (srv *Server) renterDeleteHandler(w http.ResponseWriter, req *http.Request, ps httprouter.Params) {
	err := srv.renter.DeleteFile(strings.TrimPrefix(ps.ByName("siapath"), "/"))
	if err != nil {
		writeError(w, err.Error(), http.StatusBadRequest)
		return
	}

	writeSuccess(w)
}

// renterDownloadHandler handles the API call to download a file.
func (srv *Server) renterDownloadHandler(w http.ResponseWriter, req *http.Request, ps httprouter.Params) {
	err := srv.renter.Download(strings.TrimPrefix(ps.ByName("siapath"), "/"), req.FormValue("destination"))
	if err != nil {
		writeError(w, "Download failed: "+err.Error(), http.StatusInternalServerError)
		return
	}

	writeSuccess(w)
}

// renterShareHandler handles the API call to create a '.sia' file that
// shares a set of file.
func (srv *Server) renterShareHandler(w http.ResponseWriter, req *http.Request, ps httprouter.Params) {
	err := srv.renter.ShareFiles(strings.Split(req.FormValue("siapaths"), ","), req.FormValue("destination"))
	if err != nil {
		writeError(w, err.Error(), http.StatusBadRequest)
		return
	}

	writeSuccess(w)
}

// renterShareAsciiHandler handles the API call to return a '.sia' file
// in ascii form.
func (srv *Server) renterShareAsciiHandler(w http.ResponseWriter, req *http.Request, ps httprouter.Params) {
	ascii, err := srv.renter.ShareFilesAscii(strings.Split(req.FormValue("siapaths"), ","))
	if err != nil {
		writeError(w, err.Error(), http.StatusBadRequest)
		return
	}
	writeJSON(w, RenterShareASCII{
		ASCIIsia: ascii,
	})
}

// renterUploadHandler handles the API call to upload a file.
func (srv *Server) renterUploadHandler(w http.ResponseWriter, req *http.Request, ps httprouter.Params) {
	var duration types.BlockHeight
	if req.FormValue("duration") != "" {
		_, err := fmt.Sscan(req.FormValue("duration"), &duration)
		if err != nil {
			writeError(w, "Couldn't parse duration: "+err.Error(), http.StatusBadRequest)
			return
		}
	}
	renew := req.FormValue("renew") == "true"
	err := srv.renter.Upload(modules.FileUploadParams{
		Source:   req.FormValue("source"),
		SiaPath:  strings.TrimPrefix(ps.ByName("siapath"), "/"),
		Duration: duration,
		Renew:    renew,
		// let the renter decide these values; eventually they will be configurable
		ErasureCode: nil,
		PieceSize:   0,
	})
	if err != nil {
		writeError(w, "Upload failed: "+err.Error(), http.StatusInternalServerError)
		return
	}

	writeSuccess(w)
}

// renterHostsActiveHandler handes the API call asking for the list of active
// hosts.
func (srv *Server) renterHostsActiveHandler(w http.ResponseWriter, req *http.Request, _ httprouter.Params) {
	writeJSON(w, ActiveHosts{
		Hosts: srv.renter.ActiveHosts(),
	})
}

// renterHostsAllHandler handes the API call asking for the list of all hosts.
func (srv *Server) renterHostsAllHandler(w http.ResponseWriter, req *http.Request, _ httprouter.Params) {
	writeJSON(w, ActiveHosts{
		Hosts: srv.renter.AllHosts(),
	})
}
<|endoftext|>