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

package context

import (
	"fmt"
	"html"
	"html/template"
	"io"
	"net/http"
	"strings"
	"time"

	"code.gitea.io/gitea/models"
	"code.gitea.io/gitea/modules/auth"
	"code.gitea.io/gitea/modules/base"
	"code.gitea.io/gitea/modules/log"
	"code.gitea.io/gitea/modules/setting"
	"github.com/go-macaron/cache"
	"github.com/go-macaron/csrf"
	"github.com/go-macaron/i18n"
	"github.com/go-macaron/session"
	macaron "gopkg.in/macaron.v1"
)

// Context represents context of a request.
type Context struct {
	*macaron.Context
	Cache   cache.Cache
	csrf    csrf.CSRF
	Flash   *session.Flash
	Session session.Store

	User        *models.User
	IsSigned    bool
	IsBasicAuth bool

	Repo *Repository
	Org  *Organization
}

// HasAPIError returns true if error occurs in form validation.
func (ctx *Context) HasAPIError() bool {
	hasErr, ok := ctx.Data["HasError"]
	if !ok {
		return false
	}
	return hasErr.(bool)
}

// GetErrMsg returns error message
func (ctx *Context) GetErrMsg() string {
	return ctx.Data["ErrorMsg"].(string)
}

// HasError returns true if error occurs in form validation.
func (ctx *Context) HasError() bool {
	hasErr, ok := ctx.Data["HasError"]
	if !ok {
		return false
	}
	ctx.Flash.ErrorMsg = ctx.Data["ErrorMsg"].(string)
	ctx.Data["Flash"] = ctx.Flash
	return hasErr.(bool)
}

// HasValue returns true if value of given name exists.
func (ctx *Context) HasValue(name string) bool {
	_, ok := ctx.Data[name]
	return ok
}

// HTML calls Context.HTML and converts template name to string.
func (ctx *Context) HTML(status int, name base.TplName) {
	log.Debug("Template: %s", name)
	ctx.Context.HTML(status, string(name))
}

// RenderWithErr used for page has form validation but need to prompt error to users.
func (ctx *Context) RenderWithErr(msg string, tpl base.TplName, form interface{}) {
	if form != nil {
		auth.AssignForm(form, ctx.Data)
	}
	ctx.Flash.ErrorMsg = msg
	ctx.Data["Flash"] = ctx.Flash
	ctx.HTML(200, tpl)
}

// Handle handles and logs error by given status.
func (ctx *Context) Handle(status int, title string, err error) {
	if err != nil {
		log.Error(4, "%s: %v", title, err)
		if macaron.Env != macaron.PROD {
			ctx.Data["ErrorMsg"] = err
		}
	}

	switch status {
	case 404:
		ctx.Data["Title"] = "Page Not Found"
	case 500:
		ctx.Data["Title"] = "Internal Server Error"
	}
	ctx.HTML(status, base.TplName(fmt.Sprintf("status/%d", status)))
}

// NotFoundOrServerError use error check function to determine if the error
// is about not found. It responses with 404 status code for not found error,
// or error context description for logging purpose of 500 server error.
func (ctx *Context) NotFoundOrServerError(title string, errck func(error) bool, err error) {
	if errck(err) {
		ctx.Handle(404, title, err)
		return
	}

	ctx.Handle(500, title, err)
}

// HandleText handles HTTP status code
func (ctx *Context) HandleText(status int, title string) {
	if (status/100 == 4) || (status/100 == 5) {
		log.Error(4, "%s", title)
	}
	ctx.PlainText(status, []byte(title))
}

// ServeContent serves content to http request
func (ctx *Context) ServeContent(name string, r io.ReadSeeker, params ...interface{}) {
	modtime := time.Now()
	for _, p := range params {
		switch v := p.(type) {
		case time.Time:
			modtime = v
		}
	}
	ctx.Resp.Header().Set("Content-Description", "File Transfer")
	ctx.Resp.Header().Set("Content-Type", "application/octet-stream")
	ctx.Resp.Header().Set("Content-Disposition", "attachment; filename="+name)
	ctx.Resp.Header().Set("Content-Transfer-Encoding", "binary")
	ctx.Resp.Header().Set("Expires", "0")
	ctx.Resp.Header().Set("Cache-Control", "must-revalidate")
	ctx.Resp.Header().Set("Pragma", "public")
	http.ServeContent(ctx.Resp, ctx.Req.Request, name, modtime, r)
}

// Contexter initializes a classic context for a request.
func Contexter() macaron.Handler {
	return func(c *macaron.Context, l i18n.Locale, cache cache.Cache, sess session.Store, f *session.Flash, x csrf.CSRF) {
		ctx := &Context{
			Context: c,
			Cache:   cache,
			csrf:    x,
			Flash:   f,
			Session: sess,
			Repo: &Repository{
				PullRequest: &PullRequest{},
			},
			Org: &Organization{},
		}
		// Compute current URL for real-time change language.
		ctx.Data["Link"] = setting.AppSubURL + strings.TrimSuffix(ctx.Req.URL.Path, "/")

		ctx.Data["PageStartTime"] = time.Now()

		// Get user from session if logged in.
		ctx.User, ctx.IsBasicAuth = auth.SignedInUser(ctx.Context, ctx.Session)

		if ctx.User != nil {
			ctx.IsSigned = true
			ctx.Data["IsSigned"] = ctx.IsSigned
			ctx.Data["SignedUser"] = ctx.User
			ctx.Data["SignedUserID"] = ctx.User.ID
			ctx.Data["SignedUserName"] = ctx.User.Name
			ctx.Data["IsAdmin"] = ctx.User.IsAdmin
		} else {
			ctx.Data["SignedUserID"] = 0
			ctx.Data["SignedUserName"] = ""
		}

		// If request sends files, parse them here otherwise the Query() can't be parsed and the CsrfToken will be invalid.
		if ctx.Req.Method == "POST" && strings.Contains(ctx.Req.Header.Get("Content-Type"), "multipart/form-data") {
			if err := ctx.Req.ParseMultipartForm(setting.AttachmentMaxSize << 20); err != nil && !strings.Contains(err.Error(), "EOF") { // 32MB max size
				ctx.Handle(500, "ParseMultipartForm", err)
				return
			}
		}

		ctx.Resp.Header().Set(`X-Frame-Options`, `SAMEORIGIN`)

		ctx.Data["CsrfToken"] = html.EscapeString(x.GetToken())
		ctx.Data["CsrfTokenHtml"] = template.HTML(`<input type="hidden" name="_csrf" value="` + ctx.Data["CsrfToken"].(string) + `">`)
		log.Debug("Session ID: %s", sess.ID())
		log.Debug("CSRF Token: %v", ctx.Data["CsrfToken"])

		ctx.Data["ShowRegistrationButton"] = setting.Service.ShowRegistrationButton
		ctx.Data["ShowFooterBranding"] = setting.ShowFooterBranding
		ctx.Data["ShowFooterVersion"] = setting.ShowFooterVersion
		ctx.Data["EnableOpenIDSignIn"] = setting.Service.EnableOpenIDSignIn

		c.Map(ctx)
	}
}
<commit_msg>Always return valid go-get meta, even if unauthorized (#2010)<commit_after>// Copyright 2014 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package context

import (
	"fmt"
	"html"
	"html/template"
	"io"
	"net/http"
	"path"
	"strings"
	"time"

	"code.gitea.io/gitea/models"
	"code.gitea.io/gitea/modules/auth"
	"code.gitea.io/gitea/modules/base"
	"code.gitea.io/gitea/modules/log"
	"code.gitea.io/gitea/modules/setting"
	"github.com/Unknwon/com"
	"github.com/go-macaron/cache"
	"github.com/go-macaron/csrf"
	"github.com/go-macaron/i18n"
	"github.com/go-macaron/session"
	macaron "gopkg.in/macaron.v1"
)

// Context represents context of a request.
type Context struct {
	*macaron.Context
	Cache   cache.Cache
	csrf    csrf.CSRF
	Flash   *session.Flash
	Session session.Store

	Link        string // current request URL
	User        *models.User
	IsSigned    bool
	IsBasicAuth bool

	Repo *Repository
	Org  *Organization
}

// HasAPIError returns true if error occurs in form validation.
func (ctx *Context) HasAPIError() bool {
	hasErr, ok := ctx.Data["HasError"]
	if !ok {
		return false
	}
	return hasErr.(bool)
}

// GetErrMsg returns error message
func (ctx *Context) GetErrMsg() string {
	return ctx.Data["ErrorMsg"].(string)
}

// HasError returns true if error occurs in form validation.
func (ctx *Context) HasError() bool {
	hasErr, ok := ctx.Data["HasError"]
	if !ok {
		return false
	}
	ctx.Flash.ErrorMsg = ctx.Data["ErrorMsg"].(string)
	ctx.Data["Flash"] = ctx.Flash
	return hasErr.(bool)
}

// HasValue returns true if value of given name exists.
func (ctx *Context) HasValue(name string) bool {
	_, ok := ctx.Data[name]
	return ok
}

// HTML calls Context.HTML and converts template name to string.
func (ctx *Context) HTML(status int, name base.TplName) {
	log.Debug("Template: %s", name)
	ctx.Context.HTML(status, string(name))
}

// RenderWithErr used for page has form validation but need to prompt error to users.
func (ctx *Context) RenderWithErr(msg string, tpl base.TplName, form interface{}) {
	if form != nil {
		auth.AssignForm(form, ctx.Data)
	}
	ctx.Flash.ErrorMsg = msg
	ctx.Data["Flash"] = ctx.Flash
	ctx.HTML(200, tpl)
}

// Handle handles and logs error by given status.
func (ctx *Context) Handle(status int, title string, err error) {
	if err != nil {
		log.Error(4, "%s: %v", title, err)
		if macaron.Env != macaron.PROD {
			ctx.Data["ErrorMsg"] = err
		}
	}

	switch status {
	case 404:
		ctx.Data["Title"] = "Page Not Found"
	case 500:
		ctx.Data["Title"] = "Internal Server Error"
	}
	ctx.HTML(status, base.TplName(fmt.Sprintf("status/%d", status)))
}

// NotFoundOrServerError use error check function to determine if the error
// is about not found. It responses with 404 status code for not found error,
// or error context description for logging purpose of 500 server error.
func (ctx *Context) NotFoundOrServerError(title string, errck func(error) bool, err error) {
	if errck(err) {
		ctx.Handle(404, title, err)
		return
	}

	ctx.Handle(500, title, err)
}

// HandleText handles HTTP status code
func (ctx *Context) HandleText(status int, title string) {
	if (status/100 == 4) || (status/100 == 5) {
		log.Error(4, "%s", title)
	}
	ctx.PlainText(status, []byte(title))
}

// ServeContent serves content to http request
func (ctx *Context) ServeContent(name string, r io.ReadSeeker, params ...interface{}) {
	modtime := time.Now()
	for _, p := range params {
		switch v := p.(type) {
		case time.Time:
			modtime = v
		}
	}
	ctx.Resp.Header().Set("Content-Description", "File Transfer")
	ctx.Resp.Header().Set("Content-Type", "application/octet-stream")
	ctx.Resp.Header().Set("Content-Disposition", "attachment; filename="+name)
	ctx.Resp.Header().Set("Content-Transfer-Encoding", "binary")
	ctx.Resp.Header().Set("Expires", "0")
	ctx.Resp.Header().Set("Cache-Control", "must-revalidate")
	ctx.Resp.Header().Set("Pragma", "public")
	http.ServeContent(ctx.Resp, ctx.Req.Request, name, modtime, r)
}

// Contexter initializes a classic context for a request.
func Contexter() macaron.Handler {
	return func(c *macaron.Context, l i18n.Locale, cache cache.Cache, sess session.Store, f *session.Flash, x csrf.CSRF) {
		ctx := &Context{
			Context: c,
			Cache:   cache,
			csrf:    x,
			Flash:   f,
			Session: sess,
			Link:    setting.AppSubURL + strings.TrimSuffix(c.Req.URL.Path, "/"),
			Repo: &Repository{
				PullRequest: &PullRequest{},
			},
			Org: &Organization{},
		}
		c.Data["Link"] = ctx.Link
		ctx.Data["PageStartTime"] = time.Now()
		// Quick responses appropriate go-get meta with status 200
		// regardless of if user have access to the repository,
		// or the repository does not exist at all.
		// This is particular a workaround for "go get" command which does not respect
		// .netrc file.
		if ctx.Query("go-get") == "1" {
			ownerName := c.Params(":username")
			repoName := c.Params(":reponame")
			branchName := "master"

			owner, err := models.GetUserByName(ownerName)
			if err == nil {
				repo, err := models.GetRepositoryByName(owner.ID, repoName)
				if err == nil && len(repo.DefaultBranch) > 0 {
					branchName = repo.DefaultBranch
				}
			}
			prefix := setting.AppURL + path.Join(ownerName, repoName, "src", branchName)
			c.PlainText(http.StatusOK, []byte(com.Expand(`
<html>
	<head>
		<meta name="go-import" content="{GoGetImport} git {CloneLink}">
		<meta name="go-source" content="{GoGetImport} _ {GoDocDirectory} {GoDocFile}">
	</head>
	<body>
		go get {GoGetImport}
	</body>
</html>
`, map[string]string{
				"GoGetImport":    path.Join(setting.Domain, setting.AppSubURL, ctx.Link),
				"CloneLink":      models.ComposeHTTPSCloneURL(ownerName, repoName),
				"GoDocDirectory": prefix + "{/dir}",
				"GoDocFile":      prefix + "{/dir}/{file}#L{line}",
			})))
			return
		}

		// Get user from session if logged in.
		ctx.User, ctx.IsBasicAuth = auth.SignedInUser(ctx.Context, ctx.Session)

		if ctx.User != nil {
			ctx.IsSigned = true
			ctx.Data["IsSigned"] = ctx.IsSigned
			ctx.Data["SignedUser"] = ctx.User
			ctx.Data["SignedUserID"] = ctx.User.ID
			ctx.Data["SignedUserName"] = ctx.User.Name
			ctx.Data["IsAdmin"] = ctx.User.IsAdmin
		} else {
			ctx.Data["SignedUserID"] = 0
			ctx.Data["SignedUserName"] = ""
		}

		// If request sends files, parse them here otherwise the Query() can't be parsed and the CsrfToken will be invalid.
		if ctx.Req.Method == "POST" && strings.Contains(ctx.Req.Header.Get("Content-Type"), "multipart/form-data") {
			if err := ctx.Req.ParseMultipartForm(setting.AttachmentMaxSize << 20); err != nil && !strings.Contains(err.Error(), "EOF") { // 32MB max size
				ctx.Handle(500, "ParseMultipartForm", err)
				return
			}
		}

		ctx.Resp.Header().Set(`X-Frame-Options`, `SAMEORIGIN`)

		ctx.Data["CsrfToken"] = html.EscapeString(x.GetToken())
		ctx.Data["CsrfTokenHtml"] = template.HTML(`<input type="hidden" name="_csrf" value="` + ctx.Data["CsrfToken"].(string) + `">`)
		log.Debug("Session ID: %s", sess.ID())
		log.Debug("CSRF Token: %v", ctx.Data["CsrfToken"])

		ctx.Data["ShowRegistrationButton"] = setting.Service.ShowRegistrationButton
		ctx.Data["ShowFooterBranding"] = setting.ShowFooterBranding
		ctx.Data["ShowFooterVersion"] = setting.ShowFooterVersion
		ctx.Data["EnableOpenIDSignIn"] = setting.Service.EnableOpenIDSignIn

		c.Map(ctx)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"log"
	"os"

	dem "github.com/markus-wa/demoinfocs-golang"
	common "github.com/markus-wa/demoinfocs-golang/common"
	events "github.com/markus-wa/demoinfocs-golang/events"
	ex "github.com/markus-wa/demoinfocs-golang/examples"
)

// Run like this: go run scores.go -demo /path/to/demo.dem
func main() {
	f, err := os.Open(ex.DemoPathFromArgs())
	defer f.Close()
	checkError(err)

	p := dem.NewParser(f)

	// Parse header
	h, err := p.ParseHeader()
	checkError(err)
	fmt.Println("Map:", h.MapName)

	// Register handler on round end to figure out who won
	p.RegisterEventHandler(func(e events.RoundEndedEvent) {
		gs := p.GameState()
		switch e.Winner {
		case common.TeamTerrorists:
			// Winner's score + 1 because it hasn't actually been updated yet
			fmt.Printf("Round finished: winnerSide=T  ; score=%d:%d\n", gs.TState().Score()+1, gs.CTState().Score())
		case common.TeamCounterTerrorists:
			fmt.Printf("Round finished: winnerSide=CT ; score=%d:%d\n", gs.CTState().Score()+1, gs.TState().Score())
		default:
			// Probably match medic or something similar
			fmt.Println("Round finished: No winner (tie)")
		}
	})

	// Parse to end
	err = p.ParseToEnd()
	checkError(err)
}

func checkError(err error) {
	if err != nil {
		log.Fatal(err)
	}
}
<commit_msg>Fix run instructions for print-scores example<commit_after>package main

import (
	"fmt"
	"log"
	"os"

	dem "github.com/markus-wa/demoinfocs-golang"
	common "github.com/markus-wa/demoinfocs-golang/common"
	events "github.com/markus-wa/demoinfocs-golang/events"
	ex "github.com/markus-wa/demoinfocs-golang/examples"
)

// Run like this: go run printscores.go -demo /path/to/demo.dem
func main() {
	f, err := os.Open(ex.DemoPathFromArgs())
	defer f.Close()
	checkError(err)

	p := dem.NewParser(f)

	// Parse header
	h, err := p.ParseHeader()
	checkError(err)
	fmt.Println("Map:", h.MapName)

	// Register handler on round end to figure out who won
	p.RegisterEventHandler(func(e events.RoundEndedEvent) {
		gs := p.GameState()
		switch e.Winner {
		case common.TeamTerrorists:
			// Winner's score + 1 because it hasn't actually been updated yet
			fmt.Printf("Round finished: winnerSide=T  ; score=%d:%d\n", gs.TState().Score()+1, gs.CTState().Score())
		case common.TeamCounterTerrorists:
			fmt.Printf("Round finished: winnerSide=CT ; score=%d:%d\n", gs.CTState().Score()+1, gs.TState().Score())
		default:
			// Probably match medic or something similar
			fmt.Println("Round finished: No winner (tie)")
		}
	})

	// Parse to end
	err = p.ParseToEnd()
	checkError(err)
}

func checkError(err error) {
	if err != nil {
		log.Fatal(err)
	}
}
<|endoftext|>


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

package middleware

import (
	"net/url"

	"github.com/Unknwon/macaron"
	"github.com/macaron-contrib/csrf"

	"github.com/gogits/gogs/modules/setting"
)

type ToggleOptions struct {
	SignInRequire  bool
	SignOutRequire bool
	AdminRequire   bool
	DisableCsrf    bool
}

func Toggle(options *ToggleOptions) macaron.Handler {
	return func(ctx *Context) {
		// Cannot view any page before installation.
		if !setting.InstallLock {
			ctx.Redirect(setting.AppSubUrl + "/install")
			return
		}

		// Checking non-logged users landing page.
		if !ctx.IsSigned && ctx.Req.RequestURI == "/" && setting.LandingPageUrl != setting.LANDING_PAGE_HOME {
			ctx.Redirect(string(setting.LandingPageUrl))
			return
		}

		// Redirect to dashboard if user tries to visit any non-login page.
		if options.SignOutRequire && ctx.IsSigned && ctx.Req.RequestURI != "/" {
			ctx.Redirect(setting.AppSubUrl + "/")
			return
		}

		if !options.SignOutRequire && !options.DisableCsrf && ctx.Req.Method == "POST" {
			csrf.Validate(ctx.Context, ctx.csrf)
			if ctx.Written() {
				return
			}
		}

		if options.SignInRequire {
			if !ctx.IsSigned {
				ctx.SetCookie("redirect_to", url.QueryEscape(setting.AppSubUrl+ctx.Req.RequestURI), 0, setting.AppSubUrl)
				ctx.Redirect(setting.AppSubUrl + "/user/login")
				return
			} else if !ctx.User.IsActive && setting.Service.RegisterEmailConfirm {
				ctx.Data["Title"] = ctx.Tr("auth.active_your_account")
				ctx.HTML(200, "user/auth/activate")
				return
			}
		}

		if options.AdminRequire {
			if !ctx.User.IsAdmin {
				ctx.Error(403)
				return
			}
			ctx.Data["PageIsAdmin"] = true
		}
	}
}

func ApiReqToken() macaron.Handler {
	return func(ctx *Context) {
		if !ctx.IsSigned {
			ctx.Error(403)
			return
		}
	}
}

func ApiReqBasicAuth() macaron.Handler {
	return func(ctx *Context) {
		if !ctx.IsBasicAuth {
			ctx.Error(403)
			return
		}
	}
}
<commit_msg>Add setting.AppSubUrl for LANDING_PAGE = explore<commit_after>// Copyright 2014 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package middleware

import (
	"net/url"

	"github.com/Unknwon/macaron"
	"github.com/macaron-contrib/csrf"

	"github.com/gogits/gogs/modules/setting"
)

type ToggleOptions struct {
	SignInRequire  bool
	SignOutRequire bool
	AdminRequire   bool
	DisableCsrf    bool
}

func Toggle(options *ToggleOptions) macaron.Handler {
	return func(ctx *Context) {
		// Cannot view any page before installation.
		if !setting.InstallLock {
			ctx.Redirect(setting.AppSubUrl + "/install")
			return
		}

		// Checking non-logged users landing page.
		if !ctx.IsSigned && ctx.Req.RequestURI == "/" && setting.LandingPageUrl != setting.LANDING_PAGE_HOME {
			ctx.Redirect(setting.AppSubUrl + string(setting.LandingPageUrl))
			return
		}

		// Redirect to dashboard if user tries to visit any non-login page.
		if options.SignOutRequire && ctx.IsSigned && ctx.Req.RequestURI != "/" {
			ctx.Redirect(setting.AppSubUrl + "/")
			return
		}

		if !options.SignOutRequire && !options.DisableCsrf && ctx.Req.Method == "POST" {
			csrf.Validate(ctx.Context, ctx.csrf)
			if ctx.Written() {
				return
			}
		}

		if options.SignInRequire {
			if !ctx.IsSigned {
				ctx.SetCookie("redirect_to", url.QueryEscape(setting.AppSubUrl+ctx.Req.RequestURI), 0, setting.AppSubUrl)
				ctx.Redirect(setting.AppSubUrl + "/user/login")
				return
			} else if !ctx.User.IsActive && setting.Service.RegisterEmailConfirm {
				ctx.Data["Title"] = ctx.Tr("auth.active_your_account")
				ctx.HTML(200, "user/auth/activate")
				return
			}
		}

		if options.AdminRequire {
			if !ctx.User.IsAdmin {
				ctx.Error(403)
				return
			}
			ctx.Data["PageIsAdmin"] = true
		}
	}
}

func ApiReqToken() macaron.Handler {
	return func(ctx *Context) {
		if !ctx.IsSigned {
			ctx.Error(403)
			return
		}
	}
}

func ApiReqBasicAuth() macaron.Handler {
	return func(ctx *Context) {
		if !ctx.IsBasicAuth {
			ctx.Error(403)
			return
		}
	}
}
<|endoftext|>


<commit_before>package plugins

import (
    "git.lukas.moe/sn0w/Karen/helpers"
    "github.com/bwmarrin/discordgo"
    "fmt"
    "strings"
)

type Headpat struct{}

func (h *Headpat) Commands() []string {
    return []string{
        "headpat",
        "pat",
    }
}

func (l *Headpat) Init(session *discordgo.Session) {

}

func (l *Headpat) Action(command string, content string, msg *discordgo.Message, session *discordgo.Session) {
    // Check mentions in the message
    mentionUsers := len(msg.Mentions)
    mentionRoles := len(msg.MentionRoles)

    // Delete spaces from params
    params := strings.Trim(content, " ")

    // Case 1: pat yourself
    if params == "me" || mentionUsers == 1 && (msg.Author.Username == msg.Mentions[0].Username) {
        session.ChannelMessageSend(msg.ChannelID, fmt.Sprintf(
        "%s https://media.giphy.com/media/wUArrd4mE3pyU/giphy.gif",
        helpers.GetText("bot.mentions.pat-yourself"),
    ))
        return
    }
    // Case 2: pat @User#1234
    if mentionUsers == 1 {
        session.ChannelMessageSend(msg.ChannelID, fmt.Sprintf(
        "%s , %s",
        msg.Mentions[0].Username,
        helpers.GetText("triggers.headpat.link"),
    ))
        return
    }
    // Case 3: pat multiple users
        if mentionUsers > 1 ||  mentionRoles >= 1 {
        session.ChannelMessageSend(msg.ChannelID, helpers.GetText("bot.mentions.pat-group"))
        return
    }
    // Case 4: no params || wrong params
    session.ChannelMessageSend(msg.ChannelID, helpers.GetText("bot.mentions.who-to-pat"))

}
<commit_msg>[headpats] Unify receiver names<commit_after>package plugins

import (
    "git.lukas.moe/sn0w/Karen/helpers"
    "github.com/bwmarrin/discordgo"
    "fmt"
    "strings"
)

type Headpat struct{}

func (h *Headpat) Commands() []string {
    return []string{
        "headpat",
        "pat",
    }
}

func (h *Headpat) Init(session *discordgo.Session) {

}

func (h *Headpat) Action(command string, content string, msg *discordgo.Message, session *discordgo.Session) {
    // Check mentions in the message
    mentionUsers := len(msg.Mentions)
    mentionRoles := len(msg.MentionRoles)

    // Delete spaces from params
    params := strings.Trim(content, " ")

    // Case 1: pat yourself
    if params == "me" || mentionUsers == 1 && (msg.Author.Username == msg.Mentions[0].Username) {
        session.ChannelMessageSend(msg.ChannelID, fmt.Sprintf(
        "%s https://media.giphy.com/media/wUArrd4mE3pyU/giphy.gif",
        helpers.GetText("bot.mentions.pat-yourself"),
    ))
        return
    }
    // Case 2: pat @User#1234
    if mentionUsers == 1 {
        session.ChannelMessageSend(msg.ChannelID, fmt.Sprintf(
        "%s , %s",
        msg.Mentions[0].Username,
        helpers.GetText("triggers.headpat.link"),
    ))
        return
    }
    // Case 3: pat multiple users
        if mentionUsers > 1 ||  mentionRoles >= 1 {
        session.ChannelMessageSend(msg.ChannelID, helpers.GetText("bot.mentions.pat-group"))
        return
    }
    // Case 4: no params || wrong params
    session.ChannelMessageSend(msg.ChannelID, helpers.GetText("bot.mentions.who-to-pat"))

}
<|endoftext|>


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

package process

import (
	"bytes"
	"errors"
	"fmt"
	"os/exec"
	"time"

	"code.gitea.io/gitea/modules/log"
)

var (
	// ErrExecTimeout represent a timeout error
	ErrExecTimeout = errors.New("Process execution timeout")

	// DefaultTimeout is the timeout used by Exec* family
	// of function when timeout parameter is omitted or
	// passed as -1
	// NOTE: could be custom in config file for default.
	DefaultTimeout = 60 * time.Second
)

// Process represents a working process inherit from Gogs.
type Process struct {
	Pid         int64 // Process ID, not system one.
	Description string
	Start       time.Time
	Cmd         *exec.Cmd
}

// List of existing processes.
var (
	curPid    int64 = 1
	Processes []*Process
)

// Add adds a existing process and returns its PID.
func Add(desc string, cmd *exec.Cmd) int64 {
	pid := curPid
	Processes = append(Processes, &Process{
		Pid:         pid,
		Description: desc,
		Start:       time.Now(),
		Cmd:         cmd,
	})
	curPid++
	return pid
}

// ExecDir runs a command in given path and waits for its completion
// up to the given timeout (or DefaultTimeout if -1 is given).
// Returns its complete stdout and stderr
// outputs and an error, if any (including timeout)
func ExecDir(timeout time.Duration, dir, desc, cmdName string, args ...string) (string, string, error) {
	if timeout == -1 {
		timeout = DefaultTimeout
	}

	bufOut := new(bytes.Buffer)
	bufErr := new(bytes.Buffer)

	cmd := exec.Command(cmdName, args...)
	cmd.Dir = dir
	cmd.Stdout = bufOut
	cmd.Stderr = bufErr
	if err := cmd.Start(); err != nil {
		return "", err.Error(), err
	}

	pid := Add(desc, cmd)
	done := make(chan error)
	go func() {
		done <- cmd.Wait()
	}()

	var err error
	select {
	case <-time.After(timeout):
		if errKill := Kill(pid); errKill != nil {
			log.Error(4, "Exec(%d:%s): %v", pid, desc, errKill)
		}
		<-done
		return "", ErrExecTimeout.Error(), ErrExecTimeout
	case err = <-done:
	}

	Remove(pid)
	return bufOut.String(), bufErr.String(), err
}

// ExecTimeout runs a command and waits for its completion
// up to the given timeout (or DefaultTimeout if -1 is given).
// Returns its complete stdout and stderr
// outputs and an error, if any (including timeout)
func ExecTimeout(timeout time.Duration, desc, cmdName string, args ...string) (string, string, error) {
	return ExecDir(timeout, "", desc, cmdName, args...)
}

// Exec runs a command and waits for its completion
// up to DefaultTimeout. Returns its complete stdout and stderr
// outputs and an error, if any (including timeout)
func Exec(desc, cmdName string, args ...string) (string, string, error) {
	return ExecDir(-1, "", desc, cmdName, args...)
}

// Remove removes a process from list.
func Remove(pid int64) {
	for i, proc := range Processes {
		if proc.Pid == pid {
			Processes = append(Processes[:i], Processes[i+1:]...)
			return
		}
	}
}

// Kill kills and removes a process from list.
func Kill(pid int64) error {
	for i, proc := range Processes {
		if proc.Pid == pid {
			if proc.Cmd != nil && proc.Cmd.Process != nil &&
				proc.Cmd.ProcessState != nil && !proc.Cmd.ProcessState.Exited() {
				if err := proc.Cmd.Process.Kill(); err != nil {
					return fmt.Errorf("fail to kill process(%d/%s): %v", proc.Pid, proc.Description, err)
				}
			}
			Processes = append(Processes[:i], Processes[i+1:]...)
			return nil
		}
	}
	return nil
}
<commit_msg>modules/process: add ExecDirEnv (next to ExecDir)<commit_after>// Copyright 2014 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package process

import (
	"bytes"
	"errors"
	"fmt"
	"os/exec"
	"time"

	"code.gitea.io/gitea/modules/log"
)

var (
	// ErrExecTimeout represent a timeout error
	ErrExecTimeout = errors.New("Process execution timeout")

	// DefaultTimeout is the timeout used by Exec* family
	// of function when timeout parameter is omitted or
	// passed as -1
	// NOTE: could be custom in config file for default.
	DefaultTimeout = 60 * time.Second
)

// Process represents a working process inherit from Gogs.
type Process struct {
	Pid         int64 // Process ID, not system one.
	Description string
	Start       time.Time
	Cmd         *exec.Cmd
}

// List of existing processes.
var (
	curPid    int64 = 1
	Processes []*Process
)

// Add adds a existing process and returns its PID.
func Add(desc string, cmd *exec.Cmd) int64 {
	pid := curPid
	Processes = append(Processes, &Process{
		Pid:         pid,
		Description: desc,
		Start:       time.Now(),
		Cmd:         cmd,
	})
	curPid++
	return pid
}

// ExecDirEnv runs a command in given path and environment variables, and waits for its completion
// up to the given timeout (or DefaultTimeout if -1 is given).
// Returns its complete stdout and stderr
// outputs and an error, if any (including timeout)
func ExecDirEnv(timeout time.Duration, dir, desc string, env []string, cmdName string, args ...string) (string, string, error) {
	if timeout == -1 {
		timeout = DefaultTimeout
	}

	bufOut := new(bytes.Buffer)
	bufErr := new(bytes.Buffer)

	cmd := exec.Command(cmdName, args...)
	cmd.Dir = dir
	cmd.Env = env
	cmd.Stdout = bufOut
	cmd.Stderr = bufErr
	if err := cmd.Start(); err != nil {
		return "", err.Error(), err
	}

	pid := Add(desc, cmd)
	done := make(chan error)
	go func() {
		done <- cmd.Wait()
	}()

	var err error
	select {
	case <-time.After(timeout):
		if errKill := Kill(pid); errKill != nil {
			log.Error(4, "Exec(%d:%s): %v", pid, desc, errKill)
		}
		<-done
		return "", ErrExecTimeout.Error(), ErrExecTimeout
	case err = <-done:
	}

	Remove(pid)
	return bufOut.String(), bufErr.String(), err
}

// ExecDir works exactly like ExecDirEnv except no environment variable is provided.
func ExecDir(timeout time.Duration, dir, desc, cmdName string, args ...string) (string, string, error) {
	return ExecDirEnv(timeout, dir, desc, nil, cmdName, args...)
}

// ExecTimeout runs a command and waits for its completion
// up to the given timeout (or DefaultTimeout if -1 is given).
// Returns its complete stdout and stderr
// outputs and an error, if any (including timeout)
func ExecTimeout(timeout time.Duration, desc, cmdName string, args ...string) (string, string, error) {
	return ExecDir(timeout, "", desc, cmdName, args...)
}

// Exec runs a command and waits for its completion
// up to DefaultTimeout. Returns its complete stdout and stderr
// outputs and an error, if any (including timeout)
func Exec(desc, cmdName string, args ...string) (string, string, error) {
	return ExecDir(-1, "", desc, cmdName, args...)
}

// Remove removes a process from list.
func Remove(pid int64) {
	for i, proc := range Processes {
		if proc.Pid == pid {
			Processes = append(Processes[:i], Processes[i+1:]...)
			return
		}
	}
}

// Kill kills and removes a process from list.
func Kill(pid int64) error {
	for i, proc := range Processes {
		if proc.Pid == pid {
			if proc.Cmd != nil && proc.Cmd.Process != nil &&
				proc.Cmd.ProcessState != nil && !proc.Cmd.ProcessState.Exited() {
				if err := proc.Cmd.Process.Kill(); err != nil {
					return fmt.Errorf("fail to kill process(%d/%s): %v", proc.Pid, proc.Description, err)
				}
			}
			Processes = append(Processes[:i], Processes[i+1:]...)
			return nil
		}
	}
	return nil
}
<|endoftext|>


<commit_before>package tradier

import (
	"encoding/json"
	"time"
)

// `orders` JSON can be an object or string literal "null"
type Orders struct {
	Order  []Order `json:"order,omitempty"`
	isNull *string
}

type orders Orders

// `order` JSON can be an object or array of objects
type Order struct {
	AvgFillPrice      *float64   `json:"avg_fill_price,omitempty"`
	Class             *string    `json:"class,omitempty"`
	CreateDate        *time.Time `json:"create_date,omitempty"`
	Duration          *string    `json:"duration,omitempty"`
	ExecQuantity      *float64   `json:"exec_quantity,omitempty"`
	ID                *int       `json:"id,omitempty"`
	LastFillPrice     *float64   `json:"last_fill_price,omitempty"`
	LastFillQuantity  *float64   `json:"last_fill_quantity,omitempty"`
	Quantity          *float64   `json:"quantity,omitempty"`
	RemainingQuantity *float64   `json:"remaining_quantity,omitempty"`
	Side              *string    `json:"side,omitempty"`
	Status            *string    `json:"status,omitempty"`
	Symbol            *string    `json:"symbol,omitempty"`
	TransactionDate   *time.Time `json:"transaction_date,omitempty"`
	Type              *string    `json:"type,omitempty"`
	// orderArray        `json:"-"` // Used internally to store array of `order` object as slice
}

type order struct {
	*Order `json:"order,omitempty"`
}

type orderArray []order

func (o *Orders) UnmarshalJSON(b []byte) (err error) {
	ordersStr := ""
	ordersObj := orders{}
	orderObj := order{}

	// If order is a string, i.e. "null"
	if err = json.Unmarshal(b, &ordersStr); err == nil {
		o.isNull = &ordersStr
		return nil
	}

	// If order is an array
	if err = json.Unmarshal(b, &ordersObj); err == nil {
		*o = Orders(ordersObj)
		return nil
	}

	// If order is an object
	if err = json.Unmarshal(b, &orderObj); err == nil {
		tmp := []Order{*orderObj.Order}
		*o = Orders{Order: tmp}
		return nil
	}

	return nil
}

func (o *Orders) MarshalJSON() ([]byte, error) {
	// If order is null
	if o.isNull != nil {
		return json.Marshal(o.isNull)
	}

	// If order array is size 1, return object directly
	if len(o.Order) == 1 {
		return json.Marshal(map[string]interface{}{
			"order": o.Order[0],
		})
	}

	return json.Marshal(*o)
}

// func (o *Order) UnmarshalJSON(b []byte) (err error) {
// 	orderObj := order{}
//
// 	log.Println(string(b))
//
// 	// If order is an object
// 	if err = json.Unmarshal(b, &orderObj); err == nil {
// 		log.Println("here")
// 		*o = Order(orderObj)
// 		return nil
// 	}
// 	//
// 	// // If order is an array
// 	// if err = json.Unmarshal(b, &orderArr); err == nil {
// 	// 	o.orderArray = orderArr
// 	// 	return nil
// 	// } else {
// 	// 	log.Println(err) // FIXME: Better error handling
// 	// }
//
// 	return nil
// }

// func (o *Order) MarshalJSON() ([]byte, error) {
//
// 	if o.orderArray != nil {
// 		return json.Marshal(o.orderArray)
// 	}
//
// 	return json.Marshal(Order(*o))
// }
<commit_msg>Remove the need for isNull on orders<commit_after>package tradier

import (
	"encoding/json"
	"time"
)

// Orders represents the `orders` JSON object
// If `order` is an array of objects, it can be accessed though indexing on Orders.Order
// If `order` is a single object, it can be accessed on the zeroth element
// If `order` is "null", Orders.Order will be empty
type Orders struct {
	Order []Order `json:"order,omitempty"`
}

type orders Orders

// Order represents the `order` JSON object
type Order struct {
	AvgFillPrice      *float64   `json:"avg_fill_price,omitempty"`
	Class             *string    `json:"class,omitempty"`
	CreateDate        *time.Time `json:"create_date,omitempty"`
	Duration          *string    `json:"duration,omitempty"`
	ExecQuantity      *float64   `json:"exec_quantity,omitempty"`
	ID                *int       `json:"id,omitempty"`
	LastFillPrice     *float64   `json:"last_fill_price,omitempty"`
	LastFillQuantity  *float64   `json:"last_fill_quantity,omitempty"`
	Quantity          *float64   `json:"quantity,omitempty"`
	RemainingQuantity *float64   `json:"remaining_quantity,omitempty"`
	Side              *string    `json:"side,omitempty"`
	Status            *string    `json:"status,omitempty"`
	Symbol            *string    `json:"symbol,omitempty"`
	TransactionDate   *time.Time `json:"transaction_date,omitempty"`
	Type              *string    `json:"type,omitempty"`
}

// FIXME: There should be a better way of handling Order without stubbing
//        Order inside a struct, similar to MarshalJSON via map[string]interface{}
type order struct {
	*Order `json:"order,omitempty"`
}

func (o *Orders) UnmarshalJSON(b []byte) (err error) {
	ordersStr := ""
	ordersObj := orders{}
	orderObj := order{}

	// If order is a string, i.e. "null"
	if err = json.Unmarshal(b, &ordersStr); err == nil {
		return nil
	}

	// If order is an array
	if err = json.Unmarshal(b, &ordersObj); err == nil {
		*o = Orders(ordersObj)
		return nil
	}

	// If order is an object
	if err = json.Unmarshal(b, &orderObj); err == nil {
		tmp := []Order{*orderObj.Order}
		*o = Orders{Order: tmp}
		return nil
	}

	return nil
}

func (o *Orders) MarshalJSON() ([]byte, error) {
	// If order is null
	if len(o.Order) == 0 {
		return json.Marshal("null")
	}

	// If order array is size 1, return object directly
	if len(o.Order) == 1 {
		return json.Marshal(map[string]interface{}{
			"order": o.Order[0],
		})
	}

	// Otherwise mashal as Orders normally, in this case using []Order
	return json.Marshal(*o)
}
<|endoftext|>


<commit_before>package transactionidutils

import (
	"errors"
	"math/rand"
	"net/http"
	"time"

	"golang.org/x/net/context"
)

//TransactionIDHeader is the request header to look for
const TransactionIDHeader = "X-Request-Id"

//TransactionIDKey is the key used to store the value on the context
const TransactionIDKey string = "transaction_id"

var letters = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")

func init() {
	rand.Seed(time.Now().UTC().UnixNano())
}

// GetTransactionIDFromRequest will look on the request
// for an 'X-Request-Id' header, and use that value as the returned transactionID.
// If none is found, one will be autogenerated, with a 'tid_' prefix and a random
// ten character string
func GetTransactionIDFromRequest(req *http.Request) string {
	transactionID := req.Header.Get(TransactionIDHeader)
	if transactionID == "" {
		transactionID = NewTransactionID()
		req.Header.Set(TransactionIDHeader, transactionID)
	}
	return transactionID
}

// NewTransactionID generates a new random transaction ID conforming to the FT spec
func NewTransactionID() string {
	return "tid_" + randString(10)
}

// TransactionAwareContext  will take the
// context passed in and store the transactionID on it
func TransactionAwareContext(ctx context.Context, transactionID string) context.Context {
	return context.WithValue(ctx, TransactionIDKey, transactionID)
}

// GetTransactionIDFromContext  will look for a transactionID
// value on the context and return it if found. If none is found, return empty
// string and an error
func GetTransactionIDFromContext(ctx context.Context) (string, error) {
	// ctx.Value returns nil if ctx has no value for the key;
	// string type assertion returns ok=false for nil.
	transactionID, ok := ctx.Value(TransactionIDKey).(string)
	if ok {
		return transactionID, nil
	}
	return "", errors.New("No transactionID found")
}

func randString(n int) string {
	b := make([]rune, n)
	for i := range b {
		b[i] = letters[rand.Intn(len(letters))]
	}
	return string(b)
}
<commit_msg>Updating for performance<commit_after>package transactionidutils

import (
	"errors"
	"math/rand"
	"net/http"
	"time"

	"golang.org/x/net/context"
)

//TransactionIDHeader is the request header to look for
const TransactionIDHeader = "X-Request-Id"

//TransactionIDKey is the key used to store the value on the context
const TransactionIDKey string = "transaction_id"

var letters = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
var lettersLen int

func init() {
	lettersLen = len(letters)
	rand.Seed(time.Now().UTC().UnixNano())
}

// GetTransactionIDFromRequest will look on the request
// for an 'X-Request-Id' header, and use that value as the returned transactionID.
// If none is found, one will be autogenerated, with a 'tid_' prefix and a random
// ten character string
func GetTransactionIDFromRequest(req *http.Request) string {
	transactionID := req.Header.Get(TransactionIDHeader)
	if transactionID == "" {
		transactionID = NewTransactionID()
		req.Header.Set(TransactionIDHeader, transactionID)
	}
	return transactionID
}

// NewTransactionID generates a new random transaction ID conforming to the FT spec
func NewTransactionID() string {
	return "tid_" + randString(10)
}

// TransactionAwareContext  will take the
// context passed in and store the transactionID on it
func TransactionAwareContext(ctx context.Context, transactionID string) context.Context {
	return context.WithValue(ctx, TransactionIDKey, transactionID)
}

// GetTransactionIDFromContext  will look for a transactionID
// value on the context and return it if found. If none is found, return empty
// string and an error
func GetTransactionIDFromContext(ctx context.Context) (string, error) {
	// ctx.Value returns nil if ctx has no value for the key;
	// string type assertion returns ok=false for nil.
	transactionID, ok := ctx.Value(TransactionIDKey).(string)
	if ok {
		return transactionID, nil
	}
	return "", errors.New("No transactionID found")
}

func randString(n int) string {
	b := make([]rune, n)
	for i := range b {
		b[i] = letters[rand.Intn(lettersLen)]
	}
	return string(b)
}
<|endoftext|>


<commit_before>/*
  Copyright 2012 Sergey Cherepanov (https://github.com/cheggaaa)

  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
*/

package cnst

const (
	VERSION = "0.3.5"
	SIGN    = "Anteater " + VERSION
)

<commit_msg>0.3.6<commit_after>/*
  Copyright 2012 Sergey Cherepanov (https://github.com/cheggaaa)

  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
*/

package cnst

const (
	VERSION = "0.3.6"
	SIGN    = "Anteater " + VERSION
)

<|endoftext|>


<commit_before>package comm

import (
	"bytes"
	"fmt"
	"net"
	"strconv"
	"strings"
	"time"
)

// Comm is some basic TCP communication
type Comm struct {
	connection net.Conn
}

// New returns a new comm
func New(c net.Conn) Comm {
	c.SetReadDeadline(time.Now().Add(3 * time.Hour))
	c.SetDeadline(time.Now().Add(3 * time.Hour))
	c.SetWriteDeadline(time.Now().Add(3 * time.Hour))
	return Comm{c}
}

// Connection returns the net.Conn connection
func (c Comm) Connection() net.Conn {
	return c.connection
}

func (c Comm) Write(b []byte) (int, error) {
	c.connection.Write([]byte(fmt.Sprintf("%0.5d", len(b))))
	n, err := c.connection.Write(b)
	if n != len(b) {
		err = fmt.Errorf("wanted to write %d but wrote %d", n, len(b))
	}
	// log.Printf("wanted to write %d but wrote %d", n, len(b))
	return n, err
}

func (c Comm) Read() (buf []byte, numBytes int, bs []byte, err error) {
	// read until we get 5 bytes
	bs = make([]byte, 5)
	_, err = c.connection.Read(bs)
	if err != nil {
		return
	}
	tmp := make([]byte, 1)
	for {
		bs = bytes.Trim(bs, "\x00")
		if len(bs) == 5 {
			break
		}
		c.connection.Read(tmp)
		bs = append(bs, tmp...)
	}
	numBytes, err = strconv.Atoi(strings.TrimLeft(string(bs), "0"))
	if err != nil {
		return nil, 0, nil, err
	}
	buf = make([]byte, numBytes)
	tmp = make([]byte, numBytes)
	bufStart := 0
	for {
		_, err = c.connection.Read(tmp)
		if err != nil {
			return nil, numBytes, bs, err
		}
		tmp = bytes.TrimRight(tmp, "\x00")
		copy(buf[bufStart:bufStart+len(tmp)], tmp[:])
		bufStart += len(tmp)
		if bufStart < numBytes {
			tmp = tmp[:numBytes-bufStart]
		} else {
			break
		}
	}
	// log.Printf("wanted %d and got %d", numBytes, len(buf))
	return
}

// Send a message
func (c Comm) Send(message string) (err error) {
	_, err = c.Write([]byte(message))
	return
}

// Receive a message
func (c Comm) Receive() (s string, err error) {
	b, _, _, err := c.Read()
	s = string(b)
	return
}
<commit_msg>simplify<commit_after>package comm

import (
	"bytes"
	"fmt"
	"net"
	"strconv"
	"strings"
	"time"
)

// Comm is some basic TCP communication
type Comm struct {
	connection net.Conn
}

// New returns a new comm
func New(c net.Conn) Comm {
	c.SetReadDeadline(time.Now().Add(3 * time.Hour))
	c.SetDeadline(time.Now().Add(3 * time.Hour))
	c.SetWriteDeadline(time.Now().Add(3 * time.Hour))
	return Comm{c}
}

// Connection returns the net.Conn connection
func (c Comm) Connection() net.Conn {
	return c.connection
}

func (c Comm) Write(b []byte) (int, error) {
	c.connection.Write([]byte(fmt.Sprintf("%0.5d", len(b))))
	n, err := c.connection.Write(b)
	if n != len(b) {
		err = fmt.Errorf("wanted to write %d but wrote %d", n, len(b))
	}
	// log.Printf("wanted to write %d but wrote %d", n, len(b))
	return n, err
}

func (c Comm) Read() (buf []byte, numBytes int, bs []byte, err error) {
	// read until we get 5 bytes
	bs = make([]byte, 5)
	_, err = c.connection.Read(bs)
	if err != nil {
		return
	}
	tmp := make([]byte, 1)
	for {
		bs = bytes.Trim(bs, "\x00")
		if len(bs) == 5 {
			break
		}
		c.connection.Read(tmp)
		bs = append(bs, tmp...)
	}
	numBytes, err = strconv.Atoi(strings.TrimLeft(string(bs), "0"))
	if err != nil {
		return nil, 0, nil, err
	}
	buf = make([]byte, numBytes)
	tmp = make([]byte, numBytes)
	bufStart := 0
	for {
		_, err = c.connection.Read(tmp)
		if err != nil {
			return nil, numBytes, bs, err
		}
		tmp = bytes.TrimRight(tmp, "\x00")
		copy(buf[bufStart:bufStart+len(tmp)], tmp[:])
		bufStart = len(buf)
		if bufStart < numBytes {
			tmp = tmp[:numBytes-bufStart]
		} else {
			break
		}
	}
	// log.Printf("wanted %d and got %d", numBytes, len(buf))
	return
}

// Send a message
func (c Comm) Send(message string) (err error) {
	_, err = c.Write([]byte(message))
	return
}

// Receive a message
func (c Comm) Receive() (s string, err error) {
	b, _, _, err := c.Read()
	s = string(b)
	return
}
<|endoftext|>


<commit_before>package steps

import (
	"fmt"
	"path"
	"time"

	"github.intel.com/hpdd/logging/debug"

	"github.com/mjmac/go-ps" // until PR is merged (hopefully)
	"github.com/pkg/errors"
)

const (
	// DefaultTimeout is the default waitFor timeout, in seconds
	DefaultTimeout = 10

	// StatusUpdateTimeout is the timeout for a file status update
	StatusUpdateTimeout = DefaultTimeout * 3
)

func findProcess(psName string) (ps.Process, error) {
	psList, err := ps.Processes()
	if err != nil {
		return nil, errors.Wrap(err, "Failed to get process list")
	}

	for _, process := range psList {
		if path.Base(process.Executable()) == psName {
			return process, nil
		}
	}

	return nil, fmt.Errorf("Failed to find %s in running process list", psName)
}

func checkProcessState(psName, state string, pid int) error {
	p, err := findProcess(psName)

	switch state {
	case "running":
		if err != nil {
			return err
		}
		// Optionally check that the found process matches the
		// expected pid.
		debug.Printf("Checking pid %d of %s", pid, psName)
		if pid > 0 {
			if p.Pid() != pid {
				return fmt.Errorf("Found %s, but pid %d does not match expected pid %d!", psName, p.Pid(), pid)
			}
		}
		return nil
	case "stopped":
		if err == nil {
			return fmt.Errorf("%s is still running", psName)
		}
		return nil
	default:
		return fmt.Errorf("Unknown state: %s", state)
	}
}

func waitFor(waitFn func() error, timeout int) error {
	success := make(chan struct{})
	go func() {
		for {
			if err := waitFn(); err == nil {
				close(success)
				return
			}
		}
	}()

	for {
		select {
		case <-success:
			return nil
		case <-time.After(time.Duration(timeout) * time.Second):
			return fmt.Errorf("Timed out waiting for result")
		}
	}
}
<commit_msg>Bump StatusUpdateTimeout to 1min<commit_after>package steps

import (
	"fmt"
	"path"
	"time"

	"github.intel.com/hpdd/logging/debug"

	"github.com/mjmac/go-ps" // until PR is merged (hopefully)
	"github.com/pkg/errors"
)

const (
	// DefaultTimeout is the default waitFor timeout, in seconds
	DefaultTimeout = 10

	// StatusUpdateTimeout is the timeout for a file status update
	StatusUpdateTimeout = DefaultTimeout * 6
)

func findProcess(psName string) (ps.Process, error) {
	psList, err := ps.Processes()
	if err != nil {
		return nil, errors.Wrap(err, "Failed to get process list")
	}

	for _, process := range psList {
		if path.Base(process.Executable()) == psName {
			return process, nil
		}
	}

	return nil, fmt.Errorf("Failed to find %s in running process list", psName)
}

func checkProcessState(psName, state string, pid int) error {
	p, err := findProcess(psName)

	switch state {
	case "running":
		if err != nil {
			return err
		}
		// Optionally check that the found process matches the
		// expected pid.
		debug.Printf("Checking pid %d of %s", pid, psName)
		if pid > 0 {
			if p.Pid() != pid {
				return fmt.Errorf("Found %s, but pid %d does not match expected pid %d!", psName, p.Pid(), pid)
			}
		}
		return nil
	case "stopped":
		if err == nil {
			return fmt.Errorf("%s is still running", psName)
		}
		return nil
	default:
		return fmt.Errorf("Unknown state: %s", state)
	}
}

func waitFor(waitFn func() error, timeout int) error {
	success := make(chan struct{})
	go func() {
		for {
			if err := waitFn(); err == nil {
				close(success)
				return
			}
		}
	}()

	for {
		select {
		case <-success:
			return nil
		case <-time.After(time.Duration(timeout) * time.Second):
			return fmt.Errorf("Timed out waiting for result")
		}
	}
}
<|endoftext|>


<commit_before>/*

   Copyright 2016 Wenhui Shen <www.webx.top>

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.

*/
package language

import (
	"regexp"
	"strings"

	"github.com/webx-top/echo"
	"github.com/webx-top/echo/engine"
)

const LANG_KEY = `webx:language`

func New() *Language {
	return &Language{
		List:     make(map[string]bool),
		Index:    make([]string, 0),
		Default:  "zh-cn",
		uaRegexp: regexp.MustCompile(`;q=[0-9.]+`),
	}
}

type Language struct {
	List     map[string]bool //语种列表
	Index    []string        //索引
	Default  string          //默认语种
	uaRegexp *regexp.Regexp
	I18n     *I18n
}

func (a *Language) Init(c *Config) {
	if c.AllList != nil {
		for _, lang := range c.AllList {
			a.Set(lang, true, lang == c.Default)
		}
	} else {
		a.Set(c.Default, true, true)
		a.Set(`en`, true)
	}
	a.I18n = NewI18n(c)
	if c.Reload {
		a.I18n.Monitor()
	}
}

func (a *Language) Set(lang string, on bool, args ...bool) *Language {
	if a.List == nil {
		a.List = make(map[string]bool)
	}
	if _, ok := a.List[lang]; !ok {
		a.Index = append(a.Index, lang)
	}
	a.List[lang] = on
	if on && len(args) > 0 && args[0] {
		a.Default = lang
	}
	return a
}

func (a *Language) DetectURI(_ engine.Response, r engine.Request) string {
	p := strings.TrimPrefix(r.URL().Path(), `/`)
	s := strings.Index(p, `/`)
	var lang string
	if s != -1 {
		lang = p[0:s]
	} else {
		lang = p
	}
	if len(lang) > 0 {
		if on, ok := a.List[lang]; ok {
			r.URL().SetPath(strings.TrimPrefix(p, lang))
			if !on {
				lang = ""
			}
		} else {
			lang = ""
		}
	}
	return lang
}

func (a *Language) Valid(lang string) bool {
	if len(lang) > 0 {
		if on, ok := a.List[lang]; ok {
			return on
		}
	}
	return false
}

func (a *Language) DetectUA(r engine.Request) string {
	al := r.Header().Get(`Accept-Language`)
	al = a.uaRegexp.ReplaceAllString(al, ``)
	lg := strings.SplitN(al, `,`, 5)
	for _, lang := range lg {
		lang = strings.ToLower(lang)
		if a.Valid(lang) {
			return lang
		}
	}
	return a.Default
}

func (a *Language) Middleware() echo.MiddlewareFunc {
	return echo.MiddlewareFunc(func(h echo.Handler) echo.Handler {
		return echo.HandlerFunc(func(c echo.Context) error {
			lang := c.Query(`lang`)
			hasCookie := false
			if !a.Valid(lang) {
				lang = a.DetectURI(c.Response(), c.Request())
				if !a.Valid(lang) {
					lang = c.GetCookie(`lang`)
					if !a.Valid(lang) {
						lang = a.DetectUA(c.Request())
					} else {
						hasCookie = true
					}
				}
			}
			if !hasCookie {
				c.SetCookie(`lang`, lang)
			}
			c.SetTranslator(NewTranslate(lang, a.I18n))
			return h.Handle(c)
		})
	})
}
<commit_msg>improved<commit_after>/*

   Copyright 2016 Wenhui Shen <www.webx.top>

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.

*/
package language

import (
	"regexp"
	"strings"

	"github.com/webx-top/echo"
	"github.com/webx-top/echo/engine"
)

var (
	LangVarName = `lang`
	DefaultLang = `zh-cn`
)

func New() *Language {
	return &Language{
		List:     make(map[string]bool),
		Index:    make([]string, 0),
		Default:  DefaultLang,
		uaRegexp: regexp.MustCompile(`;q=[0-9.]+`),
	}
}

type Language struct {
	List     map[string]bool //语种列表
	Index    []string        //索引
	Default  string          //默认语种
	uaRegexp *regexp.Regexp
	I18n     *I18n
}

func (a *Language) Init(c *Config) {
	if c.AllList != nil {
		for _, lang := range c.AllList {
			a.Set(lang, true, lang == c.Default)
		}
	} else {
		a.Set(c.Default, true, true)
		if c.Default != `en` {
			a.Set(`en`, true)
		}
	}
	a.I18n = NewI18n(c)
	if c.Reload {
		a.I18n.Monitor()
	}
}

func (a *Language) Set(lang string, on bool, args ...bool) *Language {
	if a.List == nil {
		a.List = make(map[string]bool)
	}
	if _, ok := a.List[lang]; !ok {
		a.Index = append(a.Index, lang)
	}
	a.List[lang] = on
	if on && len(args) > 0 && args[0] {
		a.Default = lang
	}
	return a
}

func (a *Language) DetectURI(_ engine.Response, r engine.Request) string {
	p := strings.TrimPrefix(r.URL().Path(), `/`)
	s := strings.Index(p, `/`)
	var lang string
	if s != -1 {
		lang = p[0:s]
	} else {
		lang = p
	}
	if len(lang) > 0 {
		if on, ok := a.List[lang]; ok {
			r.URL().SetPath(strings.TrimPrefix(p, lang))
			if !on {
				lang = ""
			}
		} else {
			lang = ""
		}
	}
	return lang
}

func (a *Language) Valid(lang string) bool {
	if len(lang) > 0 {
		if on, ok := a.List[lang]; ok {
			return on
		}
	}
	return false
}

func (a *Language) DetectUA(r engine.Request) string {
	al := r.Header().Get(`Accept-Language`)
	al = a.uaRegexp.ReplaceAllString(al, ``)
	lg := strings.SplitN(al, `,`, 5)
	for _, lang := range lg {
		lang = strings.ToLower(lang)
		if a.Valid(lang) {
			return lang
		}
	}
	return a.Default
}

func (a *Language) Middleware() echo.MiddlewareFunc {
	return echo.MiddlewareFunc(func(h echo.Handler) echo.Handler {
		return echo.HandlerFunc(func(c echo.Context) error {
			lang := c.Query(LangVarName)
			hasCookie := false
			if !a.Valid(lang) {
				lang = a.DetectURI(c.Response(), c.Request())
				if !a.Valid(lang) {
					lang = c.GetCookie(LangVarName)
					if !a.Valid(lang) {
						lang = a.DetectUA(c.Request())
					} else {
						hasCookie = true
					}
				}
			}
			if !hasCookie {
				c.SetCookie(LangVarName, lang)
			}
			c.SetTranslator(NewTranslate(lang, a.I18n))
			return h.Handle(c)
		})
	})
}
<|endoftext|>


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

// Minimum mutator utilization (MMU) graphing.

package main

import (
	"encoding/json"
	"fmt"
	trace "internal/traceparser"
	"log"
	"math"
	"net/http"
	"strconv"
	"strings"
	"sync"
	"time"
)

func init() {
	http.HandleFunc("/mmu", httpMMU)
	http.HandleFunc("/mmuPlot", httpMMUPlot)
	http.HandleFunc("/mmuDetails", httpMMUDetails)
}

var mmuCache struct {
	init     sync.Once
	util     [][]trace.MutatorUtil
	mmuCurve *trace.MMUCurve
	err      error
}

func getMMUCurve() ([][]trace.MutatorUtil, *trace.MMUCurve, error) {
	mmuCache.init.Do(func() {
		tr, err := parseTrace()
		if err != nil {
			mmuCache.err = err
		} else {
			mmuCache.util = tr.MutatorUtilization(trace.UtilSTW | trace.UtilBackground | trace.UtilAssist)
			mmuCache.mmuCurve = trace.NewMMUCurve(mmuCache.util)
		}
	})
	return mmuCache.util, mmuCache.mmuCurve, mmuCache.err
}

// httpMMU serves the MMU plot page.
func httpMMU(w http.ResponseWriter, r *http.Request) {
	http.ServeContent(w, r, "", time.Time{}, strings.NewReader(templMMU))
}

// httpMMUPlot serves the JSON data for the MMU plot.
func httpMMUPlot(w http.ResponseWriter, r *http.Request) {
	mu, mmuCurve, err := getMMUCurve()
	if err != nil {
		http.Error(w, fmt.Sprintf("failed to parse events: %v", err), http.StatusInternalServerError)
		return
	}

	// Find a nice starting point for the plot.
	xMin := time.Second
	for xMin > 1 {
		if mmu := mmuCurve.MMU(xMin); mmu < 0.0001 {
			break
		}
		xMin /= 1000
	}
	// Cover six orders of magnitude.
	xMax := xMin * 1e6
	// But no more than the length of the trace.
	minEvent, maxEvent := mu[0][0].Time, mu[0][len(mu[0])-1].Time
	for _, mu1 := range mu[1:] {
		if mu1[0].Time < minEvent {
			minEvent = mu1[0].Time
		}
		if mu1[len(mu1)-1].Time > maxEvent {
			maxEvent = mu1[len(mu1)-1].Time
		}
	}
	if maxMax := time.Duration(maxEvent - minEvent); xMax > maxMax {
		xMax = maxMax
	}
	// Compute MMU curve.
	logMin, logMax := math.Log(float64(xMin)), math.Log(float64(xMax))
	const samples = 100
	plot := make([][2]float64, samples)
	for i := 0; i < samples; i++ {
		window := time.Duration(math.Exp(float64(i)/(samples-1)*(logMax-logMin) + logMin))
		y := mmuCurve.MMU(window)
		plot[i] = [2]float64{float64(window), y}
	}

	// Create JSON response.
	err = json.NewEncoder(w).Encode(map[string]interface{}{"xMin": int64(xMin), "xMax": int64(xMax), "curve": plot})
	if err != nil {
		log.Printf("failed to serialize response: %v", err)
		return
	}
}

var templMMU = `<!doctype html>

    <meta charset="utf-8">

Loading plot...

Select a point for details.

`

// httpMMUDetails serves details of an MMU graph at a particular window.
func httpMMUDetails(w http.ResponseWriter, r *http.Request) {
	_, mmuCurve, err := getMMUCurve()
	if err != nil {
		http.Error(w, fmt.Sprintf("failed to parse events: %v", err), http.StatusInternalServerError)
		return
	}

	windowStr := r.FormValue("window")
	window, err := strconv.ParseUint(windowStr, 10, 64)
	if err != nil {
		http.Error(w, fmt.Sprintf("failed to parse window parameter %q: %v", windowStr, err), http.StatusBadRequest)
		return
	}
	worst := mmuCurve.Examples(time.Duration(window), 10)

	// Construct a link for each window.
	var links []linkedUtilWindow
	for _, ui := range worst {
		links = append(links, newLinkedUtilWindow(ui, time.Duration(window)))
	}

	err = json.NewEncoder(w).Encode(links)
	if err != nil {
		log.Printf("failed to serialize trace: %v", err)
		return
	}
}

type linkedUtilWindow struct {
	trace.UtilWindow
	URL string
}

func newLinkedUtilWindow(ui trace.UtilWindow, window time.Duration) linkedUtilWindow {
	// Find the range containing this window.
	var r Range
	for _, r = range ranges {
		if r.EndTime > ui.Time {
			break
		}
	}
	return linkedUtilWindow{ui, fmt.Sprintf("%s#%v:%v", r.URL(), float64(ui.Time)/1e6, float64(ui.Time+int64(window))/1e6)}
}
<commit_msg>cmd/trace: expose MMU analysis flags in web UI<commit_after>// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Minimum mutator utilization (MMU) graphing.

package main

import (
	"encoding/json"
	"fmt"
	trace "internal/traceparser"
	"log"
	"math"
	"net/http"
	"strconv"
	"strings"
	"sync"
	"time"
)

func init() {
	http.HandleFunc("/mmu", httpMMU)
	http.HandleFunc("/mmuPlot", httpMMUPlot)
	http.HandleFunc("/mmuDetails", httpMMUDetails)
}

var utilFlagNames = map[string]trace.UtilFlags{
	"perProc":    trace.UtilPerProc,
	"stw":        trace.UtilSTW,
	"background": trace.UtilBackground,
	"assist":     trace.UtilAssist,
	"sweep":      trace.UtilSweep,
}

type mmuCacheEntry struct {
	init     sync.Once
	util     [][]trace.MutatorUtil
	mmuCurve *trace.MMUCurve
	err      error
}

var mmuCache struct {
	m    map[trace.UtilFlags]*mmuCacheEntry
	lock sync.Mutex
}

func init() {
	mmuCache.m = make(map[trace.UtilFlags]*mmuCacheEntry)
}

func getMMUCurve(r *http.Request) ([][]trace.MutatorUtil, *trace.MMUCurve, error) {
	var flags trace.UtilFlags
	for _, flagStr := range strings.Split(r.FormValue("flags"), "|") {
		flags |= utilFlagNames[flagStr]
	}

	mmuCache.lock.Lock()
	c := mmuCache.m[flags]
	if c == nil {
		c = new(mmuCacheEntry)
		mmuCache.m[flags] = c
	}
	mmuCache.lock.Unlock()

	c.init.Do(func() {
		tr, err := parseTrace()
		if err != nil {
			c.err = err
		} else {
			c.util = tr.MutatorUtilization(flags)
			c.mmuCurve = trace.NewMMUCurve(c.util)
		}
	})
	return c.util, c.mmuCurve, c.err
}

// httpMMU serves the MMU plot page.
func httpMMU(w http.ResponseWriter, r *http.Request) {
	http.ServeContent(w, r, "", time.Time{}, strings.NewReader(templMMU))
}

// httpMMUPlot serves the JSON data for the MMU plot.
func httpMMUPlot(w http.ResponseWriter, r *http.Request) {
	mu, mmuCurve, err := getMMUCurve(r)
	if err != nil {
		http.Error(w, fmt.Sprintf("failed to parse events: %v", err), http.StatusInternalServerError)
		return
	}

	// Find a nice starting point for the plot.
	xMin := time.Second
	for xMin > 1 {
		if mmu := mmuCurve.MMU(xMin); mmu < 0.0001 {
			break
		}
		xMin /= 1000
	}
	// Cover six orders of magnitude.
	xMax := xMin * 1e6
	// But no more than the length of the trace.
	minEvent, maxEvent := mu[0][0].Time, mu[0][len(mu[0])-1].Time
	for _, mu1 := range mu[1:] {
		if mu1[0].Time < minEvent {
			minEvent = mu1[0].Time
		}
		if mu1[len(mu1)-1].Time > maxEvent {
			maxEvent = mu1[len(mu1)-1].Time
		}
	}
	if maxMax := time.Duration(maxEvent - minEvent); xMax > maxMax {
		xMax = maxMax
	}
	// Compute MMU curve.
	logMin, logMax := math.Log(float64(xMin)), math.Log(float64(xMax))
	const samples = 100
	plot := make([][2]float64, samples)
	for i := 0; i < samples; i++ {
		window := time.Duration(math.Exp(float64(i)/(samples-1)*(logMax-logMin) + logMin))
		y := mmuCurve.MMU(window)
		plot[i] = [2]float64{float64(window), y}
	}

	// Create JSON response.
	err = json.NewEncoder(w).Encode(map[string]interface{}{"xMin": int64(xMin), "xMax": int64(xMax), "curve": plot})
	if err != nil {
		log.Printf("failed to serialize response: %v", err)
		return
	}
}

var templMMU = `<!doctype html>

    <meta charset="utf-8">

Loading plot...

          View

          <input type="radio" name="view" id="system" checked>System
          ?Consider whole system utilization. For example, if one of four procs is available to the mutator, mutator utilization will be 0.25. This is the standard definition of an MMU.

          <input type="radio" name="view" id="perProc">Per-goroutine
          ?Consider per-goroutine utilization. When even one goroutine is interrupted by GC, mutator utilization is 0.

          Include

          <input type="checkbox" id="stw" checked>STW
          ?Stop-the-world stops all goroutines simultaneously.

          <input type="checkbox" id="background" checked>Background workers
          ?Background workers are GC-specific goroutines. 25% of the CPU is dedicated to background workers during GC.

          <input type="checkbox" id="assist" checked>Mark assist
          ?Mark assists are performed by allocation to prevent the mutator from outpacing GC.

          <input type="checkbox" id="sweep">Sweep
          ?Sweep reclaims unused memory between GCs. (Enabling this may be very slow.).

Select a point for details.

`

// httpMMUDetails serves details of an MMU graph at a particular window.
func httpMMUDetails(w http.ResponseWriter, r *http.Request) {
	_, mmuCurve, err := getMMUCurve(r)
	if err != nil {
		http.Error(w, fmt.Sprintf("failed to parse events: %v", err), http.StatusInternalServerError)
		return
	}

	windowStr := r.FormValue("window")
	window, err := strconv.ParseUint(windowStr, 10, 64)
	if err != nil {
		http.Error(w, fmt.Sprintf("failed to parse window parameter %q: %v", windowStr, err), http.StatusBadRequest)
		return
	}
	worst := mmuCurve.Examples(time.Duration(window), 10)

	// Construct a link for each window.
	var links []linkedUtilWindow
	for _, ui := range worst {
		links = append(links, newLinkedUtilWindow(ui, time.Duration(window)))
	}

	err = json.NewEncoder(w).Encode(links)
	if err != nil {
		log.Printf("failed to serialize trace: %v", err)
		return
	}
}

type linkedUtilWindow struct {
	trace.UtilWindow
	URL string
}

func newLinkedUtilWindow(ui trace.UtilWindow, window time.Duration) linkedUtilWindow {
	// Find the range containing this window.
	var r Range
	for _, r = range ranges {
		if r.EndTime > ui.Time {
			break
		}
	}
	return linkedUtilWindow{ui, fmt.Sprintf("%s#%v:%v", r.URL(), float64(ui.Time)/1e6, float64(ui.Time+int64(window))/1e6)}
}
<|endoftext|>


<commit_before>package main

import (
	tushttp "github.com/tus/tusd/src/http"
	"log"
	"net/http"
	"os"
	"path/filepath"
	"strconv"
)

const basePath = "/files/"

func main() {
	log.SetFlags(log.Ldate | log.Ltime | log.Lmicroseconds)
	log.Printf("tusd started")

	addr := ":1080"
	if envPort := os.Getenv("TUSD_PORT"); envPort != "" {
		addr = ":" + envPort
	}

	maxSize := int64(1024 * 1024 * 1024)
	if envMaxSize := os.Getenv("TUSD_DATA_STORE_MAXSIZE"); envMaxSize != "" {
		parsed, err := strconv.ParseInt(envMaxSize, 10, 64)
		if err != nil {
			panic("bad TUSD_DATA_STORE_MAXSIZE: " + err.Error())
		}
		maxSize = parsed
	}

	dir := os.Getenv("TUSD_DATA_DIR")
	if dir == "" {
		if workingDir, err := os.Getwd(); err != nil {
			panic(err)
		} else {
			dir = filepath.Join(workingDir, "tus_data")
		}
	}

	tusConfig := tushttp.HandlerConfig{
		Dir:      dir,
		MaxSize:  maxSize,
		BasePath: basePath,
	}

	log.Printf("handler config: %+v", tusConfig)

	tusHandler, err := tushttp.NewHandler(tusConfig)
	if err != nil {
		panic(err)
	}

	http.Handle(basePath, tusHandler)

	go handleUploads(tusHandler)

	log.Printf("servering clients at http://localhost%s", addr)
	if err := http.ListenAndServe(addr, nil); err != nil {
		panic(err)
	}
}

func handleUploads(tus *tushttp.Handler) {
	for {
		select {
		case err := <-tus.Error:
			log.Printf("error: %s", err)
		}
	}
}
<commit_msg>Add CORS support again<commit_after>package main

import (
	tushttp "github.com/tus/tusd/src/http"
	"log"
	"net/http"
	"os"
	"path/filepath"
	"strconv"
)

const basePath = "/files/"

func main() {
	log.SetFlags(log.Ldate | log.Ltime | log.Lmicroseconds)
	log.Printf("tusd started")

	addr := ":1080"
	if envPort := os.Getenv("TUSD_PORT"); envPort != "" {
		addr = ":" + envPort
	}

	maxSize := int64(1024 * 1024 * 1024)
	if envMaxSize := os.Getenv("TUSD_DATA_STORE_MAXSIZE"); envMaxSize != "" {
		parsed, err := strconv.ParseInt(envMaxSize, 10, 64)
		if err != nil {
			panic("bad TUSD_DATA_STORE_MAXSIZE: " + err.Error())
		}
		maxSize = parsed
	}

	dir := os.Getenv("TUSD_DATA_DIR")
	if dir == "" {
		if workingDir, err := os.Getwd(); err != nil {
			panic(err)
		} else {
			dir = filepath.Join(workingDir, "tus_data")
		}
	}

	tusConfig := tushttp.HandlerConfig{
		Dir:      dir,
		MaxSize:  maxSize,
		BasePath: basePath,
	}

	log.Printf("handler config: %+v", tusConfig)

	tusHandler, err := tushttp.NewHandler(tusConfig)
	if err != nil {
		panic(err)
	}

	http.HandleFunc(basePath, func(w http.ResponseWriter, r *http.Request) {
		// Allow CORS for almost everything. This needs to be revisted / limited to
		// routes and methods that need it.
		w.Header().Add("Access-Control-Allow-Origin", "*")
		w.Header().Add("Access-Control-Allow-Methods", "HEAD,GET,PUT,POST,DELETE")
		w.Header().Add("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Content-Range, Content-Disposition")
		w.Header().Add("Access-Control-Expose-Headers", "Location, Range, Content-Disposition")

		if r.Method == "OPTIONS" {
			return
		}

		tusHandler.ServeHTTP(w, r)
	})

	go handleUploads(tusHandler)

	log.Printf("servering clients at http://localhost%s", addr)
	if err := http.ListenAndServe(addr, nil); err != nil {
		panic(err)
	}
}

func handleUploads(tus *tushttp.Handler) {
	for {
		select {
		case err := <-tus.Error:
			log.Printf("error: %s", err)
		}
	}
}
<|endoftext|>


<commit_before>// Package odin ...
package odin

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"net/url"
	"os"
	"strings"

	"github.com/jcelliott/lumber"

	"github.com/nanobox-io/nanobox/commands/registry"
	"github.com/nanobox-io/nanobox/models"
	"github.com/nanobox-io/nanobox/util"
)

const (
	NANOBOX  = "https://api.nanobox.io/v1/"
	BONESALT = "https://api.bonesalt.com/v1/"
	DEV      = "http://api.nanobox.dev:8080/v1/"
	SIM      = "http://api.nanobox.sim/v1/"
)

var (
	// set the default endpoint to nanobox
	endpoint = "nanobox"
	apiKey   string
)

type (
	evar struct {
		ID    string `json:"id"`
		Key   string `json:"title"`
		Value string `json:"value"`
	}
)

// sets the odin endpoint
func SetEndpoint(stage string) {
	endpoint = stage
}

// Auth authenticates the user with odin.
func Auth(username, password string) (string, error) {

	loginInfo := struct {
		Slug     string `json:"slug"`
		Password string `json:"password"`
	}{username, password}

	resBody := map[string]string{}

	if err := doRequest("GET", "user_auth_token", nil, loginInfo, &resBody); err != nil {
		return "", err
	}

	return resBody["authentication_token"], nil
}

// App ...
func App(slug string) (models.App, error) {
	app := models.App{}
	var params url.Values
	if strings.Contains(slug, "/") {
		appNameParts := strings.Split(slug, "/")
		if len(appNameParts) == 2 {
			params = url.Values{}
			params.Set("ci", appNameParts[0])
			slug = appNameParts[1]
		}

	}

	return app, doRequest("GET", "apps/"+slug, params, nil, &app)
}

// Deploy ...
func Deploy(appID, id, boxfile, message string) error {

	//
	body := map[string]map[string]string{
		"deploy": {
			"boxfile_content": boxfile,
			"build_id":        id,
			"commit_message":  message,
		},
	}

	var params url.Values

	if strings.Contains(appID, "/") {
		appNameParts := strings.Split(appID, "/")
		if len(appNameParts) == 2 {
			params = url.Values{}
			params.Set("ci", appNameParts[0])
			appID = appNameParts[1]
		}

	}

	return doRequest("POST", fmt.Sprintf("apps/%s/deploys", appID), params, body, nil)
}

func ListEvars(appID string) ([]evar, error) {
	evars := []evar{}

	var params url.Values
	if strings.Contains(appID, "/") {
		appNameParts := strings.Split(appID, "/")
		if len(appNameParts) == 2 {
			params = url.Values{}
			params.Set("ci", appNameParts[0])
			appID = appNameParts[1]
		}

	}

	return evars, doRequest("GET", fmt.Sprintf("apps/%s/evars", appID), params, nil, &evars)
}

func AddEvar(appID, key, val string) error {
	body := map[string]map[string]string{
		"evar": {
			"title": key,
			"value": val,
		},
	}

	var params url.Values

	if strings.Contains(appID, "/") {
		appNameParts := strings.Split(appID, "/")
		if len(appNameParts) == 2 {
			params = url.Values{}
			params.Set("ci", appNameParts[0])
			appID = appNameParts[1]
		}

	}

	return doRequest("POST", fmt.Sprintf("apps/%s/evars", appID), params, body, nil)
}

func RemoveEvar(appID, id string) error {
	var params url.Values

	if strings.Contains(appID, "/") {
		appNameParts := strings.Split(appID, "/")
		if len(appNameParts) == 2 {
			params = url.Values{}
			params.Set("ci", appNameParts[0])
			appID = appNameParts[1]
		}

	}

	return doRequest("DELETE", fmt.Sprintf("apps/%s/evars/%s", appID, id), params, nil, nil)
}

// EstablishTunnel requests a tunnel from odin.
func EstablishTunnel(tunCfg models.TunnelConfig) (models.TunnelInfo, error) {
	r := models.TunnelInfo{Port: tunCfg.DestPort}

	params := url.Values{}
	if strings.Contains(tunCfg.AppName, "/") {
		appNameParts := strings.Split(tunCfg.AppName, "/")
		if len(appNameParts) == 2 {
			params = url.Values{}
			// ci is contextID for teams `team/app`
			params.Set("ci", appNameParts[0])
			tunCfg.AppName = appNameParts[1]
		}
	}

	err := doRequest("GET", fmt.Sprintf("apps/%s/tunnels/%s", tunCfg.AppName, tunCfg.Component), params, r, &r)
	if err != nil {
		if strings.Contains(err.Error(), "valid port") {
			if err2, ok := err.(util.Err); ok {
				err2.Suggest = "Specify a valid destination port with `-p source:destination`"
				err2.Message = err.Error()
				return r, err2
			}
		}
		if strings.Contains(err.Error(), "no default") {
			if err2, ok := err.(util.Err); ok {
				err2.Suggest = "Specify a destination port with `-p source:destination`"
				err2.Code = "USER"
				err2.Message = err.Error()
				return r, err2
			}
		}
		if strings.Contains(err.Error(), "Not Found") {
			if err2, ok := err.(util.Err); ok {
				err2.Message = fmt.Sprintf("%s - component '%s' not found on app '%s'", err.Error(), tunCfg.Component, tunCfg.AppName)
				return r, err2
			}
			err = fmt.Errorf("%s - component '%s' not found on app '%s'", err.Error(), tunCfg.Component, tunCfg.AppName)
		}
	}

	return r, err
}

// EstablishConsole ...
// protocol ssh/docker
func EstablishConsole(appID, id string) (string, string, string, error) {
	// use a default user
	params := url.Values{}
	params.Set("user", "gonano")
	if registry.GetString("console_user") != "" {
		params.Set("user", registry.GetString("console_user"))
	}

	if strings.Contains(appID, "/") {
		appNameParts := strings.Split(appID, "/")
		if len(appNameParts) == 2 {
			params.Set("ci", appNameParts[0])
			appID = appNameParts[1]
		}

	}

	r := map[string]string{}
	err := doRequest("GET", fmt.Sprintf("apps/%s/consoles/%s", appID, id), params, nil, &r)

	return r["token"], r["url"], r["protocol"], err
}

// GetWarehouse ...
func GetWarehouse(appID string) (string, string, error) {
	r := map[string]string{}

	var params url.Values
	if strings.Contains(appID, "/") {
		appNameParts := strings.Split(appID, "/")
		if len(appNameParts) == 2 {
			params = url.Values{}
			params.Set("ci", appNameParts[0])
			appID = appNameParts[1]
		}

	}

	err := doRequest("GET", fmt.Sprintf("apps/%s/services/warehouse", appID), params, nil, &r)

	return r["token"], r["url"], err
}

// GetComponent gets the token and url for a given component
func GetComponent(appID, component string) (string, string, error) {
	r := map[string]string{}

	var params url.Values
	if strings.Contains(appID, "/") {
		appNameParts := strings.Split(appID, "/")
		if len(appNameParts) == 2 {
			params = url.Values{}
			params.Set("ci", appNameParts[0])
			appID = appNameParts[1]
		}

	}

	err := doRequest("GET", fmt.Sprintf("apps/%s/services/%s", appID, component), params, nil, &r)
	// r = map["uid":"pusher1" "name":"message bus" "slug":"pusher" "url":"x.x.x.x" "token":"secret" "mode":"simple" "ip":"x.x.x.x" "id":"d371c59b-fbbc-4248-8f3b-7f694a62b5e1"]

	return r["token"], r["url"], err
}

func GetPreviousBuild(appID string) (string, error) {
	r := []map[string]string{}

	var params url.Values
	if strings.Contains(appID, "/") {
		appNameParts := strings.Split(appID, "/")
		if len(appNameParts) == 2 {
			params = url.Values{}
			params.Set("ci", appNameParts[0])
			appID = appNameParts[1]
		}

	}

	err := doRequest("GET", fmt.Sprintf("apps/%s/deploys", appID), params, nil, &r)
	if err != nil {
		return "", err
	}

	if len(r) > 0 {
		return r[0]["build_id"], nil
	}

	return "", nil
}

func SubmitEvent(action, message, app string, meta map[string]interface{}) error {
	params := url.Values{}
	params.Set("api_key", apiKey)

	request := struct {
		Action  string                 `json:"action"`
		App     string                 `json:"eventable_id,omitempty"`
		Meta    map[string]interface{} `json:"meta"`
		Message string                 `json:"message"`
	}{
		Action:  action,
		App:     app,
		Meta:    meta,
		Message: message,
	}

	err := doRequest("POST", "events", params, map[string]interface{}{"event": request}, nil)
	if err != nil {
		return err
	}

	return nil
}

// doRequest ...
func doRequest(method, path string, params url.Values, requestBody, responseBody interface{}) error {

	var rbodyReader io.Reader

	//
	if requestBody != nil {
		jsonBytes, err := json.Marshal(requestBody)
		if err != nil {
			return err
		}
		rbodyReader = bytes.NewBuffer(jsonBytes)
	}

	auth, _ := models.LoadAuthByEndpoint(endpoint)

	// if they have not logged in but the user name and password are both set
	// use attempt to authenticate
	if auth.Key == "" &&
		os.Getenv("NANOBOX_PASSWORD") != "" &&
		os.Getenv("NANOBOX_USERNAME") != "" &&
		path != "user_auth_token" {

		auth.Key, _ = Auth(os.Getenv("NANOBOX_USERNAME"), os.Getenv("NANOBOX_PASSWORD"))
	}

	if params == nil {
		params = url.Values{}
	}
	if auth.Key != "" {
		params.Set("auth_token", auth.Key)
	}

	// fetch the correct url from the endpoint
	url := odinURL()

	//
	lumber.Debug("%s%s?%s\n", url, path, params.Encode())
	req, err := http.NewRequest(method, fmt.Sprintf("%s%s?%s", url, path, params.Encode()), rbodyReader)
	if err != nil {
		return err
	}

	req.Header.Set("Content-Type", "application/json")
	lumber.Trace("REQ: %s %s %s", req.Method, req.URL, req.Proto)

	res, err := http.DefaultClient.Do(req)
	if err != nil {
		return err
	}

	lumber.Debug("RES: %d %s %s %s (%s)", res.StatusCode, req.Method, req.URL, req.Proto, res.Header.Get("Content-Length"))

	// print the body even if status is not 2XX
	b, err := ioutil.ReadAll(res.Body)
	if err != nil {
		return err
	}

	if res.StatusCode == 401 {
		err = util.ErrorfQuiet("[USER] Unauthorized (%s)", b)
		if err != nil {
			if err2, ok := err.(util.Err); ok {
				err2.Suggest = "It appears you are not logged in, run `nanobox login` and try again"
				return err2
			}
		}
		return err
	}

	if res.StatusCode == 404 {
		err = util.ErrorfQuiet("[USER] Not Found (%s)", b)
		if err != nil {
			if err2, ok := err.(util.Err); ok {
				err2.Suggest = "It appears that app or component wasn't found, check the team/app name and try again"
				return err2
			}
		}
		return err
	}

	// if it is a 400 but not
	if res.StatusCode >= 400 && res.StatusCode < 500 {
		rb := map[string]string{}
		err = json.Unmarshal(b, &rb)
		if err != nil {
			return util.ErrorfQuiet("[NANOBOX] %s", b)
		}

		errorMessage, ok := rb["error"]
		if !ok {
			return util.ErrorfQuiet("[ODIN] %s", b)
		}
		return util.ErrorfQuiet("[ODIN] %s", errorMessage)
	}

	if res.StatusCode == 500 {
		return util.ErrorfQuiet("[ODIN] Internal Server Error (%s)", b)
	}

	if res.StatusCode < 200 || res.StatusCode >= 300 {
		return util.ErrorfQuiet("[ODIN] bad exit response(%d %s %s %s (%s) %s)", res.StatusCode, req.Method, strings.Replace(req.URL.String(), auth.Key, "REDACTED", -1), req.Proto, res.Header.Get("Content-Length"), b)
	}

	if responseBody != nil {
		lumber.Debug("response body: '%s'\n", b)
		err = json.Unmarshal(b, responseBody)
		if err != nil {
			return err
		}
	}

	return nil
}

func odinURL() string {
	switch endpoint {
	case "bonesalt":
		return BONESALT
	case "dev":
		return DEV
	case "sim":
		return SIM
	default:
		return NANOBOX
	}
}
<commit_msg>update Odin TLDs<commit_after>// Package odin ...
package odin

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"net/url"
	"os"
	"strings"

	"github.com/jcelliott/lumber"

	"github.com/nanobox-io/nanobox/commands/registry"
	"github.com/nanobox-io/nanobox/models"
	"github.com/nanobox-io/nanobox/util"
)

const (
	NANOBOX  = "https://api.nanobox.io/v1/"
	BONESALT = "https://api.bonesalt.com/v1/"
	DEV      = "http://api.nanobox.local:8080/v1/"
	SIM      = "http://api.nanobox.test/v1/"
)

var (
	// set the default endpoint to nanobox
	endpoint = "nanobox"
	apiKey   string
)

type (
	evar struct {
		ID    string `json:"id"`
		Key   string `json:"title"`
		Value string `json:"value"`
	}
)

// sets the odin endpoint
func SetEndpoint(stage string) {
	endpoint = stage
}

// Auth authenticates the user with odin.
func Auth(username, password string) (string, error) {

	loginInfo := struct {
		Slug     string `json:"slug"`
		Password string `json:"password"`
	}{username, password}

	resBody := map[string]string{}

	if err := doRequest("GET", "user_auth_token", nil, loginInfo, &resBody); err != nil {
		return "", err
	}

	return resBody["authentication_token"], nil
}

// App ...
func App(slug string) (models.App, error) {
	app := models.App{}
	var params url.Values
	if strings.Contains(slug, "/") {
		appNameParts := strings.Split(slug, "/")
		if len(appNameParts) == 2 {
			params = url.Values{}
			params.Set("ci", appNameParts[0])
			slug = appNameParts[1]
		}

	}

	return app, doRequest("GET", "apps/"+slug, params, nil, &app)
}

// Deploy ...
func Deploy(appID, id, boxfile, message string) error {

	//
	body := map[string]map[string]string{
		"deploy": {
			"boxfile_content": boxfile,
			"build_id":        id,
			"commit_message":  message,
		},
	}

	var params url.Values

	if strings.Contains(appID, "/") {
		appNameParts := strings.Split(appID, "/")
		if len(appNameParts) == 2 {
			params = url.Values{}
			params.Set("ci", appNameParts[0])
			appID = appNameParts[1]
		}

	}

	return doRequest("POST", fmt.Sprintf("apps/%s/deploys", appID), params, body, nil)
}

func ListEvars(appID string) ([]evar, error) {
	evars := []evar{}

	var params url.Values
	if strings.Contains(appID, "/") {
		appNameParts := strings.Split(appID, "/")
		if len(appNameParts) == 2 {
			params = url.Values{}
			params.Set("ci", appNameParts[0])
			appID = appNameParts[1]
		}

	}

	return evars, doRequest("GET", fmt.Sprintf("apps/%s/evars", appID), params, nil, &evars)
}

func AddEvar(appID, key, val string) error {
	body := map[string]map[string]string{
		"evar": {
			"title": key,
			"value": val,
		},
	}

	var params url.Values

	if strings.Contains(appID, "/") {
		appNameParts := strings.Split(appID, "/")
		if len(appNameParts) == 2 {
			params = url.Values{}
			params.Set("ci", appNameParts[0])
			appID = appNameParts[1]
		}

	}

	return doRequest("POST", fmt.Sprintf("apps/%s/evars", appID), params, body, nil)
}

func RemoveEvar(appID, id string) error {
	var params url.Values

	if strings.Contains(appID, "/") {
		appNameParts := strings.Split(appID, "/")
		if len(appNameParts) == 2 {
			params = url.Values{}
			params.Set("ci", appNameParts[0])
			appID = appNameParts[1]
		}

	}

	return doRequest("DELETE", fmt.Sprintf("apps/%s/evars/%s", appID, id), params, nil, nil)
}

// EstablishTunnel requests a tunnel from odin.
func EstablishTunnel(tunCfg models.TunnelConfig) (models.TunnelInfo, error) {
	r := models.TunnelInfo{Port: tunCfg.DestPort}

	params := url.Values{}
	if strings.Contains(tunCfg.AppName, "/") {
		appNameParts := strings.Split(tunCfg.AppName, "/")
		if len(appNameParts) == 2 {
			params = url.Values{}
			// ci is contextID for teams `team/app`
			params.Set("ci", appNameParts[0])
			tunCfg.AppName = appNameParts[1]
		}
	}

	err := doRequest("GET", fmt.Sprintf("apps/%s/tunnels/%s", tunCfg.AppName, tunCfg.Component), params, r, &r)
	if err != nil {
		if strings.Contains(err.Error(), "valid port") {
			if err2, ok := err.(util.Err); ok {
				err2.Suggest = "Specify a valid destination port with `-p source:destination`"
				err2.Message = err.Error()
				return r, err2
			}
		}
		if strings.Contains(err.Error(), "no default") {
			if err2, ok := err.(util.Err); ok {
				err2.Suggest = "Specify a destination port with `-p source:destination`"
				err2.Code = "USER"
				err2.Message = err.Error()
				return r, err2
			}
		}
		if strings.Contains(err.Error(), "Not Found") {
			if err2, ok := err.(util.Err); ok {
				err2.Message = fmt.Sprintf("%s - component '%s' not found on app '%s'", err.Error(), tunCfg.Component, tunCfg.AppName)
				return r, err2
			}
			err = fmt.Errorf("%s - component '%s' not found on app '%s'", err.Error(), tunCfg.Component, tunCfg.AppName)
		}
	}

	return r, err
}

// EstablishConsole ...
// protocol ssh/docker
func EstablishConsole(appID, id string) (string, string, string, error) {
	// use a default user
	params := url.Values{}
	params.Set("user", "gonano")
	if registry.GetString("console_user") != "" {
		params.Set("user", registry.GetString("console_user"))
	}

	if strings.Contains(appID, "/") {
		appNameParts := strings.Split(appID, "/")
		if len(appNameParts) == 2 {
			params.Set("ci", appNameParts[0])
			appID = appNameParts[1]
		}

	}

	r := map[string]string{}
	err := doRequest("GET", fmt.Sprintf("apps/%s/consoles/%s", appID, id), params, nil, &r)

	return r["token"], r["url"], r["protocol"], err
}

// GetWarehouse ...
func GetWarehouse(appID string) (string, string, error) {
	r := map[string]string{}

	var params url.Values
	if strings.Contains(appID, "/") {
		appNameParts := strings.Split(appID, "/")
		if len(appNameParts) == 2 {
			params = url.Values{}
			params.Set("ci", appNameParts[0])
			appID = appNameParts[1]
		}

	}

	err := doRequest("GET", fmt.Sprintf("apps/%s/services/warehouse", appID), params, nil, &r)

	return r["token"], r["url"], err
}

// GetComponent gets the token and url for a given component
func GetComponent(appID, component string) (string, string, error) {
	r := map[string]string{}

	var params url.Values
	if strings.Contains(appID, "/") {
		appNameParts := strings.Split(appID, "/")
		if len(appNameParts) == 2 {
			params = url.Values{}
			params.Set("ci", appNameParts[0])
			appID = appNameParts[1]
		}

	}

	err := doRequest("GET", fmt.Sprintf("apps/%s/services/%s", appID, component), params, nil, &r)
	// r = map["uid":"pusher1" "name":"message bus" "slug":"pusher" "url":"x.x.x.x" "token":"secret" "mode":"simple" "ip":"x.x.x.x" "id":"d371c59b-fbbc-4248-8f3b-7f694a62b5e1"]

	return r["token"], r["url"], err
}

func GetPreviousBuild(appID string) (string, error) {
	r := []map[string]string{}

	var params url.Values
	if strings.Contains(appID, "/") {
		appNameParts := strings.Split(appID, "/")
		if len(appNameParts) == 2 {
			params = url.Values{}
			params.Set("ci", appNameParts[0])
			appID = appNameParts[1]
		}

	}

	err := doRequest("GET", fmt.Sprintf("apps/%s/deploys", appID), params, nil, &r)
	if err != nil {
		return "", err
	}

	if len(r) > 0 {
		return r[0]["build_id"], nil
	}

	return "", nil
}

func SubmitEvent(action, message, app string, meta map[string]interface{}) error {
	params := url.Values{}
	params.Set("api_key", apiKey)

	request := struct {
		Action  string                 `json:"action"`
		App     string                 `json:"eventable_id,omitempty"`
		Meta    map[string]interface{} `json:"meta"`
		Message string                 `json:"message"`
	}{
		Action:  action,
		App:     app,
		Meta:    meta,
		Message: message,
	}

	err := doRequest("POST", "events", params, map[string]interface{}{"event": request}, nil)
	if err != nil {
		return err
	}

	return nil
}

// doRequest ...
func doRequest(method, path string, params url.Values, requestBody, responseBody interface{}) error {

	var rbodyReader io.Reader

	//
	if requestBody != nil {
		jsonBytes, err := json.Marshal(requestBody)
		if err != nil {
			return err
		}
		rbodyReader = bytes.NewBuffer(jsonBytes)
	}

	auth, _ := models.LoadAuthByEndpoint(endpoint)

	// if they have not logged in but the user name and password are both set
	// use attempt to authenticate
	if auth.Key == "" &&
		os.Getenv("NANOBOX_PASSWORD") != "" &&
		os.Getenv("NANOBOX_USERNAME") != "" &&
		path != "user_auth_token" {

		auth.Key, _ = Auth(os.Getenv("NANOBOX_USERNAME"), os.Getenv("NANOBOX_PASSWORD"))
	}

	if params == nil {
		params = url.Values{}
	}
	if auth.Key != "" {
		params.Set("auth_token", auth.Key)
	}

	// fetch the correct url from the endpoint
	url := odinURL()

	//
	lumber.Debug("%s%s?%s\n", url, path, params.Encode())
	req, err := http.NewRequest(method, fmt.Sprintf("%s%s?%s", url, path, params.Encode()), rbodyReader)
	if err != nil {
		return err
	}

	req.Header.Set("Content-Type", "application/json")
	lumber.Trace("REQ: %s %s %s", req.Method, req.URL, req.Proto)

	res, err := http.DefaultClient.Do(req)
	if err != nil {
		return err
	}

	lumber.Debug("RES: %d %s %s %s (%s)", res.StatusCode, req.Method, req.URL, req.Proto, res.Header.Get("Content-Length"))

	// print the body even if status is not 2XX
	b, err := ioutil.ReadAll(res.Body)
	if err != nil {
		return err
	}

	if res.StatusCode == 401 {
		err = util.ErrorfQuiet("[USER] Unauthorized (%s)", b)
		if err != nil {
			if err2, ok := err.(util.Err); ok {
				err2.Suggest = "It appears you are not logged in, run `nanobox login` and try again"
				return err2
			}
		}
		return err
	}

	if res.StatusCode == 404 {
		err = util.ErrorfQuiet("[USER] Not Found (%s)", b)
		if err != nil {
			if err2, ok := err.(util.Err); ok {
				err2.Suggest = "It appears that app or component wasn't found, check the team/app name and try again"
				return err2
			}
		}
		return err
	}

	// if it is a 400 but not
	if res.StatusCode >= 400 && res.StatusCode < 500 {
		rb := map[string]string{}
		err = json.Unmarshal(b, &rb)
		if err != nil {
			return util.ErrorfQuiet("[NANOBOX] %s", b)
		}

		errorMessage, ok := rb["error"]
		if !ok {
			return util.ErrorfQuiet("[ODIN] %s", b)
		}
		return util.ErrorfQuiet("[ODIN] %s", errorMessage)
	}

	if res.StatusCode == 500 {
		return util.ErrorfQuiet("[ODIN] Internal Server Error (%s)", b)
	}

	if res.StatusCode < 200 || res.StatusCode >= 300 {
		return util.ErrorfQuiet("[ODIN] bad exit response(%d %s %s %s (%s) %s)", res.StatusCode, req.Method, strings.Replace(req.URL.String(), auth.Key, "REDACTED", -1), req.Proto, res.Header.Get("Content-Length"), b)
	}

	if responseBody != nil {
		lumber.Debug("response body: '%s'\n", b)
		err = json.Unmarshal(b, responseBody)
		if err != nil {
			return err
		}
	}

	return nil
}

func odinURL() string {
	switch endpoint {
	case "bonesalt":
		return BONESALT
	case "dev":
		return DEV
	case "sim":
		return SIM
	default:
		return NANOBOX
	}
}
<|endoftext|>